/********************************************************************************
 * 
 * File:
 *	Ajax.js 
 * 
 * Description:
 *	Contains routines to support asynchronous communication with the web server.
 * 
 * Revision History:
 *	2009.08.24	dwo
 *				SubmitForm():  If the current document is within a parent (IFrame), then for
 *				the response status '0000' we need to redirect the parent window, not
 *				the child IFrame window.
 *
 *	2009.05.11	dwo
 *				SubmitForm(), SubmitRequest(): Added 'Session Timed Out' status code = '0004'.
 *
 *	2009.01.01	dwo
 *				Many updates and alterations to the original code.
 *				In particular: SubmitForm(), SubmitRequest().
 *
 *	2007.01.12	dwo
 *				Original: Downloaded from the web.
 *					SAL - Simple Ajax Lib. 23-Sep-2005
 *					by Nigel Liefrink
 *					Email: leafrink@hotmail.com
 * 
 ********************************************************************************/

var debug = false;
//debug = true;

////////////////////////////////////////////////////////////////////////////////

function encodeValue(value)
	{
	if (typeof encodeURIComponent != 'undefined')
		{
		return encodeURIComponent(value);
		}
	else
		{
		return escape(value);
		}
	}	// End encodeValue()

////////////////////////////////////////////////////////////////////////////////

function decodeValue(value)
	{
	if (typeof decodeURIComponent != 'undefined')
		{
		return decodeURIComponent(value);
		}
	else
		{
		return unescape(value);
		}
	}	// End decodeValue()

////////////////////////////////////////////////////////////////////////////////

function buildQueryString(theForm)
	{
	var qs = '';
	for (e=0;e<theForm.elements.length;e++)
		{
		if (theForm.elements[e].name!='' && theForm.elements[e].name!='__VIEWSTATE') {
			//qs+=(qs=='')?'?':'&';
			// Do not prepend a '?' at the start of the query string.
			qs+=(qs=='')?'':'&';
			qs+=theForm.elements[e].name+'='+escape(theForm.elements[e].value);
			}
		}
	return qs
	}	// End buildQueryString()

////////////////////////////////////////////////////////////////////////////////

function buildPostString(theForm)
	{
	var qs = '';
	var field;
	var delimiter = '';
	var strFieldName;
		
	if (debug)
		{
		alert("We are in buildPostString(" + theForm.id + ", " + theForm.elements + ")");
		}

//	// Always include the logged on UserID...if it is present on the page.
//	var ctlLoggedOnUserID = document.getElementById('txtLoggedOnUserID');
//	if ( ctlLoggedOnUserID )
//		{
//		qs = 'txtLoggedOnUserID=' + ctlLoggedOnUserID.value;
//		delimiter = ',';
//		}
//		
	for (e=0;e<theForm.elements.length;e++)
		{
		field = theForm.elements[e]
		strFieldName = field.name;
		if ( strFieldName == '' )
			strFieldName = field.id;
		if (strFieldName!='' && strFieldName!='__VIEWSTATE')
			{
			if (field.type == 'select-multiple')
				{
				//qs += encodeValue(strFieldName) + '=';
				qs += strFieldName + '=';
				for (var i = 0; i < field.options.length; i++)
					{
					if (field.options[i].selected)
						{
						qs += delimiter + encodeValue(field.options[i].value);
						delimiter = ',';
						}
					}

	 			qs +=  '&';
				}
			else if (field.type == 'checkbox')
				{
				if ( field.checked )
					qs += encodeValue(strFieldName) + '=true' + '&';
				else
					qs += encodeValue(strFieldName) + '=false' + '&';
				}
			else if (field.type == 'radio')
				{
				if ( field.checked )
					qs += encodeValue(strFieldName) + '=' + field.value + '&';
				}
			else if ( field.getAttribute('tinyMCE') )
				{
				qs += encodeValue(strFieldName) + '=' + encodeValue(tinyMCE.getInstanceById(strFieldName).getHTML()) + '&' ;
				}
			else
				{
				qs += encodeValue(strFieldName) + '=' + encodeValue(field.value) + '&';
				}
			}
		}

	if (qs.length > 0)
		{
		qs = qs.substring(0, qs.length - 1);
		}
		
	if (debug)
		{
		alert("Leaving buildPostString() with: " + qs);
		}

	return qs
	}	// End buildPostString()

////////////////////////////////////////////////////////////////////////////////

