
//Debug Window Support
var debugWindowContent = "";
var debugMsgCount = 0;
function logMessage(msg, msgType){
  var tempContent = "";
  if (debugMsgCount > 15) {
    debugWindowContent = ""; //only save 15 logging messages at a time;
    debugMsgCount = 0;
  }
  var timeStamp = new Date();
  if (msgType == "request") {
    tempContent += '<table width="100%" border="0" cellspacing="2" cellpadding="2" style="background-color:#c1edbd"><tr>';
  } else {
    tempContent += '<table width="100%" border="0" cellspacing="2" cellpadding="2" style="background-color:#b3c9e9"><tr>';
  }
  tempContent += '<td align="center" style="font-family:Verdana, Arial, Helvetica, sans-serif; color:#000000; font-size:10px">';
  if (msgType == "request") {
    tempContent += 'Request - Timestamp: ';
  } else {
    tempContent += 'Response - Timestamp: ';
  }
  tempContent += timeStamp;
  tempContent += '</td></tr><tr><td align="center"><textarea cols="120" rows="10" style="font-family:Verdana, Arial, Helvetica, sans-serif; color:#000000; font-size:10px; border:solid 1px #666666">';
  tempContent += msg;
  tempContent += '</textarea></td></tr></table>';
  debugWindowContent = tempContent + debugWindowContent;
  debugMsgCount++;
}

//Keystroke Capture for Debugging and Timing
function agCheckKey(evt){
if (document.all){
  if (event.ctrlKey && (event.keyCode == 29)) doDebugLogging();
  if (event.ctrlKey && (event.keyCode == 27)) displayTimingData();
}else if (document.getElementById){
  if (evt.ctrlKey && (evt.which == 93)) doDebugLogging();
  if (evt.ctrlKey && (evt.which == 91)) displayTimingData();
}
}

var agDebugWindow = null;
function doDebugLogging(){
  agDebugWindow = window.open("","","height=400,width=800,location=no,toolbar=no,menubar=no,status=no,resize=yes,scrollbars=yes", true);
  agDebugWindow.document.write(debugWindowContent);
}

//Hover Popup Support
var latestHoveredDivId = "";
var hoverPopArray = new Array();
function doHoverPopMouseOver(div, href){
  var tempArray = new Array();
  tempArray["href"] = href;
  tempArray["pop"]= true;
  hoverPopArray[div.id] = tempArray;
  window.setTimeout('showHoverPop("'+div.id+'")', AGHOVERPOPUPDELAY);

}
function doHoverPopMouseOut(div){
  hoverPopArray[div.id]["pop"] = false;
}
function showHoverPop(divId){
 if (hoverPopArray[divId]["pop"] == true) {
    var hoverDiv = document.getElementById(divId);
    var closestSubmitNode = _findClosestSubmit(hoverDiv, null);
    if (closestSubmitNode) {
      closestSubmitNode.onclick();
      latestHoveredDivId = divId;
    }
    return false;
  }
}

//Lookup Field Callback
var lastLookupFieldID = null;
function insertLookupValue(lookupValue){
  if (lastLookupFieldID != null) {
    var inputToFill = document.getElementById(lastLookupFieldID);
    if (inputToFill != null) {
      inputToFill.value = lookupValue;
    }
  } else {
   return;
  }
}

//Form Validation

//method for parsing the OID of a given object
function getOID(value) {
  var a = value.split(':');
  var oidString = a[a.length-1];
  var oid = oidString.split('~');
  return oid;
}

//determine whether a given input is related to a given action
function isActionInput(operationOIDString, inputOIDString) {
  var operationOIDElements = getOID(operationOIDString)
  var inputOIDElements = getOID(inputOIDString)
  return (operationOIDElements[1] == inputOIDElements[1] && operationOIDElements[2] == inputOIDElements[2]) 
}

var detailFormIsDirty = false;
var numberOfErrors = 0;
var numberOfInputs = 0;
var formSubmitCalls = new  Array();
var formSubmitCallCount = 0;

function agValidateForm(strActionOID){
	numberOfErrors = 0;
	strActionOID = strActionOID.replace(/%3A/g,":");
	strActionOID = strActionOID.replace(/%7E/g,"~");
	for (inputOID in formSubmitCalls) {
		if (isActionInput(strActionOID, inputOID)){
			eval(formSubmitCalls[inputOID]);
		}
	}
  if(numberOfErrors>0) {
  	//there were validation errors on the form, they are displayed
    return false;
  }else{ 
    //there were no errors on the form, reset form submit calls
    agClearSubmitCalls(strActionOID);
    return true;
  }
}

//clears submit calls for a given submit after it has passed validation
function agClearSubmitCalls(strActionOID){
	for (inputOID in formSubmitCalls) {
		if (isActionInput(strActionOID, inputOID)){
			formSubmitCalls[inputOID] = null;
		}
	}
}

function addFormSubmitCall(call, oid) { 
	formSubmitCalls[oid] = call;
}

function displayError(divid, message){
  if(document.getElementById(divid) != null){
	var inputid = divid;
	var labelid = divid + "_label";
	var innerid = divid + "_inner";
	var containerid = divid + "_container";
	document.getElementById(inputid).className = "agTextInputError";
	document.getElementById(labelid).className = "agTextLabelError";
	document.getElementById(containerid).className = "errorMsgDiv";
	var currentInputValue = document.getElementById(inputid).value;
	var currentDivValue = document.getElementById(innerid).innerHTML;
	var newDivValue = "<div id='" + innerid + "'>" + currentDivValue + "</div>" + message;
	document.getElementById(containerid).innerHTML = newDivValue;
	document.getElementById(inputid).value = currentInputValue;
  }
}

