/*==================================================================
	Ajaxbase.js
	
	Author: James Edgeworth (2009) (unless otherwise credited)
	
	Ajax-related functions for handling httpRequests in different situations.
	
	Originally based on the Actionscript sendAndLoad function, but later
	required support for different parameters, and variants.


==================================================================*/


var xmlHttp;

var postString = '';

// sourceData - the raw data retrieved from sendAndLoad(), sendAndCall().
var sourceData = '';

// responseStatus/Content - the two split values from sourceData, used in sendAndLoad(), sendAndCall().
var responseStatus = '';
var responseContent = '';

// sourceXML - the XML retrieved from using sendAndCallXML(), sendAndLoadXML().
var sourceXML = '';



/*
	formToPostVars(Obj Form)
	
	Prepares a POST string using the elements of the form that calls this function.

	Credit goes to : 
	http://www.adoreport.com/ajaxpilotsource/ajaxpilot.js.txt 
	http://www.onlamp.com/pub/a/onlamp/2005/05/19/xmlhttprequest.html
	
	which this function is almost entirely based upon.
	
*/
function formToPostVars(theForm)
{

	postString = '';			//Reset postString - if submit button is clicked numerous times, this var would concatenate itself
	var formElement;
	var lastFormElement = '';	//Keep note of last checkbox (for checkbox value contatenation)
	
	
	for ( i = 0; i < theForm.elements.length; i++ )
	{
	
		formElement = theForm.elements[i];
		
		switch ( formElement.type )
		{
		
			case 'text':
			case 'hidden':
			case 'password':
			case 'textarea':
				postString += formElement.name + '=' + escape(formElement.value) + '&';
			break;
			
			case 'select-one':
				postString += formElement.name + '=' + escape(formElement[formElement.selectedIndex].value) + '&';
			break;
			
			case 'radio':
			
				if ( formElement.checked )
				{
					postString += formElement.name + '=' + paramEscape(formElement.value) + '&';
				}
				
			break;
			
			case 'checkbox':
			
				if ( formElement.checked )
				{
				
					//Comma-concatenate values for checkbox element
					if ( formElement.name == lastFormElement )
					{
					
						// If postString ends with &...
						if(postString.lastIndexOf('&') == postString.length -1)
						{
						
							//...Strip off the &
							postString = postString.substring(0, postString.length - 1);
							
						}
						
						postString += ',' + paramEscape(formElement.value);
						
					}
					else
					{
						postString += formElement.name + '=' + paramEscape(formElement.value);
					}
					
					postString += '&';
					lastElementName = formElement.name;
				}
			
			break;
			
		}
	}
	
	// Remove last ampersand
	postString = postString.substring(0, postString.length - 1);
	
	//return postString;
}

function paramEscape(paramValue)
{
	return encodeURIComponent(paramValue);
}




/*
	validateSourceData()
	
	Checks the data returned by a backend script. If it is prefixed with
	"AjaxError::", then the script errored, and the resulting data should not
	be processed. Otherwise, return the data.

*/
function validateSourceData()
{

	if ( sourceData.indexOf('AjaxError::') == -1 )
	{
		return true;
	}
	else
	{
	
		alert(sourceData);
		return false;
		
	}
	
}


/*
	checkForMessage()
	
	Checks the response from the server (as text/html).
	
	If the response contains any of:
	AjaxError::
	AjaxMessage::
	
	Then we simply have a return message from the server.
	
	Returns true if response was a message, false if no message
	was found.
	
	
*/
function checkForMessage(statusTarget)
{

	if ( sourceData.indexOf('AjaxError::') != -1 ||
		 sourceData.indexOf('AjaxMessage::') != -1 )
	{
	
		var strArray = sourceData.split('::');
	
		if ( statusTarget )
		{
			document.getElementById(statusTarget).innerHTML = strArray[1];
		}
		else
		{
			alert(strArray[1]);
		}
		
		return true;
	
	}
	else
	{
		return false;
	}
	
}



/*
	processResponse()
	
	In typical cases, line 0 represents a message to set
	to a status element. It is split from the rest of the
	response content via '||'. We know that there is no status
	message if this is missing.
	
*/
function processResponse(text)
{

	var responseArray = text.split('||');
			
	// Handle cases where there is no message in the responseText.
	if ( responseArray.length < 2 )
	{
	
		responseArray.push('');
		responseArray[1] = responseArray[0];
		responseArray[0] = '';
	
	}
	
	responseStatus = responseArray[0];
	responseContent = responseArray[1];
	
}