function fillFormFromRequest(theForm, strFormRequest)
	{
	if (strFormRequest)
		{
		var arrField = new Array();
		var arrValues;
		var field;
		var optionValue;

        if (debug)
            alert("fillFormFromRequest");
            
		// Break apart the Field/Value pairs
		//		FieldName1=32&FieldName2=Doug
		var arrFieldValuePairs = strFormRequest.split('&');

		for (var i = 0; i < arrFieldValuePairs.length; i++)
			{
			//alert(arrFieldValuePairs[i]);		
			// Break the Field/Value into its constituent parts.
			//	FieldName1=32
			//		becomes
			//	arrField[0] = 'FieldName1'
			//	arrField[1] = 32
			var intIndex = arrFieldValuePairs[i].indexOf('=');
			if ( intIndex >= 0 )
				{
				arrField[0] = arrFieldValuePairs[i].substring(0, intIndex);
				arrField[1] = arrFieldValuePairs[i].substring(intIndex + 1);
				// See if there's a specific property of this Field we are to access.
				var strPropertyName = '';
				intIndex = arrField[0].indexOf('.');
				if ( intIndex > 0 )
					{
					strPropertyName = arrField[0].substring(intIndex + 1);
					arrField[0] = arrField[0].substring(0, intIndex); 
					}
				}
			
			if (arrField.length)
				{
				// Decode the Fieldname, just in case it had special characters in it.
				fieldName = decodeValue(arrField[0]);
				// Locate the document element by its Fieldname/Id.
				field = document.getElementById(fieldName);
				
				if ( field )
					{
					// If this is a multi-select list, then...
					if (field.type == 'select-multiple')
						{
						// Unselect all options in the list...
						for (var intOptionIndex=0; intOptionIndex < field.options.length; intOptionIndex++)
							{
							field.options[intOptionIndex].selected = false;
							}
						// Get an array of the selected Option values.
						arrValues = arrField[1].split(',');
						// For each option value...
						for (var j=0; j < arrValues.length; j++)
							{
							optionValue = decodeValue(arrValues[j]);
							// Loop through the list of options...
							for (var intOptionIndex=0; intOptionIndex < field.options.length; intOptionIndex++)
								{
								// If this option has the specified value, then select it.
								if (field.options[intOptionIndex].value == optionValue)
									{
									field.options[intOptionIndex].selected = true;
									}
								}	// End for (each Option)
							}	// End for (each Selected Option)
						}
					else if (field.type == 'checkbox')
						{
						field.checked = decodeValue(arrField[1]);
						}
					else if (field.tagName == 'img' || field.tagName == 'IMG')
					    {
						var src = decodeValue(arrField[1]);
						field.src = src;
						// Use 'null' for no image:
						//	An img tag where the src attribute = '' will attempt
						//	to access the website's home document (index.php).
						//	This will set up a race condition between this Ajax
						//	request and access to the index.php as the img src page.
						//	If index.php contains a call to session_start(), then
						//	this race condition will cause the PHP session to hang.
						if ( (arrField[1].length != 0) && (src != 'null') )
						    field.style.visibility = 'visible';
						else
						    field.style.visibility = 'hidden';
					    }
					else if (field.tagName == 'a' || field.tagName == 'A')
					    {
						field.href = decodeValue(arrField[1]);
					    }
					else if (field.tagName.toLowerCase() == 'select')
						{
						if ( strPropertyName.toLowerCase() == 'innerhtml' )
							field.innerHTML = decodeValue(arrField[1]);
						else
							{
							//alert("Select value: " + arrField[1]);
							field.value = decodeValue(arrField[1]);
							}
						}
					else if (field.tagName.toLowerCase() == 'div')
						{
						field.innerHTML = arrField[1];
//						field.innerHTML = decodeValue(arrField[1]);
						}
					else if (field.type == null)
						{
						field.innerHTML = decodeValue(arrField[1]);
						}
					else if ( field.getAttribute('tinyMCE') )
						{
						tinyMCE.getInstanceById(fieldName).setHTML(decodeValue(arrField[1]));
						}
					else
						{
						field.value = decodeValue(arrField[1]);
						}
					}
				}
			}	// End for (each FieldValue pair)
		
		}	// End if (strFormRequest)
		
	}	// End fillFormFromRequest()

////////////////////////////////////////////////////////////////////////////////