function clearError(divid){
	
	var inputid = divid;
	var labelid = divid + "_label";
	var innerid = divid + "_inner";
	var containerid = divid + "_container";
	document.getElementById(inputid).className = "agTextInput";
	document.getElementById(labelid).className = "agTextLabel";
	document.getElementById(containerid).className = "";
	var currentInputValue = document.getElementById(inputid).value;
	var originalDivValue = document.getElementById(innerid).innerHTML;
	var newDivValue = "<div id='" + innerid + "'>" + originalDivValue + "</div>";
	document.getElementById(containerid).innerHTML = newDivValue;
	document.getElementById(inputid).value = currentInputValue;
}

var errorHistory = new Array();

function regExCheckValue(validationExpression, divid, message) {
	var formElement = document.getElementById(divid);
	if (formElement != null) {
    var formValue = document.getElementById(divid).value;
    var re = validationExpression;
    if (formValue.match(re)) {
      //matched, remove error
      if (errorHistory[divid]) {
      	clearError(divid);
      	errorHistory[divid] = false;
      }
    } else {
      //did not match
    	displayError(divid, message);
    	errorHistory[divid] = true;
    	numberOfErrors++;
    }
  }
}

function agSetError(inputID, message){
	displayError(inputID, message);
	errorHistory[inputID] = true;
	numberOfErrors++;
}

function agClearError(inputID){
	errorHistory[inputID] = false;
	clearError(inputID);
}

function isInErrorState(inputID){
	if ( errorHistory[inputID] ) return true;
	else return false;
}

//Server-Side Form Field Validation Support

var serverSideValidationErrors = new Array();

function clearOldServerErrors(){
	for (serverError in serverSideValidationErrors) {
		if (document.getElementById(serverError)){
			clearError(serverError);
		}
	}
}

function displayFieldErrors(xmlDoc){
	clearOldServerErrors();
  var errorNodes = xmlDoc.selectNodes("/AJAXIncludeXFormResponse/errors/fieldErrors/field");
  if (errorNodes.length > 0) {
	  for (var i=0; i<errorNodes.length; i++) {
	    oid = Sarissa.getText(errorNodes[i].selectSingleNode("oid"), false);
	    msg = Sarissa.getText(errorNodes[i].selectSingleNode("msg"), false);
	    if (document.getElementsByName(oid)[0] != null) {
	      var fieldId = document.getElementsByName(oid)[0].id;
	      displayError(fieldId, msg);
	      serverSideValidationErrors[fieldId] = true;
	    }
	  }
	}
	
  hideLoadingDiv();
}

//Error and Loading Div Placement
//keep the error and loading divs at the top of the viewport, not the window area
//if (REPOSITION_MESSAGES) window.setTimeout('divPositionCheck()',200);
function divPositionCheck(){
  if(document.getElementById('loadingDiv')){
    if (window.scrollY) {
      document.getElementById('loadingDiv').style.top = window.scrollY + 'px';
    } else {
      document.getElementById('loadingDiv').style.top = '0px';
    }
    if (document.body.parentNode.scrollTop) document.getElementById('loadingDiv').style.top = document.body.parentNode.scrollTop + 'px';
  }
  if(document.getElementById('pageErrorDiv')){
    if (window.scrollY){
      document.getElementById('pageErrorDiv').style.top = window.scrollY + 'px';
    } else {
      document.getElementById('pageErrorDiv').style.top = '0px';
    }
    if (document.body.parentNode.scrollTop) document.getElementById('pageErrorDiv').style.top = document.body.parentNode.scrollTop + 'px';
  }
  agPositionTimeout = window.setTimeout('divPositionCheck()',50);
}

//Session Expiration Message Support
function sessionExpired(){
  document.getElementById("timeoutDiv").style.display = 'block';
  refreshCountdown(2400);
  //window.location.href = document.forms.masterForm.action;
}

function refreshCountdown(milsecs){
  if (milsecs == 0) {
    window.location.href = document.forms.masterForm.action;
  } else {
    milsecs = milsecs - 800;
    secs = milsecs / 800;
    document.getElementById("timeoutSecs").innerHTML = secs;
    window.setTimeout("refreshCountdown("+milsecs+")",milsecs);
  }
}

//Page Error and Messaging Display Support
function displayPageErrors(xmlDoc){
  var errorNodes = xmlDoc.selectNodes("/AJAXIncludeXFormResponse/errors/pageErrors/item");
  if (errorNodes.length > 0) {
	  var errorDivContent = '';
	  for (var i=0; i<errorNodes.length; i++){
	    if (Sarissa.getText(errorNodes[i]) == 'Session has expired.  Please refresh the page') {
	      sessionExpired();
	      return;
	    }
	  }
	  for (var i=0; i<errorNodes.length; i++){
	    errorDivContent += '<table width="100%" cellspacing="2" cellpadding="0" border="0"><tr><td class="agPageErrorText">' + Sarissa.getText(errorNodes[i]) + '</td></tr></table>';
	  }
	  var pageErrorDiv = document.getElementById("pageErrorDivContents");
	  pageErrorDiv.innerHTML = errorDivContent;
	  var pageErrorContainerDiv = document.getElementById("pageErrorDiv");
	  if (SHOW_ERRORS) pageErrorContainerDiv.style.visibility = 'visible';
	}
	hideLoadingDiv();
}

