/* *****************************************************************************
 * WAGAjaxUtil.js
 * JavaScript class for cross-browser handling of XMLHttpRequest.
 *
 *
 * Version: 1.0
 * Date: 11/2/2005
 * Author: Steve Kratowicz
 *
 * ****************************************************************************/


/* *****************************************************************************
 * WAGAjaxUtil Constructor
 * ****************************************************************************/
function WAGAjaxUtil(url)
{
	this.XmlHttpReq = null;
	this.ObjType = WAGAjaxUtil.TypeNull;
	this.Url = url;
	this.Slot = -1;
	this.CallBackOnSuccess = null;
	this.CallBackOnFailure = null;
	
	// Branch for Native or IE/Windows XMLHttpRequest
	if (window.XMLHttpRequest)
	{
		this.XmlHttpReq = new XMLHttpRequest();
		this.ObjType = WAGAjaxUtil.TypeNative;
	}
	else if (window.ActiveXObject)
	{
		this.XmlHttpReq = new ActiveXObject("Microsoft.XMLHTTP");
		if (this.XmlHttpReq)
			this.ObjType = WAGAjaxUtil.TypeWindows;
	}
}


/* *****************************************************************************
 * WAGAjaxUtil Class Variables
 * ****************************************************************************/

// ObjectType Constants
WAGAjaxUtil.TypeNull = 0
WAGAjaxUtil.TypeNative = 1
WAGAjaxUtil.TypeWindows = 2

// ReadyState Constants
WAGAjaxUtil.ReadyStateComplete = 4

// Array to store instances for callbacks
WAGAjaxUtil.Instances = new Array()


/* *****************************************************************************
 * SendRequest Method
 * Sends the GET request to the configured URL and sets the event handler for
 *   the response.
 * ****************************************************************************/
WAGAjaxUtil.prototype.SendRequest = function()
{
	// If no XmlHttpRequest object, return false
	if (this.ObjType == WAGAjaxUtil.TypeNull)
		return false;
	
	// Set the callback handler
	this._setCallback();
	
	// Open, Send
	this.XmlHttpReq.open("GET", this.Url, true);
	if (this.ObjType == WAGAjaxUtil.TypeNative)
		this.XmlHttpReq.send(null);
	else if (this.ObjType == WAGAjaxUtil.TypeWindows)
		this.XmlHttpReq.send();
	else
		return false;
	
	// Return True
	return true;
}


/* *****************************************************************************
 * OnReadyStateChange Method
 * Internal method, waits for state change, calls the appropriate callback
 *   functions when the request comes back.
 * ****************************************************************************/
WAGAjaxUtil.prototype.OnReadyStateChange = function()
{	
	// Check that ReadyState is Complete
	if (this.XmlHttpReq.readyState == WAGAjaxUtil.ReadyStateComplete) {

		// Check that HTTP Status Code is OK
		if (this.XmlHttpReq.status == 200) {
			if(typeof this.CallBackOnSuccess == "function")
				this.CallBackOnSuccess();
		} else {
			if(typeof this.CallBackOnFailure == "function")
				this.CallBackOnFailure();
		}
		
		// Clear the referenct to this instance in the Instances array
		WAGAjaxUtil.Instances[this.Slot] = null;
	}
}


	

/* *****************************************************************************
 * GetResponseXML Method
 * Returns the responseXML of the HTTP Request.
 * ****************************************************************************/
WAGAjaxUtil.prototype.GetResponseXML = function()
{
	if (! this.XmlHttpReq)
		return null;
	else
		return this.XmlHttpReq.responseXML;
}


/* *****************************************************************************
 * GetDocumentElement Method
 * Returns the document element of the responseXML of the HTTP Request.
 * ****************************************************************************/
WAGAjaxUtil.prototype.GetDocumentElement = function()
{
	if (this.XmlHttpReq
		&& this.XmlHttpReq.responseXML)
		return this.XmlHttpReq.responseXML.documentElement;
	else
		return null;
}


/* *****************************************************************************
 * GetNodeList Method
 * Accepts an XPath string, returns the node list selected by that expression.
 * ****************************************************************************/
WAGAjaxUtil.prototype.GetNodeList = function(xPathStr)
{
	var docEl = this.GetDocumentElement();
	if (docEl)
	{
		if (typeof docEl.selectNodes == 'function')
			return docEl.selectNodes(xPathStr);
		else
			return WAGAjaxUtil.SelectNodes(xPathStr, docEl);
	}
	else
		return null;
}


/* *****************************************************************************
 * _setCallback Method
 * This private method is used to create a slot for the current instance as a
 *   class variable that can be used to refer the onreadystatechange event
 *   back to an instance method.
 * ****************************************************************************/
WAGAjaxUtil.prototype._setCallback = function()
{
	// Find the current slot in the Instances array, store current instance there
	this.Slot = WAGAjaxUtil.Instances.length;
	WAGAjaxUtil.Instances[this.Slot] = this;
	
	// Create a function that calls the OnReadyStateChange method on the
	// instance from the Instances array, assign it as the handler
	var fTxt = 'WAGAjaxUtil.Instances[' + this.Slot + '].OnReadyStateChange();';
	this.XmlHttpReq.onreadystatechange = new Function(fTxt);
}


/* *****************************************************************************
 * selectNodes, selectSingleNode
 * For Netscape and FireFox, create prototype of the selectNodes and
 *   selectSingleNode methods.
 * ****************************************************************************/
if(document.implementation &&
	document.implementation.hasFeature("XPath", "3.0"))
{
	XMLDocument.prototype.selectNodes = function(cXPathString, xNode)
	{
		if(!xNode)
			xNode = this;

		var oNSResolver = this.createNSResolver(this.documentElement)
		var aItems = this.evaluate(cXPathString, xNode, oNSResolver,
			XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
		var aResult = [];
		for (var i=0; i<aItems.snapshotLength; i++)
			aResult[i] = aItems.snapshotItem(i);
		
		return aResult;
	}
	
	XMLDocument.prototype.selectSingleNode = function(cXPathString, xNode)
	{
		if(!xNode)
			xNode = this;

		var xItems = this.selectNodes(cXPathString, xNode);
		if(xItems.length > 0)
			return xItems[0];
		else
			return null;
	}

	Element.prototype.selectNodes = function(cXPathString)
	{
		if(this.ownerDocument.selectNodes)
			return this.ownerDocument.selectNodes(cXPathString, this);
		else
			throw "For XML Elements Only";
	}

	Element.prototype.selectSingleNode = function(cXPathString)
	{	
		if(this.ownerDocument.selectSingleNode)
			return this.ownerDocument.selectSingleNode(cXPathString, this);
		else
			throw "For XML Elements Only";
	}
}


/* *****************************************************************************
 * selectNodes
 * ****************************************************************************/
 
WAGAjaxUtil.SelectNodes = function(xPathStr, xNode)
{
	if (typeof xNode.selectNodes == "function")
		return xNode.selectNodes(xPathStr);

	var nodeList = null;
	var paths = xPathStr.split('/');
		
	for (var i=0; i<paths.length; i++)
	{
		if (paths[i].length == 0)
			continue;

		var curNode = (nodeList == null || nodeList.length == 0)
			? xNode : nodeList[0];

		nodeList = curNode.getElementsByTagName(paths[i]);
		
		var tmpArray = new Array();
		for (var j=0; j<nodeList.length; j++)
		{
			if (nodeList[j].parentNode == curNode)
				tmpArray[tmpArray.length] = nodeList[j];
		}
		
		nodeList = tmpArray;
	}

	return nodeList;
}