function ClearForm(theForm)
	{
	for (var e=0;e<theForm.elements.length;e++)
		{
		var strFieldName;
		
		field = theForm.elements[e]
		strFieldName = field.name;
		if ( strFieldName == '' )
			strFieldName = field.id;
		var blnNoClear = (field.getAttribute('noclear') == 'true');
		if ((strFieldName!='') && (strFieldName!='__VIEWSTATE') && (! blnNoClear))
			{
			if ( field.tagName.toLowerCase() == 'select' )
				{
				field.selectedIndex = -1;
				}
			else if (field.type == 'select-multiple')
				{
				field.selectedIndex = -1;
				//// Unselect all options in the list...
				//for (var intOptionIndex=0; intOptionIndex < field.options.length; intOptionIndex++)
				//	{
				//	field.options[intOptionIndex].removeAttribute("selected");
				//	//field.options[intOptionIndex].selected = false;
				//	}
				}
			else if (field.type == 'checkbox')
				{
				field.checked = false;
				}
			else if ((field.type == 'text') || (field.type == 'textarea') || (field.type == 'password') || (field.type == 'file') || (field.type == 'hidden'))
				{
				field.value = '';
				}
			}	// End if (the field does not have a name, or its name is __VIEWSTATE or has attribute 'noclear'.
		}	// End for (each element on the Form)
		
	}	// End ClearForm()

////////////////////////////////////////////////////////////////////////////////

/**
Browser Compatability function.
Returns the correct XMLHttpRequest depending on the current browser.
*/
function GetXmlHttp() {	
	var xmlhttp = false;
	if (window.XMLHttpRequest)
		{
		// Firefox, Opera 8.0+, Safari
		xmlhttp = new XMLHttpRequest();
		}
	else if (window.ActiveXObject)// code for IE
		{
		//Internet Explorer
		try 
			{
			xmlhttp = new ActiveXObject("Msxml2.XMLHTTP");
			} 
		catch (e) 
			{
			try 
				{
				xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
				}
			catch (E)
				{
				xmlhttp=false;
				}
			}
		}

	return xmlhttp;

}	/* End GetXmlHttp() */

////////////////////////////////////////////////////////////////////////////////

function SubmitForm(theForm, url, obj_id, callbackFunction, params)
{		
    if (typeof theForm != 'object')
		theForm = document.getElementById(theForm);

	var xmlhttp = new GetXmlHttp();

	if (debug)
		{
		alert("We are in SubmitForm()");
		}

	// Now we got the XmlHttpRequest object, send the request.
	if (xmlhttp)
		{
		xmlhttp.open("POST",url,true);
		xmlhttp.onreadystatechange =
		function () 
			{
				if (debug)
					{
					alert("Entering onreadystatechange function.");
					}
				if (xmlhttp && xmlhttp.readyState==4)
					{	// We got something back..
					if (xmlhttp.status==200)
						{
						if (debug)
							{
							alert(xmlhttp.responseText);
							}

						// First 4 characters of the response are the response Status code.
						var statusCode = xmlhttp.responseText.substring(0,4);
						// The remaining characters of the response are the associated text.
						var responseText = xmlhttp.responseText.substring(4, xmlhttp.responseText.length);
						if (debug)
							{
							alert('ResponseText: [' + xmlhttp.responseText + ']');
							}
						
						// If the first code encountered is specifying that
						// there is an array of responses, then we will need
						// to split up the responses and loop through each one.
						var arrResponses = new Array();
						if ( statusCode == '1000' )
							arrResponses = responseText.split(String.fromCharCode(1));
						else
							// Otherwise there's just a single response.
							arrResponses[0] = xmlhttp.responseText;

						if (debug)
							alert('arrResponses[].length: ' + arrResponses.length);

						for (i = 0; i < arrResponses.length; i++)
							{
							// First 4 characters of the response are the response Status code.
							var statusCode = arrResponses[i].substring(0,4);
							// The remaining characters of the response are the associated text.
							var responseText = arrResponses[i].substring(4, arrResponses[i].length);

							if (debug)
								{
								alert('ResponseText: [' + responseText + ']');
								}

							switch(statusCode)
								{
								case '0000':	// Success/Replace the current document with a new one.
									var objParent = parent;
									if ( objParent )
										objParent.location.replace(responseText);
									else
										location.replace(responseText);
									break;

								case '0001':	// Error status message to apply to the given Object/Tag.
												// Different than 0005 in that this is a Failure message.
												// This statusCode is passed to the callback function so
												// it will know the request failed.
									if(typeof obj_id == 'object')
										{
										obj_id.innerHTML = responseText;
										//obj_id.style.visibility = 'visible';
										}
									else if ( obj_id )
										{
										document.getElementById(obj_id).innerHTML = responseText;
										//document.getElementById(obj_id).style.visibility = 'visible';
										}
									break;

								case '0005':	// Status message to apply to the given Object/Tag.
												// Different than 0001 in that this is a Success message.
												// This statusCode is passed to the callback function so
												// it will know the request succeeded.
									if(typeof obj_id == 'object')
										{
										obj_id.innerHTML = responseText;
										//obj_id.style.visibility = 'visible';
										}
									else if ( obj_id )
										{
										document.getElementById(obj_id).innerHTML = responseText;
										//document.getElementById(obj_id).style.visibility = 'visible';
										}
									break;

								case '0002':	// Message
									alert('Response: ' + responseText);
									break;

								case '0003':	// Fill Form controls
									fillFormFromRequest(theForm, responseText);
									break;

								case '0004':	// Session Timed out
									var ctlReLogin = document.getElementById('divReLogin');
									if ( ctlReLogin )
										ctlReLogin.style.display='block';
									break;
								
								}	// End switch(statusCode)

							if (debug)
								alert(callbackFunction);

							if ( callbackFunction != undefined )
								{
								if ( callbackFunction.length )
									{
									var functionToCall = callbackFunction+'(statusCode, responseText, obj_id, '+params+')';
									if (debug)
										{
										alert(responseText);
										alert(functionToCall);
										}
			                        document.body.style.cursor = 'default';
									eval(functionToCall);
									}
								}
							}	// End for (each response)

                        document.body.style.cursor = 'default';
						}
					else if(debug)
						{
    					alert("xmlhttp.response = [" + xmlhttp.responseText + "]");
						//obj_id.innerHTML = xmlhttp.responseText;
						//document.Write(xmlhttp.responseText);
						}
					}
			}	// End function()

		var qs = buildPostString(theForm);

		xmlhttp.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
	    if (debug)
		    {
		    alert("Sending request: " + qs);
			//document.getElementById('Request').innerHTML = qs;
		    }
        xmlhttp.setRequestHeader("If-Modified-Since", "Sat, 1 Jan 2000 00:00:00 GMT"); 
        document.body.style.cursor = 'wait';
		xmlhttp.send(qs);
	    if (debug)
		    {
		    //alert("Request Sent");
		    }
		}

}	// End SubmitForm()