function displayClientSideErrors(errorString){
  var errorDivContent = "";
  errorDivContent = '<table width="100%" cellspacing="2" cellpadding="0" border="0"><tr><td class="agPageErrorText">' + errorString + '</td></tr></table>';
  var pageErrorDiv = document.getElementById("pageErrorDivContents");
  pageErrorDiv.innerHTML = errorDivContent;
  var pageErrorContainerDiv = document.getElementById("pageErrorDiv");
  if (SHOW_ERRORS) pageErrorContainerDiv.style.visibility = 'visible';
  hideLoadingDiv();
}

function hidePageErrors(){
  document.getElementById("pageErrorDivContents").innerHTML = '';
  document.getElementById("pageErrorDiv").style.visibility = 'hidden';

}

function closePopupOnClick(){
	document.getElementById('agPopupContainer').style.visibility='hidden';
	document.getElementById('agPopup').innerHTML='';
}

var closePopupFlag = false;

function masterClosePopup(){
	closePopupFlag = true;
}


//Timing and Performance Tuning Support
var timeRequestSent;
var timeResponseReceived;
var timePageRenderStart;
var timePageRenderCSSStart;
var timePageRenderCSSDoneRemoving;
var timePageRenderCSSDoneParsing;
var timePageRenderContentStart;
var timePageRenderHeadStart;
var timePageRenderComplete;
var numberOfCSSRules = 0;
var numberOfCSSNodes = 0;

function getTimingDataForRequest(){
	if ((timeRequestSent) && (timeResponseReceived)){
		if (timeResponseReceived.getTime() < timeRequestSent.getTime()){
			//last response was not to most recent request
			return "LAST_REQUEST_ABANDONED"
		}else{
			return "LAST_RESPONSE_TIME: " + (timeResponseReceived.getTime() - timeRequestSent.getTime()) + 'ms';
		}
	}else{
		return "NO_TIMING_DATA_AVAILABLE";
	}
}

function getTimingDataForPageGen(){
	if ((timePageRenderStart) && (timePageRenderComplete)){
		if (timePageRenderComplete.getTime() < timePageRenderStart.getTime()){
			//last response was not to most recent request
			return "PAGE_GENERATION_INCOMPLETE"
		}else{
			return "PAGE_GENERATION_TIME: " + (timePageRenderComplete.getTime() - timePageRenderStart.getTime()) + 'ms';
		}
	}else{
		return "NO_TIMING_DATA_AVAILABLE";
	}
}

function displayTimingData(){
  var timingString = "";
  if ((timeRequestSent.getTime()) && (timeResponseReceived.getTime())){
    timingString += "Request/Response Time: " + (timeResponseReceived.getTime() - timeRequestSent.getTime()) + "ms \n";
  }
  if ((timeResponseReceived.getTime()) && (timePageRenderStart.getTime())){
    timingString += "Response Received to Page Render Start Time: " + (timePageRenderStart.getTime() - timeResponseReceived.getTime()) + "ms \n";
  }
  if ((timePageRenderStart.getTime()) && (timePageRenderCSSStart.getTime())){
    timingString += "Page Render Start to Start of CSS Import Time: " + (timePageRenderCSSStart.getTime() - timePageRenderStart.getTime()) + "ms \n"
  }
  if ((timePageRenderCSSStart.getTime()) && (timePageRenderCSSDoneRemoving.getTime())){
    timingString += "CSS Cleanup Time: " + (timePageRenderCSSDoneRemoving.getTime() - timePageRenderCSSStart.getTime()) + "ms \n"
  }
  if ((timePageRenderCSSDoneRemoving.getTime()) && (timePageRenderCSSDoneParsing.getTime())){
    timingString += "CSS Parsing Time: " + (timePageRenderCSSDoneParsing.getTime() - timePageRenderCSSDoneRemoving.getTime()) + "ms \n"
  }
  if ((timePageRenderCSSDoneParsing.getTime()) && (timePageRenderContentStart.getTime())){
    timingString += "CSS Import Time: " + (timePageRenderContentStart.getTime() - timePageRenderCSSDoneParsing.getTime()) + "ms \n"
  }
  if ((timePageRenderContentStart.getTime()) && (timePageRenderHeadStart.getTime())){
    timingString += "Content Render Time: " + (timePageRenderHeadStart.getTime() - timePageRenderContentStart.getTime()) + "ms \n"
  }
  if ((timePageRenderHeadStart.getTime()) && (timePageRenderComplete.getTime())){
    timingString += "Head Render Time: " + (timePageRenderComplete.getTime() - timePageRenderHeadStart.getTime()) + "ms \n"
  }
  timingString += "Number of CSS Rules Added: " + numberOfCSSRules + " \n";
  timingString += "Number of CSS Nodes In Response: " + numberOfCSSNodes + " \n";
  alert(timingString);
}

//Server-Side Error Handling
function handleServerErrorResponses(errorCode){
  switch(errorCode){
    case 404:
      displayClientSideErrors('The server could not be located. Please try again later. Error 404');
    break;
    case 401:
      displayClientSideErrors('The server authentication failed. Please try again later. Error 401');
    break;
    case 403:
      displayClientSideErrors('The server refused the connection. Please try again later. Error 403');
    break;
    case 500:
      displayClientSideErrors('There was an internal server error. Please try again later. Error 500');
    break;
    case 503:
      displayClientSideErrors('The server was unable to respond because it was busy or unavailble. Please try again later. Error 503');
    break;
    case 504:
      displayClientSideErrors('The server timed out. Please try again later. Error 504');
    break;
    default: displayClientSideErrors('There was an error on the server. Please try again later. Error code: '+ errorCode);
  }
}


/////////////////////////////////////////////////////////
//
//    Form Submission Code
//
/////////////////////////////////////////////////////////