/*
	preparePost()
	
	Prepares POST vars to be sent with xmlHttp.
*/
function preparePost(postVars)
{
	
	// Add js variable
	postVars = (postVars.length > 0) ? postVars + '&js=1' : 'js=1';
	
	// Add postString from formToPostVars(),
	postVars = (postString.length > 0) ? postVars + '&' + postString : postVars;
	

	xmlHttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
	xmlHttp.setRequestHeader("Content-length", postVars.length);
	xmlHttp.setRequestHeader("Connection", "close");
	
	return postVars;
	
}



/*
	Obj Function getXmlHttpObject(void)
	
	Attempts to set an xmlHttpRequest object, depending on browser.
	First it tries for Firefox, Opera, and Safari. If that fails, it tries for different versions
	of Internet Explorer. If that fails, the user does not have a browser that supports Ajax.

*/
function getXmlHttpObject()
{
	var xmlHttp = null;
	
	try
	{
	
		// Firefox, Opera 8.0+, Safari
		xmlHttp = new XMLHttpRequest();
		
	}
	catch (e)
	{
	
		// Internet Explorer
		try
		{
			xmlHttp = new ActiveXObject("Msxml2.XMLHTTP");
		}
		catch (e)
		{
			xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
		}
		
	}
	
	return xmlHttp;
}





/*
	sendAndCall()
	
	Variant of sendAndLoad(), but instead of placing response in an html element,
	it calls a specified function.

*/
function sendAndCall(callbackFunction, statusElement, script, postVars)
{
	xmlHttp = getXmlHttpObject();
	
	if(xmlHttp == null)
	{
		alert("Your browser does not support Ajax");
		return;
	}
	

	document.getElementById(statusElement).innerHTML = '<img src="themes/_common/ajax_loading.gif" /><b>Loading...</b>';
	
	
	xmlHttp.onreadystatechange = function()
	{
	
		if ( xmlHttp.readyState == 4 && xmlHttp.status == 200 )
		{
		
			sourceData = xmlHttp.responseText;
			
			processResponse(sourceData);
			
			checkForMessage(statusElement);
			
			callbackFunction();
			
		}
		
	}
	
	xmlHttp.open('post', script, true);
	
	if ( postVars == null ) var postVars = '';
	
	postVars = preparePost(postVars);

	xmlHttp.send(postVars);
	
}




/*
	sendAndCallXML()
	
	Variant of sendAndCall(), but handles XML

*/
function sendAndCallXML(callbackFunction, statusElement, script, postVars)
{
	xmlHttp = getXmlHttpObject();
	
	if ( xmlHttp == null )
	{
		alert("Your browser does not support Ajax");
		return;
	}
	

	document.getElementById(statusElement).innerHTML = '<img src="themes/_common/ajax_loading.gif" /><b>Loading...</b> ';
	
	
	xmlHttp.onreadystatechange = function()
	{
		if ( xmlHttp.readyState == 4 && xmlHttp.status == 200 )
		{

			sourceXML = xmlHttp.responseXML;
			
			callbackFunction();
			
		}
	}
	
	xmlHttp.open('post', script, true);
	
	if ( postVars == null ) var postVars = '';
	
	postVars = preparePost(postVars);
	
	xmlHttp.send(postVars);
	
}



/*
	sendAndLoad()
	
	removed the option for POST, as post is usually always sent.
	removed the need for "js=1" in a post var, as it will be set
	automatically.
	removed option for async/sync modes.
	
	Added option for statustarget, and contentTarget.
	
	When sending a request, the recieved value's first line
	should be the status message. The rest would be the content.
	
*/
function sendAndLoad(statusTarget, contentTarget, script, postVars)
{
	xmlHttp = getXmlHttpObject();
	
	if ( xmlHttp == null )
	{
		alert("Your browser does not support Ajax");
		return;
	}
	
	var response = Array();

	document.getElementById(statusTarget).innerHTML = '<img src="themes/_common/ajax_loading.gif" /><b>Loading...</b>';
	
	xmlHttp.onreadystatechange = function()
	{
	
		if ( xmlHttp.readyState == 4 && xmlHttp.status == 200 )
		{

			sourceData = xmlHttp.responseText;

			if ( !checkForMessage(statusTarget) )
			{
				processResponse(sourceData);
				
				// Update statusTarget only if it is not the same as the contentTarget
				if ( statusTarget != contentTarget )
				{
					document.getElementById(statusTarget).innerHTML = responseStatus;
				}
				
				document.getElementById(contentTarget).innerHTML = responseContent;
				
			}
			

			
		}
	
	}
	
	xmlHttp.open('post', script, true);
	
	if ( postVars == null ) var postVars = '';
	
	postVars = preparePost(postVars);
	
	//alert(postVars);
	xmlHttp.send(postVars);
	
	return true;
	
}