function SubmitRequest(strFormValues, url, obj_id, callbackFunction, params)
{		
	var xmlhttp = new GetXmlHttp();

	if (debug)
		{
		alert("We are in SubmitRequest('" + strFormValues + "')");
		}

	// Now we got the XmlHttpRequest object, send the request.
	if (xmlhttp)
		{
		xmlhttp.open("POST",url,true);
		xmlhttp.onreadystatechange =
		function () 
			{
				if (debug)
					{
					alert("Entering onreadystatechange function.");
					}
				if (xmlhttp && xmlhttp.readyState==4)
					{	// We got something back..
					if (xmlhttp.status==200)
						{
						if (debug)
							{
							alert(xmlhttp.responseText);
							}

						// First 4 characters of the response are the response Status code.
						var statusCode = xmlhttp.responseText.substring(0,4);
						// The remaining characters of the response are the associated text.
						var responseText = xmlhttp.responseText.substring(4, xmlhttp.responseText.length);
						if (debug)
							{
							alert('ResponseText: [' + xmlhttp.responseText + ']');
							}
						
						// If the first code encountered is specifying that
						// there is an array of responses, then we will need
						// to split up the responses and loop through each one.
						var arrResponses = new Array();
						if ( statusCode == '1000' )
							arrResponses = responseText.split(String.fromCharCode(1));
						else
							// Otherwise there's just a single response.
							arrResponses[0] = xmlhttp.responseText;

						for (i = 0; i < arrResponses.length; i++)
							{
							// First 4 characters of the response are the response Status code.
							var statusCode = arrResponses[i].substring(0,4);
							// The remaining characters of the response are the associated text.
							var responseText = arrResponses[i].substring(4, arrResponses[i].length);

							if (debug)
								{
								alert('ResponseText: [' + responseText + ']');
								}

							switch(statusCode)
								{
								case '0000':	// Success/Replace the current document with a new one.
									var objParent = parent;
									if ( objParent )
										objParent.location.replace(responseText);
									else
										location.replace(responseText);
									break;

								case '0001':	// Error status message to apply to the given Object/Tag.
												// Different than 0005 in that this is a Failure message.
												// This statusCode is passed to the callback function so
												// it will know the request failed.
									if(typeof obj_id == 'object')
										{
										obj_id.innerHTML = responseText;
										//obj_id.style.visibility = 'visible';
										}
									else if ( obj_id )
										{
										document.getElementById(obj_id).innerHTML = responseText;
										//document.getElementById(obj_id).style.visibility = 'visible';
										}
									break;

								case '0005':	// Status message to apply to the given Object/Tag.
												// Different than 0001 in that this is a Success message.
												// This statusCode is passed to the callback function so
												// it will know the request succeeded.
									if(typeof obj_id == 'object')
										{
										obj_id.innerHTML = responseText;
										//obj_id.style.visibility = 'visible';
										}
									else if ( obj_id )
										{
										document.getElementById(obj_id).innerHTML = responseText;
										//document.getElementById(obj_id).style.visibility = 'visible';
										}
									break;

								case '0002':	// Message
									alert('Response: ' + responseText);
									break;

								case '0003':	// Fill Form controls
									fillFormFromRequest(theForm, responseText);
									break;

								case '0004':	// Session Timed out
									var ctlReLogin = document.getElementById('divReLogin');
									if ( ctlReLogin )
										ctlReLogin.style.display='block';
									break;
								
								}	// End switch(statusCode)

							if (debug)
								alert(callbackFunction);

							if ( callbackFunction != undefined )
								{
								if ( callbackFunction.length )
									{
									var functionToCall = callbackFunction+'(statusCode, responseText, obj_id, '+params+')';
									if (debug)
										{
										alert(responseText);
										alert(functionToCall);
										}
			                        document.body.style.cursor = 'default';
									eval(functionToCall);
									}
								}
							}	// End for (each response)

                        document.body.style.cursor = 'default';
						}
					else if(debug)
						{
    					alert("xmlhttp.response = [" + xmlhttp.responseText + "]");
						//obj_id.innerHTML = xmlhttp.responseText;
						//document.Write(xmlhttp.responseText);
						}
					}
			}	// End function()
				
		xmlhttp.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
	    if (debug)
		    {
		    alert("Sending request: " + strFormValues);
			//document.getElementById('Request').innerHTML = qs;
		    }
        xmlhttp.setRequestHeader("If-Modified-Since", "Sat, 1 Jan 2000 00:00:00 GMT"); 
        document.body.style.cursor = 'wait';
		xmlhttp.send(strFormValues);
		}

}	// End SubmitRequest()