//Serializes Form Data Into a Parameter String
function createParameterString(){
  form = document.forms.masterForm
  formElements = form.elements;
  var parameters = "";
  for (var i=0; i<formElements.length; i++){
    var elementType = formElements[i].type;
    switch(elementType){
      case 'checkbox':
        if (formElements[i].checked) parameters += encodeURIComponent(formElements[i].name) + "=" + encodeURIComponent(formElements[i].value) + "&";
      break;
      case 'radio':
        if (formElements[i].checked) parameters += encodeURIComponent(formElements[i].name) + "=" + encodeURIComponent(formElements[i].value) + "&";
      break;
      case 'select-one':
        if (formElements[i].selectedIndex != -1) parameters += encodeURIComponent(formElements[i].name) + "=" + encodeURIComponent(formElements[i].value) + "&";
      break;
      case 'select-multiple':
        options = formElements[i].options;
        optionsLength = options.length;
        for (var optionIndex=0;optionIndex < optionsLength; optionIndex++) {
          currentOption = options[optionIndex];
          if (currentOption.selected) {
            parameters += encodeURIComponent(formElements[i].name) + "=" + encodeURIComponent(currentOption.value) + "&";
          }
        }
      break;
      case 'button':
      break;
      case 'image':
      break;
      case 'submit':
      break;
      case 'reset':
      break;
      default:
        escapeVal = encodeURIComponent(formElements[i].value);
        if (!ISFIREFOX) {
            escapeVal = escapeVal.replace(/%0D%0A/g, '%0A');
        }
        parameters += encodeURIComponent(formElements[i].name) + "=" + escapeVal + "&";
    }
  }
  return parameters;
}

//Wrapper method to submit a form using standard, non-ajax submit, targeting a new window with the result
function agNewWindowSubmit(href) {
    hidePageErrors();
    form = document.forms.masterForm
    qindex = href.indexOf("?")
    if (qindex >= 0) {
        qstring = href.substring(qindex+1)
        separator = '?'
        if (form.action.indexOf('?') >=0) {
            separator = '&'
            }
        hrefAction = form.action + separator + qstring
    }
    if (agValidateForm(href)) {
        preSubmit(form)
        agNewWindowPOST(hrefAction)
    }
    return false;
}

//Post the form data to a new window using standard, non-ajax submit
function agNewWindowPOST(action) {
    var form = document.forms.masterForm;
    var oldtarget=form.target;
    var oldaction=form.action;

    form.target='_blank';
    form.action=action;

    form.submit();

    form.target=oldtarget;
    form.action=oldaction;
}


function createXHR() {
    var xmlHttpRequest = null;
    if (window.XMLHttpRequest) { // Mozilla, Safari,...
        xmlHttpRequest = new XMLHttpRequest();
        if (xmlHttpRequest.overrideMimeType) {
            xmlHttpRequest.overrideMimeType('text/xml');
        }
    } else if (window.ActiveXObject) { // IE
        try {
            xmlHttpRequest = new ActiveXObject("Msxml2.XMLHTTP");
        } catch (e) {
            xmlHttpRequest = new ActiveXObject("Microsoft.XMLHTTP");
        }
    }
    if (!xmlHttpRequest) {
        displayClientSideErrors('Cannot create XMLHTTP instance');
        return null;
    }
    return xmlHttpRequest;
}


//Core AJAX Request Method
var agHttpRequest = createXHR();
function agAJAXPost(url, parameters, callBackFunction) {
    logMessage("url: " + url+ "  parameters: " +parameters, "request");
    agHttpRequest.open('POST', url, true);
    agHttpRequest.onreadystatechange = callBackFunction;
    agHttpRequest.setRequestHeader("Content-type", "application/x-www-form-urlencoded; charset=utf-8");
    agHttpRequest.setRequestHeader("Content-length", parameters.length);
    agHttpRequest.setRequestHeader("client-request-timing", getTimingDataForRequest());
    agHttpRequest.setRequestHeader("client-pagegen-timing", getTimingDataForPageGen());
    agHttpRequest.send(parameters);
    timeRequestSent = new Date();
}


//IFrame-based, non-ajax submit for file upload
function agIframePOST(form, action) {
    showUploadingDiv();
    var oldtarget=form.target;
    var oldenctype=form.enctype;
    var oldencoding=form.encoding;
    var oldaction=form.action;

    form.enctype='multipart/form-data';
    form.encoding=form.enctype;
    form.target='agIframePOSTFrame';
    form.action=action;

    var itag=document.createElement('input');
    itag.type='hidden';
    itag.name='agIframePOST';
    itag.value='TRUE';
    form.appendChild(itag);
    form.submit();

    form.target=oldtarget;
    form.enctype=oldenctype;
    form.encoding=oldencoding;
    form.action=oldaction;
    form.removeChild(itag);
}

//Determine whether a response that could not parse is HTML
function agIsResponseHTML(responseAsText){
  var responseString = new String(responseAsText);
  if (responseString.match(/\<HTML\>/gi)) {
    return true;
  } else {
    return false;
  }
}

