/**
 * ajax.js
 *
 * Allows in-page communication from the browser to the web server. IE an application can reload part 
 * instead of a full page.
 *
 * How to use
 * ==========
 * 1) Call processRequest from the relevant event on the HTML page (e.g. onclick).
 * 2) Pass the url to a servlet, such as a Struts action class, and the name of the HTML form to post.
 * 3) When the server responds ...
 *		a) the script loops through the servlet response, looking for <div id="name">newContent</div>
 *			elements. "newContent" will contain your HTML content.  "id" will contain a name that you make up.
 *		b) for each DIV tag found on the HTML page where the value of the ID property matches
 *			a DIV tag's ID value from the servlet response, the content within the DIV tag on the 
 *			document will be replaced with the content of the DIV tag from the servlet response.
 *
 * NOTE: <div id="name"> is case sensitive. The ID value must follow the first quote mark and end in a quote
 *			Everything after the first '>' up to the '</div>' is considered content.
 *			Empty Sections should be in the format <div id="name"></div>. DIV elements must
 *			be in lower case. <DIV> is different then <div>.
 *
 * Example HTML page: 
 * <form name="myForm">
 * <input type="text" name="itemCd" 
 *     onblur="processRequest('/ItemLookupAction.do?customerId=1', 'myForm');">
 * <div id="itemDescArea">No description found</div>
 * </form>
 *
 * Example Output from servlet:
 * <div id="itemDescArea">Big fat widget</div>
 */
var req; // holds the XML HTTP request object.

/**
 * TAC - modified to use new <code>processRequest</code> function.
 *
 * Calls a servlet, pointed to by aUrl, and replaces the content on the calling page
 * with the HTML output from the servlet.  The calling page must surround the "changeable" 
 * content with DIV tags.  The servlet must also output HTML with DIV tags as well.
 * If the ID on the DIV tag from the page matches the ID on the DIV tag from the servlet,
 * then the page content will be replaced with the output from the servlet.
 *
 * @param aUrl The URL to a servlet which will render the HTML to place on the page. 
 * (e.g. /appctx/ajaxrocks.do?formId=51) 
 * @param aHtmlForm The value of the ID property on the HTML form.  If supplied, all fields on 
 * the form will be appended to aUrl as request parameters.  Pass null to NOT append any 
 * form fields to aUrl. 
 */
function processRequest(aUrl, aHtmlForm) {
	processRequest(aUrl, aHtmlForm, null);
}

/**
 * TAC - added 11/9/2006
 *
 * Calls a servlet, pointed to by aUrl, and replaces the content on the calling page
 * with the HTML output from the servlet.  The calling page must surround the "changeable" 
 * content with DIV tags.  The servlet must also output HTML with DIV tags as well.
 * If the ID on the DIV tag from the page matches the ID on the DIV tag from the servlet,
 * then the page content will be replaced with the output from the servlet.
 *
 * @param aUrl The URL to a servlet which will render the HTML to place on the page. 
 * (e.g. /appctx/ajaxrocks.do?formId=51) 
 * @param aHtmlForm The value of the ID property on the HTML form.  If supplied, all fields on 
 * the form will be appended to aUrl as request parameters.  Pass null to NOT append any 
 * form fields to aUrl. 
 * @param aCallBack A pointer to a call back function. This will handle the response from the 
 * <code>XMLHttpRequest</code>. The function will access the <code>XMLHttpRequest</code> with the
 * variable named <code>req</code>.
 */
function processRequest(aUrl, aHtmlForm, aCallBack) {
	// get the (form based) params to push up as part of the get request
	aUrl += getFormAsString(aUrl, aHtmlForm);
	if (window.ActiveXObject) { // Internet Explorer Browser
		executeIeBrowser(aUrl, aCallBack);
	} else if (window.XMLHttpRequest) { // Non-Internet Explorer browsers
		executeOtherBrowser(aUrl, aCallBack);
	} else {
		alert("Your browser does not support AJAX");
	}
}

/** Executes the URL for Internet Explorer users. */
function executeIeBrowser(aUrl, aCallBack) {
	req = new ActiveXObject("Microsoft.XMLHTTP");
	if (req) {
		if(aCallBack == null){
			req.onreadystatechange = processStateChange; // callback method name.
		}else{
			req.onreadystatechange = aCallBack;
		}
		req.open("GET", aUrl, true);
		req.send();
	} else {
		alert("You do not have ActiveX enabled on your browser.");
	}
}

/** Executes the URL for NON Internet Explorer users. */
function executeOtherBrowser(aUrl, aCallBack) {
	req = new XMLHttpRequest();
	if(aCallBack == null){
		req.onreadystatechange = processStateChange; // callback method name.
	}else{
		req.onreadystatechange = aCallBack;
	}
	try {
		req.open("GET", aUrl, true); 
	} catch (e) {
		alert("Problem Communicating with Server\n" + e);
	}
	req.send(null);
}
 
