/*
 * @author Brian Jerolleman
 * @date 10/03/2005
 *
 * Definitions used to assit performing AJAX calls.
 * The easiest use is to execute only the AJAX_ExecuteRequest function.
 *
 * Example:
 *   (1) Define a handler function:
 *
 *       function updateDetails(xmlResponse)
 *       {
 *           var details = xmlResponse.getElementsByTagName("regulationDetails")[0];
 *           document.getElementById("txtRegulator").value = details.getElementsByTagName("regulator")[0].firstChild.nodeValue;
 *           document.getElementById("txtCategory").value = details.getElementsByTagName("category")[0].firstChild.nodeValue;
 *           document.getElementById("txtRegulation").value = details.getElementsByTagName("regulation")[0].firstChild.nodeValue;
 *       }
 *
 *   (2) Execute the AJAX call in the desired event handler:
 *
 *       AJAX_ExecuteRequest
 *       (
 *           updateDetails,
 *           "GetRegulationDetails.html",
 *           "regulatorID=" + regulatorID + "&majorCategoryID=" + majorCategoryID + "&questionID=" + questionID
 *       );
 *
 *   (3) Generate the XML in GetRegulationDetails.html:
 *
 *       <regulationDetails>
 *           <regulator>FDIC</regulator>
 *           <category>Best Practices</category>
 *           <regulation>CP30</regulation>
 *       </regulationDetails>
 */




/////////////////////////////////////////////////
// The including HTML must set these parameters
/////////////////////////////////////////////////

/**
 * URL to handle NameValuePairs_update function calls.
 */
var NameValuePairs_url;

/**
 * URL to handle AJAX_isUnique function calls.
 */
var AJAX_isUniqueURL;

/**
 * URL to handle AJAX_isInteger function calls.
 */
var AJAX_isIntegerURL;



////////////////////////////////////////////////
// General AJAX functions
/////////////////////////////////////////////////

/**
 * Executes an AJAX call to the specified URL with the specified parameters
 * and the with the XML response to be handled by the specified function.
 * The optionally specified error handler will be executed on error and passed the request object.
 *
 * @param responseXmlHandler Function to pass the XML response.
 * @param url URL of the Web resource handling the request.
 * @param parameters Query string format of parameters to use for the request. e.g. name1=value1&name2=value2
 * @param errorHandler Optional function executed on error and passed the request object.  If nothing is specified, an alert with an error message is displayed on error.
 */
function AJAX_ExecuteRequest(responseXmlHandler, url, parameters, errorHandler, requestID)
{
	AJAX_ExecuteRequestExtended(responseXmlHandler, url, parameters, errorHandler, requestID, true);
}

/**
 * Like AJAX_ExecuteRequest but adds an asynch flag for the request.
 */
function AJAX_ExecuteRequestExtended(responseXmlHandler, url, parameters, errorHandler, requestID, asynch)
{
	// If no error handler is specified, assign a default
	if (!errorHandler) errorHandler = function(req) { alert("HTTP error " + req.status + "."); };

	// Execute reuqest
	var req = AJAX_newXMLHttpRequest();
	req.onreadystatechange = AJAX_getReadyStateHandler(req, responseXmlHandler, errorHandler, requestID);
	req.open("POST", url, asynch);
	req.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
	req.send(parameters);
}

/**
 * Checks if the returned payload is the login page.
 *
 * @param the response object returned from a previous AJAX call
 * @returns true if the user is logged out or their session has expired, otherwise false
 */
function isLoggedOut(req)
{
	// If this is an xml payload
	if (req.documentElement)
	{
		return req.documentElement.getElementsByTagName("script").length > 0;
	}
	// Otherwise, use it as a string
	else
	{
		return req.indexOf("//Login") > 0;
	}
}