//Callback for file upload
function agAJAXHandleXML(xmlAsText) {
    logMessage(xmlAsText, "response");
    var xmlDoc = (new DOMParser()).parseFromString(xmlAsText, "text/xml");
    if (xmlDoc.parseError != 0){
        displayClientSideErrors(Sarissa.getParseErrorText(xmlDoc));
    } else {
        if ((xmlDoc.selectNodes("/AJAXIncludeXFormResponse/errors/pageErrors/item").length > 0) || (xmlDoc.selectNodes("/AJAXIncludeXFormResponse/errors/fieldErrors/field").length > 0)) {
            //there were errors, display them
            displayPageErrors(xmlDoc);
            displayFieldErrors(xmlDoc);
        } else if (xmlDoc.selectNodes("/AJAXIncludeXFormResponse/include").length == 0) {
            //there are no includes
            if(agIsResponseHTML(xmlAsText) && REFRESH_ON_HTML){
              //it was html, refresh
              window.location.href = document.forms.masterForm.action;
              //document.write(xmlAsText);
            } else {
              //it was something else
              displayClientSideErrors('There was an error on the server that resulted in an invalid response.');
            }
        } else {
            generatePage(xmlDoc);
            if (BACK_BUTTON_SUPPORT) createHashHistoryEntry(xmlDoc, false);
        }
    }
    hideUploadingDiv();
}

//Standard AJAX Callback Method
function agAJAXCallbackReplace() {
    if(agHttpRequest.readyState == 4) {
        if ((agHttpRequest.status >= 200) & (agHttpRequest.status < 300)) {
            timeResponseReceived = new Date();
            agAJAXHandleXML(agHttpRequest.responseText);
            hideLoadingDiv();
        } else {
            timeResponseReceived = new Date();
            handleServerErrorResponses(agHttpRequest.status);
            logMessage(agHttpRequest.responseText, "response");
            hideLoadingDiv();
        }
    }
    if(agHttpRequest.readyState == 3) {
    }
}

//Wrapper method for retrieving the next page
function getDivContents(url){
  showLoadingDiv();
  var parameters = createParameterString();
  agAJAXPost(url, parameters,agAJAXCallbackReplace);
}


/////////////////////////////////////////////////////////
//
//    Page Generation Code
//
/////////////////////////////////////////////////////////

//Standard method for taking parsed response and triggering page generation
function generatePage(xmlDoc){
  timePageRenderStart = new Date();
  try{
	  //determine whether this is a full response or a paginating one
	  if (xmlDoc.selectSingleNode("/AJAXIncludeXFormResponse/@fragmentID")){
	    //paginating, just replace page
	    var targetDivID = Sarissa.getText(xmlDoc.selectSingleNode("/AJAXIncludeXFormResponse/@fragmentID"));
	    var sourceDocNode = xmlDoc.selectSingleNode("/AJAXIncludeXFormResponse/include");
	    //replace page fragment contents, not head or css
	    replaceDiv(targetDivID, sourceDocNode, false, false);
	  } else {
	    //full, replace all ajaxframes
	    var sourceDocNodes = xmlDoc.selectNodes("/AJAXIncludeXFormResponse/include");
	      for (var i=0; i<sourceDocNodes.length; i++){
	        var sourceDocNode = sourceDocNodes[i]
	        targetDivID = Sarissa.getText(sourceDocNode.selectSingleNode("@includeID"))
	        //replace page fragment contents, head, and css
	        replaceDiv(targetDivID, sourceDocNode, true, true);
	      }
	  }
	}catch(err){
		displayClientSideErrors('There was a javascript error on page generation that prevented the page from displaying correctly. Please try again. If this problem persists, please contact your application administrator.');
	}
  timePageRenderComplete = new Date();
  hideLoadingDiv();
}

//Wrapper method for separating out each stylesheet section from the response
function createNewStyleSheet(includeNode){
  var newStyleSheet = "";
  cssNodes = includeNode.selectNodes("css")
  for (var i=0; i<cssNodes.length; i++) {
    newStyleSheet += Sarissa.getText(cssNodes[i]);
  }
  return newStyleSheet;
}