////////////////////////////////////////////////////////////////////////////////

function CheckZipCode(ctl, obj_idError, obj_idSuccess)
{
    var strValue = ctl.value;
	SubmitRequest('ZipCode=' + strValue, 'ajaxIsZipCodeValid.php', '', 'CheckZipCodeResponse', "'" + obj_idError + "','" + obj_idSuccess + "'");
}   // End CheckZipCode()

////////////////////////////////////////////////////////////////////////////////

function CheckZipCodeResponse(statusCode, responseText, obj_id, obj_idError, obj_idSuccess)
{
	if ( obj_idError )
		{
		if(typeof obj_idError != 'object')
			obj_idError = document.getElementById(obj_idError);
		
		if(typeof obj_idSuccess != 'object')
			obj_idSuccess = document.getElementById(obj_idSuccess);
	
		switch (statusCode)
			{
			case '0001':	// Error status
				obj_idError.style.color = 'Maroon';
				obj_idError.innerHTML = responseText;
				obj_idSuccess.innerHTML = "&nbsp;";
				break;
				
			case '0005':	// Success status
				obj_idSuccess.style.color = 'Gray';
				obj_idSuccess.innerHTML = responseText;
				obj_idError.innerHTML = "&nbsp;";
				break;
			
			default:
				break;
			}	// End switch (statusCode)
		}

}	// End CheckZipCodeResponse()
	
////////////////////////////////////////////////////////////////////////////////

function IsUsernameUnique(ctl, obj_id, blnIncludeCurrentUser)
{
    var strUsername = ctl.value;
    if ( blnIncludeCurrentUser )
		SubmitRequest('txtUsername=' + strUsername + '&chkIncludeCurrentUser=1', 'ajaxIsUsernameUnique.php', obj_id);
    else
		SubmitRequest('txtUsername=' + strUsername, 'ajaxIsUsernameUnique.php', obj_id);
}   // End IsUsernameUnique()


