/////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////Main AJAX functions///////////////////////////////////////////
//---------------------------------------------------------------------------------------------//
/* Loads an xml document, and sets the onreadystatechange to the onReadyStateFunction to handle the xmlhttp
 * @param xmlURL String the xml URL to request
 * @param onReadyStateFunction function() the function to handle the xmlhttp 
 */
function loadXMLDoc(xmlURL, onReadyStateFunction)
{
  if (window.XMLHttpRequest)
	{ xmlhttp=new XMLHttpRequest(); }
  else
	{	xmlhttp=new ActiveXObject("Microsoft.XMLHTTP"); }

  if (onReadyStateFunction != null) {
		xmlhttp.open("GET",xmlURL,true);
		// Used to delete this instance of xhttp, for multiple ajax at a time.
		xmlhttp.onreadystatechange = onReadyStateFunction
  		xmlhttp.send("");
	}
  else {
		xmlhttp.open("GET",xmlURL,false);
  		xmlhttp.send("");
		return xmlhttp.responseXML;
	}
}	
//---------------------------------------------------------------------------------------------//
/////////////////////////////////////////////////////////////////////////////////////////////////


/////////////////////////////////////////////////////////////////////////////////////////////////
///////////Functions to process specifically xml & xslt transformation///////////////////////////
//---------------------------------------------------------------------------------------------//
/* Processes an XML and XSL object, and accepting one function to handle state changes, and another to to handle the finished responses (function must take xmlResponse as stirng and xslResponse as string)
 * @param xmlObject of xmlObjectClass the xml Object containing URL, Type = "xml", ID optional
 * @param xslObject of xmlObjectClass the xsl Object containing URL, Type = "xsl", ID optional
 * @param onStateChangeFunction function(xmlObject) to handle the xmlhttp state changes for the given xmlObject
 * @param finishedFunction function(xmlDoc, xslDoc) to handle the two xmlhttp.responseXML
 * @comment Make sure the xmlObject and xslObject are of type xmlObjectClass
 * @comment Make sure the finishedFunction accepts at least two parameters, both xmlDoc, first the xml response, second the xslt response.  
 * @comment Make sure the onStateChangeFunction accepts at least one parameter, the xmlObject, which can be used to tell what document is generating the response.
 */
function processXMLandXSLT(xmlObject, xslObject, onStateChangeFunction, finishedFunction)
{
	var xmlXslObject = new xmlXslObjectClass();
	
	// Creates the onReadyState function for the XSL (called after XML loaded).
	// Will run finishedFunction after XSL is loaded
	var onReadyStateFunctionXSL = partial(onReadyStateHandler, finishedFunction, onStateChangeFunction, xslObject, xmlXslObject);
	
	// Creates the "finished function" for the XML document, which runs the load XSL.
	// In short, after the XML is done loading, it will load the XSL, which once finished will run
	// the finishedFunction
	var processXSLNext = partial(loadXMLDoc, xslObject.URL, onReadyStateFunctionXSL);
	var onReadyStateFunctionXML = partial(onReadyStateHandler, processXSLNext, onStateChangeFunction,xmlObject, xmlXslObject);

	// Loads XML
	loadXMLDoc(xmlObject.URL, onReadyStateFunctionXML);
}

/* Creates the onReadyState for xml and xslt processing
 * @param finishedFunction function(xmlResponse, xslResponse) the function to call once both documents are loaded
 * @param onStateChangeFunction function(xmlObject) the function to process any changes to the xmlhttp responses
 * @param xmlObject xmlObjectClass the object that is having the request done on it
 * @param xmlXslObject xmlXslObjectClass the object that houses the two responses
 */
function onReadyStateHandler(finishedFunction, onStateChangeFunction, xmlObject, xmlXslObject)
{
	if (xmlhttp.readyState==4 && xmlhttp.status==200) { 
		// self is defined in laodXMLDoc, and is a reference to the particular query 
		handleXML(finishedFunction, xmlObject, xmlXslObject, xmlhttp.responseXML) 
	}
	else
	{ onStateChangeFunction(xmlObject) }  
}

/* Handles a completed response, adds the response to either the xmlXslObject.xmlResponse or .xslResponse depending, and if both filled in will run the finished function, passing the responses to that function.
 * @param finishedFunction function(xmlDoc, xslDoc) that handles the two responses.
 * @param xmlObject xmlObjectClass the xmlObject that finished it's process.
 * @param xmlXslObject xmlXslObjectClass the object that houses the xml and xsl response xmlDocs.
 */
function handleXML(finishedFunction, xmlObject, xmlXslObject, response)
{
	if(xmlObject.Type == "xml") { 
		xmlXslObject.xmlResponse = response;
		// Will be calling the finished function which will be to run the loadXMLDoc for the XSL script
		finishedFunction();
	}
	else if (xmlObject.Type == "xsl") { 
		xmlXslObject.xslResponse = response;
		if(xmlXslObject.xslResponse != null && xmlXslObject.xmlResponse != null) 
		{ finishedFunction(xmlXslObject.xmlResponse, xmlXslObject.xslResponse); }
	}
}

/* Object class for holding the xml and xslt responses */
function xmlXslObjectClass()
{
	this.xmlResponse = null;
	this.xslResponse = null;
}

/* Object class for holding a xml item, containing URL, Type, and ID to help identify it.
 * @xmlURL String the URL of the xml document.
 * @xmlType String the type the object is, usually "xml" or "xslt" but used to identify
 * @xmlID String String another identification means.
 */
function xmlObjectClass(xmlURL, xmlType, xmlID)
{
	this.URL = xmlURL;
	this.Type = xmlType;
	this.ID = xmlID;
}
//---------------------------------------------------------------------------------------------//
/////////////////////////////////////////////////////////////////////////////////////////////////


/////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////Helper Functions/////////////////////////////////////////////
//---------------------------------------------------------------------------------------------//
/* Applies an xslt style sheet to an xml item and returns the html results.
 * @param xmlDoc as XMLDocument the xml object
 * @param xslDOC as XMLDocument the xsl object
 * @return String the html that was contained in the results.
 */
function getTransformedNodeHTML(xmlDoc, xslDoc)
{
	// code for IE
	if (window.ActiveXObject)
	{
		return xmlDoc.transformNode(xslDoc);
	}
	// code for Mozilla, Firefox, Opera, etc.
	else if (document.implementation && document.implementation.createDocument)
	{
		  xsltProcessor=new XSLTProcessor();
		  xsltProcessor.importStylesheet(xslDoc);
		  var tempDiv = document.createElement("div");
		  tempDiv.appendChild(xsltProcessor.transformToFragment(xmlDoc,document));
		  var nodetext = tempDiv.innerHTML;

		  nodetext = nodetext.replace(/&amp;/gi, "&");
		  nodetext = nodetext.replace(/&lt;/gi, "<");
		  nodetext = nodetext.replace(/&gt;/gi, ">");

          return nodetext
	}
}


/* Special function by Jason Bunting to allow you to set a function with parameters as a variable.
 * @comment Used for setting the function when a ajax request is finished.
 * @param func the function
 * @param any other args
 * @return the function object
 */
function partial(func /*, 0..n args */) {
  var args = Array.prototype.slice.call(arguments, 1);
  var theFunction = function() {
    var allArguments = args.concat(Array.prototype.slice.call(arguments));
    return func.apply(this, allArguments);
  };
  return theFunction
}
//---------------------------------------------------------------------------------------------//
/////////////////////////////////////////////////////////////////////////////////////////////////