//Main page generation method, takes a single ajaxframes content as input
var styleSheetArray = new Array();
function replaceDiv(divID, includeNode, replaceHead, replaceCSS){
  if (document.getElementById(divID+"_onunload")){
    if (document.getElementById(divID+"_onunload").innerText) eval(document.getElementById(divID+"_onunload").innerText);
  }
  if (closePopupFlag) {
  	document.getElementById('agPopupContainer').style.visibility='hidden';
		document.getElementById('agPopup').innerHTML='';
		closePopupFlag = false;
  }
  timePageRenderCSSStart = new Date();
  if (replaceCSS) {
    //remove any old stylesheets from the body
    var oldStyleSheet = document.getElementById(divID + "_style");
    if (oldStyleSheet) oldStyleSheet.parentNode.removeChild(oldStyleSheet);
    //add the stylesheet to the body
    var newStyleSheet = createNewStyleSheet(includeNode);
    if (!document.createStyleSheet){
    	timePageRenderCSSDoneRemoving = new Date();
      timePageRenderCSSDoneParsing = new Date();
    } else {
      //if a stylesheet for this include does not exist, create it. otherwise clear out the old one
      if (!styleSheetArray[divID]) {
        styleSheetArray[divID] = document.createStyleSheet();
      } else {
        var SSRulesLength = styleSheetArray[divID].rules.length;
        for (var i=0; i<SSRulesLength; i++){
          styleSheetArray[divID].removeRule();
        }
      }
      timePageRenderCSSDoneRemoving = new Date();
      //build array of rules
      numberOfCSSRules = 0;
      cssNodes = includeNode.selectNodes("css")
      numberOfCSSNodes = cssNodes.length;
      for (var i=0; i<cssNodes.length; i++) {
        var mystring = new String(Sarissa.getText(cssNodes[i]));
        var cssPairs = new Array();
        var startingIndex = 0;
        var openRuleIndex = mystring.indexOf('{',startingIndex);
        var closeRuleIndex = 0;
        var moreRules = true;
        for(var j=0; moreRules; j++){
          moreRules = false;
          openRuleIndex = mystring.indexOf('{',startingIndex);
          if (openRuleIndex != -1) {
            closeRuleIndex = mystring.indexOf('}',openRuleIndex);
            if (closeRuleIndex != -1) {
              var tempArray = new Array();
              tempArray["selector"] = mystring.substring(startingIndex,openRuleIndex);
              tempArray["selector"] = tempArray["selector"].replace(/$/g,"");
              tempArray["selector"] = tempArray["selector"].replace(/\t/g,"");
              tempArray["selector"] = tempArray["selector"].replace(/\n/g,"");
              tempArray["selector"] = tempArray["selector"].replace(/<!--/g,"");
              tempArray["selector"] = tempArray["selector"].replace(/-->/g,"");
              tempArray["rule"] = mystring.substring(openRuleIndex+1,closeRuleIndex);
              startingIndex = closeRuleIndex + 1;
              cssPairs[j] = tempArray;
              moreRules = true;
            }else{
              displayClientSideErrors("Missing } in layout CSS");
            }
          }
        }
        numberOfCSSRules += cssPairs.length;
        timePageRenderCSSDoneParsing = new Date();
        //add the rules to stylesheet for this include
        for (var n=0; n<cssPairs.length; n++){
          styleSheetArray[divID].addRule(cssPairs[n]["selector"],cssPairs[n]["rule"]);
        }
      }
    }
  } else {
    timePageRenderCSSDoneRemoving = new Date();
    timePageRenderCSSDoneParsing = new Date();
  }
  timePageRenderContentStart = new Date();
//add the content to the div
  var newContent ="";
  if (!document.createStyleSheet) newContent += "<style>" + newStyleSheet + "</style>";
  newContent += Sarissa.getText(includeNode.selectSingleNode("body"));
  newContent = newContent.replace(/\<\!\[CDATA\[/g,"");
  newContent = newContent.replace(/\]\]\>/g,"");
  targetDiv = document.getElementById(divID);
  if (targetDiv == null) {
    displayClientSideErrors("You have targeted a non-existant AJAXFrame. Please modify the target of the button or link you just clicked.")
  }
  targetDiv.innerHTML = null;
  targetDiv.innerHTML = newContent;
  targetDiv.style.display = "block";
  timePageRenderHeadStart = new Date();
//add the head to the head
  if (replaceHead) {
    var newHeadContent = "";
    if (includeNode.selectSingleNode('head')) newHeadContent = Sarissa.getText(includeNode.selectSingleNode("head"));
    newHeadContent = newHeadContent.replace(/\<script.*\>/g,"");
    newHeadContent = newHeadContent.replace(/\<\/script\>/g,"");
    if (newHeadContent != ""){
      if(document.scripts){
       if(document.scripts[divID+"_head"]) document.scripts[+"_head"] = null;
      }
      var newHeadNode = document.createElement("script");
      newHeadNode.type="text/javascript";
      newHeadNode.text=newHeadContent;
      newHeadNode.id= divID + "_head";
      document.getElementsByTagName("head")[0].appendChild(newHeadNode);
    }
  }
  if (divID == "agPopup"){
    //this is a popup, show it
    var popup = document.getElementById("agPopupContainer");
    var popupWidth = document.getElementById("agPopup").clientWidth;
    if (ISFIREFOX){
      var hiddenDiv = document.getElementById("hiddenPopupSupport");
      hiddenDiv.innerHTML = newContent;
      popup.style.width = hiddenDiv.clientWidth + "px";
      document.getElementById("agPopup").width = (hiddenDiv.clientWidth + 10) + "px";
      hiddenDiv.innerHTML = "";
    }else{
      popup.style.width = popupWidth + "px";
    }
    popup.style.top = AGPOPUPTOP; //'$agPopupTop';
    popup.style.left = AGPOPUPLEFT; //'$agPopupLeft';
    popup.style.visibility = 'visible';
  } else {
  	//clear the popup contents so they don't get submitted again
  	//document.getElementById("agPopup").innerHTML = "";
  }
  if (divID == "agHoverPopup"){
    //this is a hover popup, show it
    var popup = document.getElementById("agHoverPopupContainer");
    //figure out where to put the hover popup, and show it
    var openerDiv = document.getElementById(latestHoveredDivId);
    var currentDiv = openerDiv;
    var agOffsetTop = 0;
    var agOffsetLeft = 0;
    agOffsetTop += currentDiv.offsetTop;
    agOffsetLeft += currentDiv.offsetLeft;
    while (currentDiv.offsetParent.tagName != 'BODY'){
    	agOffsetTop += currentDiv.offsetTop;
    	agOffsetLeft += currentDiv.offsetLeft;
    	currentDiv = currentDiv.offsetParent;
    }
    if (ISFIREFOX){
    	popup.style.top = agOffsetTop - popup.clientHeight + 10;
    }else{
    	popup.style.top = agOffsetTop - popup.clientHeight;
    }
    popup.style.left = agOffsetLeft + 10;
    popup.style.visibility = 'visible';
    popup.style.display = 'block';
    popup.focus();
  }
  //handle inline script
  var scriptNodes = targetDiv.getElementsByTagName("script");
  var scriptNodesLength = scriptNodes.length;
  for (var i=0; i<scriptNodesLength; i++){
    var newScriptNode = document.createElement('script');
    newScriptNode.type = "text/javascript";
    newScriptNode.text = scriptNodes[i].text;
    targetDiv.appendChild(newScriptNode);
  }
  if (document.getElementById(divID+"_onload")){
    if (document.getElementById(divID+"_onload").innerText) eval(document.getElementById(divID+"_onload").innerText);
  }
}