// AJAX_ExecuteRequest helper funciton.
// Returns a new XMLHttpRequest object, or false if the browser doesn't support it.
/* private */ function AJAX_newXMLHttpRequest()
{
	var xmlreq = false;

	// Non-Microsoft browsers
	if (window.XMLHttpRequest)
	{
		xmlreq = new XMLHttpRequest();
	}
	else if (window.ActiveXObject)
	{
		try 
		{
			// Newer versions of Internet Explorer
			xmlreq = new ActiveXObject("Msxml2.XMLHTTP");
		}
		catch(e1)
		{
			try 
			{
				// Older versions of Internet Explorer
				xmlreq = new ActiveXObject("Microsoft.XMLHTTP");
			}
			catch (e2)
			{
				// Unable to create an XMLHttpRequest
				xmlreq = false;
			}
		}
	}
  
	return xmlreq;
}

// AJAX_ExecuteRequest helper funciton.
// Returns a function that waits for the specified XMLHttpRequest to complete,
// then passes the XML response to the given handler function if the request completes normally,
// or passes the the request to the error handler on error.
//
// @param req The XMLHttpRequest making the request.
// @param responseXmlHandler Function to pass the XML response.
// @param errorHandler Function to pass the request on error.
/* private */ function AJAX_getReadyStateHandler(req, responseXmlHandler, errorHandler, requestID)
{
	return function() 
	{
		if (req.readyState == 4)						// If the request's status is "complete"
		{
			if (req.status == 200)						// Check that we received a successful response from the server
				responseXmlHandler(req.responseXML, req, requestID);	// Pass the XML payload of the response to the handler function
			else 
				errorHandler(req);						// Pass the request object to the error handler function on error
		}
	}
}




/////////////////////////////////////////////////
// IsUnique functions
/////////////////////////////////////////////////

/**
 * Executes an AJAX call to check if the specified name of the specified type of item is unique.
 *
 * @param type Type of item being tested.
 * @param id ID of item being tested.  This should be "0" for new items.
 * @param name This is the property of the item being tested for uniqueness.
 * @param handler Called when after the AJAX response and is passed the specified id and true/false uniqueness value.
 * @param errorHandler Passed to AJAX_ExecuteRequest.
 */
function AJAX_isUnique(type, id, name, handler, errorHandler)
{
	var params = new Object();
	params.handler = handler;
	params.id = id;

	AJAX_ExecuteRequest
	(
		AJAX_isUniqueHandler,
		AJAX_isUniqueURL,
		"type=" + type + "&id=" + id + "&name=" + name,
		errorHandler,
		params
	);
}

// AJAX_isUnique helper funciton.
/* private */ function AJAX_isUniqueHandler(xmlResponse, req, params)
{
	if (params.handler)
	{
		params.handler(params.id, (xmlResponse.getElementsByTagName("unique")[0].firstChild.nodeValue =="true")? true: false);
	}
	else if (! xmlResponse.getElementsByTagName("unique")[0].firstChild.nodeValue)
	{
		alert("Name is not unique.");
	}
}

/////////////////////////////////////////////////
// IsInteger functions
/////////////////////////////////////////////////

/**
 * Executes an AJAX call to check if the specified name of the specified type of item is an integer
 *
 * @param input value being checked
 * @param handler Called when after the AJAX response and is passed the specified id and true/false uniqueness value.
 * @param errorHandler Passed to AJAX_ExecuteRequest.
 */
function AJAX_isInteger(input, handler, errorHandler)
{
	var params = new Object();
	params.handler = handler;

	AJAX_ExecuteRequest
	(
		AJAX_isIntegerHandler,
		AJAX_isIntegerURL,
		"input=" + input,
		errorHandler,
		params
	);
}

// AJAX_isInteger helper funciton.
/* private */ function AJAX_isIntegerHandler(xmlResponse, req, params)
{
	if (params.handler)
	{
		params.handler(params.id, (xmlResponse.getElementsByTagName("validinteger")[0].firstChild.nodeValue =="true")? true: false);
	}
	else if (! xmlResponse.getElementsByTagName("validinteger")[0].firstChild.nodeValue)
	{
		alert("input is not an integer.");
	}
}