/** Gets the contents of the form as a URL encoded String suitable for appending to a url */ 
function getFormAsString(aUrl, aFormName){
	returnString = "";
	if (aFormName == null) return returnString;

	formElements=document.forms[aFormName].elements;
	if (formElements == null) return returnString; 
	
	if (aUrl.indexOf("?") < 0) {
		returnString = "?";
	} else {
		if (aUrl.substring(aUrl.length - 1) != "&") {
			returnString = "&";
		}
	}
	for (var i=formElements.length-1; i>=0; --i ){
 		returnString += escape(formElements[i].name) + "=" + escape(formElements[i].value) + "&";
 	}
 	
 	return returnString; 
}

/** Set as the callback method for when XmlHttpRequest State Changes used by processRequest. */
function processStateChange() {
	if (req.readyState == 4) { // 4 = Complete
		if (req.status == 200) { // 200 = OK response
			servletOutput = req.responseText;
			updatePage(servletOutput);
		} else {
			alert("Problem with server response:\n" + req.statusText + "\n\nstatus:" + req.status);
		}
	}
}

/**
 * Builds an array containing the DIV elements from the Servlet output
 * and replaces the content on the page that is surrounded by DIV tags
 * that contain the same ID value as the ID value from the Servlet. 
 * @param aServletOutput the HTML output from the servlet. If no DIV elements from
 * the Servlet are found, this method does nothing.
 */
function updatePage(aServletOutput) {
	data = getDivs(aServletOutput);
	if (data == null) { return; }
	
	replaceContent(data);
}

function getDivs(aServletOutput) {	
	var divs = "";
	var input = "";
	
	input = aServletOutput;
	var begDivIdx = input.indexOf("<div "); 
	if (begDivIdx < 0) { return new Array(); }
	
	return findEndDiv(input, begDivIdx);
}

function findEndDiv(aServletOutput, aBeginDivIdx) {
	var cnt = 1;
	var divs = new Array();
	
	return getEndDiv(aServletOutput, aBeginDivIdx, cnt, divs);
}

var globalBeginIdx = 0;

function getEndDiv(aServletOutput, aBeginDivIdx, aCnt, aDivs) {
	len = aServletOutput.length;
	if (aBeginDivIdx == (len - 1)) { return null; }
	
	var cnt = aCnt;
	begDivIdx = aServletOutput.indexOf("<div ", aBeginDivIdx);
	endDivIdx = aServletOutput.indexOf("</div>", aBeginDivIdx + 1);
	
	if (begDivIdx > -1 && begDivIdx < endDivIdx) {
		if (cnt == 1) {
			globalBeginIdx = begDivIdx;
		}
		cnt++;
		return getEndDiv(aServletOutput, begDivIdx + 1, cnt, aDivs);
	}
	
	cnt--;
	if (cnt <= 0) { return aDivs; }
	
	if (cnt == 1) {
		last = aDivs.length;
		aDivs[last] = aServletOutput.substring(globalBeginIdx, endDivIdx + 6);
		globalBeginIdx = 0;
	}
	
	return getEndDiv(aServletOutput, endDivIdx + 1, cnt, aDivs);
}
 
/** Splits the text into DIV elements and returns array containing each DIV element. */
function getElements(aServletOutput){
	returnElements=aServletOutput.split("</div>");
	if (returnElements == null || returnElements == aServletOutput) return null;
 	
	for (var i=returnElements.length-1; i>=0; --i ) {
		// Remove everything before the DIV tag.
		pos = returnElements[i].indexOf("<div");	
		if (pos > 0) {
			subString=returnElements[i].substring(pos);
			returnElements[i]=subString;
		} 
	}
	return returnElements;
}
 
/**
 * Replace HTML elements in the existing (ie viewable document) with new elements 
 * (from the ajax requested document) WHERE they have the same ID value AND are 
 * DIV elements.
 * @param aData an array of DIV element data in the format 
 * <div id="name">texttoupdate
 */
function replaceContent(aData) {
	if (aData == null) { return; }
	
	for (var i=aData.length-1; i>=0; --i ) {
		if (aData[i].indexOf("<div") < 0) continue;
		
		idVal = getIdValue(aData, i);
		content = getElementContent(aData, i);
		
		// Update page with content from Servlet.
		if (document.getElementById(idVal)) {
			document.getElementById(idVal).innerHTML = content;
		}
 	}
 }

/** Returns the value of the ID property. */
 function getIdValue(aData, aIndex) {
	startIdPos = aData[aIndex].indexOf('"') + 1;
	endIdPos = aData[aIndex].indexOf('"', startIdPos);
	return aData[aIndex].substring(startIdPos, endIdPos);
 }

/** Returns the content contained within the DIV tag. */
 function getElementContent(aData, aIndex) {
	startContentPos=aData[aIndex].indexOf('>') + 1;
	return aData[aIndex].substring(startContentPos);
 }