/////////////////////////////////////////////////////////
//
//    END Page Generation Code
//
/////////////////////////////////////////////////////////

//Miscelaneous helper methods for showing/hiding loading messages
var agPositionTimeout;
function showLoadingDiv(){
  document.getElementById('loadingDiv').style.visibility='visible';
  if (REPOSITION_MESSAGES) agPositionTimeout = window.setTimeout('divPositionCheck()',50);
}

function hideLoadingDiv(){
  document.getElementById('loadingDiv').style.visibility='hidden';
  if (REPOSITION_MESSAGES) window.clearTimeout(agPositionTimeout);
}

function showUploadingDiv(){
  document.getElementById('uploadingDiv').style.visibility='visible';
  if (REPOSITION_MESSAGES) agPositionTimeout = window.setTimeout('divPositionCheck()',50);
}

function hideUploadingDiv(){
  document.getElementById('uploadingDiv').style.visibility='hidden';
  if (REPOSITION_MESSAGES) window.clearTimeout(agPositionTimeout);
}

function windowYScroll(Ycoord){
  if (Ycoord!=""){
    window.scroll(0,Ycoord);
  }
}

/////////////////////////////////////////////////////////
//
//    Back Button Support
//
/////////////////////////////////////////////////////////


//Initialize browser-specific variables
var detect = navigator.userAgent.toLowerCase();
if(detect.indexOf("msie")>-1) document.iframesfix = true;
var uiState = new Array();
var historyStack = new Array();
var historyStackCounter = 0;

//Method for creating an entry in the history cache
function createHashHistoryEntry(xmlDoc, isFragment){
  var date = new Date();
  var historyObject = new Array();
  historyObject['xmlDoc'] = xmlDoc;
  hashId = "hid" + '_' + date.getMilliseconds();
  uiState[hashId] = historyObject;

  //save history in an indexed stack, saving whether it is a fragment or not
  historyStackCounter++;
  var historyReference = new Array();
  historyReference['hashid'] = hashId;
  historyReference['isFragment'] = isFragment;
  historyStack[historyStackCounter] = historyReference;
  if (historyStackCounter > 20) {
  	historyStack[historyStackCounter-20] = null;
  }

  if (document.iframesfix){
    //IE
    var oNewDoc = document.getElementById('ajaxHistoryFrame').contentWindow.document.open("text/html",false);
    var sMarkup = "<HTML><HEAD><TITLE>ActiveGrid</TITLE></HEAD><BODY>" + hashId + "</BODY></HTML>";
    oNewDoc.write(sMarkup);
    oNewDoc.close();
  }else{
    //Everything else
    window.location.hash = hashId;
  }
  setTimeout("startHistoryPolling()", 200);
}

//Method used when most recent history cache entry is a page fragment, to go back to the last full request and recreate the page in full
function getMostRecentFullRequest(stackID){
    if (!historyStack[stackID]['isFragment']) {
      return historyStack[stackID]['hashid'];
    } else {
      stackID--;
      return getMostRecentFullRequest(stackID)
    }
}

//Method to load a history entry from the cache to the current page - uses standard page generation
function loadParticularHistoryEvent(eventID, stackID){
  if(eventID){
    if (historyStack[stackID]['isFragment']){
      lastFullRequestID = getMostRecentFullRequest(stackID);
      if (lastFullRequestID != null){
        var lastFullXMLDoc = uiState[lastFullRequestID]['xmlDoc'];
        generatePage(lastFullXMLDoc);
        var xmlDoc = uiState[eventID]['xmlDoc'];
        generatePage(xmlDoc);
      }
    } else {
      var xmlDoc = uiState[eventID]['xmlDoc'];
      generatePage(xmlDoc);
    }
  }
}

//Poll to check to see whether the back button has been pressed
var hashId = "";
function startHistoryPolling(){
  if (document.iframesfix){   //IE
    if (document.getElementById('ajaxHistoryFrame').contentWindow.document.body.innerHTML){
      var currentIframeBody = document.getElementById('ajaxHistoryFrame').contentWindow.document.body.innerHTML;
      if(currentIframeBody != hashId){
        historyStackCounter--;
        loadParticularHistoryEvent(currentIframeBody,historyStackCounter);
        hashId = currentIframeBody;
      }
    }
  }else{
    //Firefox, et all
    if (window.location.hash){
      var currentHashLoc = window.location.hash.replace(/#/g,"");
      if(currentHashLoc != hashId){
        historyStackCounter--;
        loadParticularHistoryEvent(currentHashLoc,historyStackCounter);
        hashId = currentHashLoc;
       }
    }
  }
  setTimeout("startHistoryPolling()", 200);
}

/////////////////////////////////////////////////////////
//
//    Form Submission Helper Methods
//
/////////////////////////////////////////////////////////

//Given a node, walk the dom tree to find the nearest submit node
function _findClosestSubmit(node, ignore)
{
    var ret;

    ret=_findClosestSubmit_recurse(node, null);
    if (ret==null) {
        if (node.parentNode) {
            ret=_findClosestSubmit(node.parentNode, node);
        } else {
            ret=null;
        }
    }
    return ret;
}

function _findClosestSubmit_recurse(node, ignore)
{
    var firstChild, i, ret, children;

    // success case:
    if(node.name=="ENTERSUBMIT") {
        return node;
    }

    if (node.hasChildNodes()) {
        children=node.childNodes;
        for(i=0;i<children.length;i++) {
            if(ignore!=node) {
                ret=_findClosestSubmit_recurse(children[i], ignore);
                if(ret) {
                    return ret;
                }
            }
        }
    }

    return null;
}

function getParentTR(node){
	if(node.nodeName == "TR"){
		return node;
	} else {
		return getParentTR(node.parentNode);
	}
}

function agSubmitOnColumnLink(linknode){
	  var parentTR = getParentTR(linknode);
	  if(parentTR.onclick == null){
    //submit the form, so long as the row isn't taking care of it
    var closestSubmitNode = _findClosestSubmit(linknode, null);
    if (closestSubmitNode) {
      closestSubmitNode.onclick();
    }
    return false;
  }
}

function agSubmitOnRowClick(rowObject){
    //submit the form
    var closestSubmitNode = _findClosestSubmit(rowObject, null);
    if (closestSubmitNode) {
      closestSubmitNode.onclick();
    }
    return false;
}

function agSubmitClosest(nodeObj){
    //submit the form
    var closestSubmitNode = _findClosestSubmit(nodeObj, null);
    if (closestSubmitNode) {
      closestSubmitNode.onclick();
    }
    return false;
}

function preSubmit(form) {
        form.CTXSubmitCount.value++

    }

function onSubmitHandler(form) {
        preSubmit(form)
    }

//Enter key form submission support
function agSubmitViaEnter(evt, formElement){
  evt = (evt) ? evt : event;
  var target = (evt.target) ? evt.target : evt.srcElement;
  var form = target.form;
  var charCode = (evt.charCode) ? evt.charCode : ((evt.which) ? evt.which : evt.keyCode);
  if (charCode == 13 || charCode == 3) {
    //submit the form
    var closestSubmitNode = _findClosestSubmit(formElement, null);
    if (closestSubmitNode) {
      closestSubmitNode.onclick();
    }
    return false;
  }
  return true;
}

//Main method for submitting a form, given a form action (href)
function hrefSubmitForm(href, performValidation) {
    hidePageErrors();
    form = document.forms.masterForm
    qindex = href.indexOf("?")
    if (qindex >= 0) {
        qstring = href.substring(qindex+1)
        separator = '?'
        if (form.action.indexOf('?') >=0) {
            separator = '&'
            }
        hrefAction = form.action + separator + qstring
    }
    if (agFileUploadSubmit(hrefAction)) {
        /* pass */
    } else if (performValidation) {
					if (agValidateForm(href)) {
        		preSubmit(form)
        		getDivContents(hrefAction)
        	}
    } else {
      preSubmit(form)
      getDivContents(hrefAction)        		
    }
    return false;
}

function anchorSubmitForm(anchor) {
        form = document.forms.masterForm
        href = anchor.href
        return hrefSubmitForm(href)
}


//Method for triggering file upload (non-ajax) submit
function agFileUploadSubmit(action) {
    var form=document.forms.masterForm;
    formElements=form.elements;
    var doFileUpload=false;
    for(var i=0;i<formElements.length;i++) {
        if ((formElements[i].type=='file') && (formElements[i].value!="")) {
            doFileUpload=true;
        }
    }

    if (doFileUpload) {
        agIframePOST(form, action);
        return true;
    } else {
        return false;
    }
}

//Iframe callback method for iframe-based form submit
function agIframePOSTCallback() {
    /* see http://ajaxpatterns.org/IFrame_Call */
    var frame=document.getElementById('agIframePOSTFrame')
    /* see http://developer.apple.com/internet/webcontent/iframe.html */
    if (frame.contentDocument) {
        // For NS6
        fd = frame.contentDocument; 
    } else if (frame.contentWindow) {
        // For IE5.5 and IE6
        fd = frame.contentWindow.document;
    } else if (frame.document) {
        // For IE5
        fd = frame.document;
    } else {
        fd = null;
    }

    if(!fd) {
        return false;
    }

    var resp=fd.getElementById("agIframePOSTResponse");
    if (!resp) {
        return false;
    }
    var ih=resp.value;

    agAJAXHandleXML(ih);

    fd.removeChild(fd.firstChild);
}



/////////////////////////////////////////////////////////
//
//    Popup Drag Support
//
/////////////////////////////////////////////////////////

var ie=document.all
var ns6=document.getElementById&&!document.all

var dragapproved=false
var z,x,y

function move(e){
if (dragapproved){
z.style.left=ns6? temp1+e.clientX-x + "px": temp1+event.clientX-x + "px"
z.style.top=ns6? temp2+e.clientY-y + "px": temp2+event.clientY-y + "px"
if (parseInt(z.style.top) < 0) z.style.top = "0px"
if (parseInt(z.style.left) < 0) z.style.left = "0px"
return false
}
}

function drags(e){
if (!ie&&!ns6)
return
var firedobj=ns6? e.target : event.srcElement
var topelement=ns6? "HTML" : "BODY"
while (firedobj.tagName!="HTML" && firedobj.tagName!="BODY" &&firedobj.className!="agPopupTitleBar"){
  if (ns6){
    firedobj = firedobj.parentNode;
  }else{
    firedobj = firedobj.parentElement;
  }
}

if (firedobj.className=="agPopupTitleBar"){
dragapproved=true
z=document.getElementById("agPopupContainer")
temp1=parseInt(z.style.left+0)
temp2=parseInt(z.style.top+0)
x=ns6? e.clientX: event.clientX
y=ns6? e.clientY: event.clientY
document.onmousemove=move
return false
}
}
document.onmousedown=drags
document.onmouseup=new Function("dragapproved=false")
