ajax.js

Summary

Ajax Javascript Library
(c)2006 LAMATEK, Inc.


Version: 2.0

Author: Tom Cole tcole@lamatek.com


Class Summary
AjaxRequest  

Method Summary
static Object getXMLHttpRequest()
          

Generic function that returns a new request, but does not map it to the xmlhttp variable.

Returns - an XMLHttpRequest

/**
 @fileoverview
 Ajax Javascript Library<br/>
 (c)2006 LAMATEK, Inc.<br/>
  @author Tom Cole tcole@lamatek.com
 @version 2.0
*/

/**
 <p>
 Cross-browser implementation to obtain and process a XMLHttpRequest instance.
 It removes the need to worry about cross-browser implementation issues and provides
 a simple, consistent interface to XMLHttpRequests.
 </p>
 <p>
 Here's a simple example: 
 <ol>
<li> <p>There is a form with two fields, item_no and qty. It also has a span with id price
    and two buttons, one for checking the price and one to add to the order:</p>
    <code>
 	&lt;form action="http://www.mysite.com/add_item.php" method="POST"><br/>
 	&lt;p>Item no.: &lt;input type="text" name="item_no" size="30"/>&lt;/p><br/>
 	&lt;p>Qty.: &lt;input type="text" name="qty" size="5"/>&lt;/p><br/>
 	&lt;p>Price: &lt;span id="price">&lt;/span>&lt;/p><br/>
 	&lt;p>&lt;input type="button" value="Check Price" onclick="javascript:checkPrice();"/><br/>
 	   &lt;input type="submit" value="Add Item"/>&lt;/p><br/>
 	&lt;/form><br/>
 	</code>
 	
<li> <p>When the Check Price button is clicked it calls the checkPrice() method. Here's where
   AJAX magic happens. The checkPrice function looks like this:</p>
 	<code>
 	 <p>var ajax = new AjaxRequest();</p>
 	
	 function checkPrice() {<br/>
 		&nbsp;&nbsp;String item = document.getElementById("item_no").value;<br/>
	 	&nbsp;&nbsp;String qty = document.getElementById("qty").value;<br/>
	 	&nbsp;&nbsp;ajax.doXMLRequest("GET", "http://www.mysite.com/check_price?item_no=" + item_no + "&qty=" + qty, updatePrice);<br/>
	 }<br/>
 	</code>
   <p>The doXMLRequest line will submit the request to the check_price.php script, using
   the GET method. It will also pass control to your updatePrice() method once completed.</p>
   
<li> <p>When the request has completed, the XML document has been stored and your
    updatePrice method is called. The updatePrice method can obtain reference to the
    XML DOM object by simply calling getValue(). (If we had used getTextRequest
    instead of getXMLRequest, we would get a String variable by calling getValue()).
    </p><p>
    For this example we'll assume an XML document something like this:
    </p>
    <code>
    &lt;data><br/>
    	&nbsp;&nbsp;&lt;item_no>123456&lt;/item_no><br/>
    	&nbsp;&nbsp;&lt;qty>1000&lt;/qty><br/>
    	&nbsp;&nbsp;&lt;price>10.50&lt;/price><br/>
    &lt;/data><br/>
    </code>
    <p>
    We then simply parse the XML and update the price:
    </p>
    <code>
      function updatePrice() {<br/>
      	&nbsp;&nbsp;var xml = ajax.getValue();<br/>
      	&nbsp;&nbsp;var root = xml.documentElement;<br/>
      	&nbsp;&nbsp;var item_no = root.getElementsByTagName('item_no')[0].firstChild.data;<br/>
      	&nbsp;&nbsp;var qty = root.getElementsByTagName('qty')[0].firstChild.data;<br/>
      	&nbsp;&nbsp;var price = root.getElementsByTagName('price')[0].firstChild.data;<br/>
      	&nbsp;&nbsp;document.getElementById("item_no").value = item_no;<br/>
      	&nbsp;&nbsp;document.getElementById("qty").value = qty;<br/>
      	&nbsp;&nbsp;document.getElementById("price").innerHTML = "$" + price;<br/>
      }<br/>
     </code>
<li> <p>That's about it. All we have to do is:</p>
<ul>
	<li> Create an AjaxRequest object.
	<li> Create a request using AjaxRequest.doXMLRequest or AjaxRequest.doTextRequest.
	<li> Get the returned value using AjaxRequest.getValue.
	<li> Process the results.
</ul>
 </p>
*/
function AjaxRequest () {
	
	/**Current debugging status. */
	var debug = false;
	
	/**Handle to a loading display div.*/
	var async = true;
	
	/**The resulting value (either a String or DOM object based on request type.*/
	var value = null; 
	
	/**The XMLHttpRequest used to send & receive data.*/
	var xmlhttp = null; 
	
	/**Holds the response code of the last request made.*/
	var response_code = null;
	
	/**Holds the completion status of the last request.*/
	var completed = false;
	
	/**The method that will get called on a successful request.*/
	var handler = null;
	
	/**Attempts to hold browser type. Only works after an AjaxRequest has been created.*/
	var browser = (navigator.appName.indexOf('Microsoft') >= 0);
	
	/**The text to display while requests are processing.*/
	var message = "Please wait...";
	
	/**Holds the last request type.*/
	var type = "text";	
	
	/**Provides DOM based drag capabilities for the log window.*/
	var Drag = {

		obj : null,
	
		init : function(o, oRoot, minX, maxX, minY, maxY, bSwapHorzRef, bSwapVertRef, fXMapper, fYMapper)
		{
			try {
				o.onmousedown	= Drag.start;
		
				o.hmode			= bSwapHorzRef ? true : false ;
				o.vmode			= bSwapVertRef ? false : true ;
		
				o.root = oRoot && oRoot != null ? oRoot : o ;
		
				if (o.hmode  && isNaN(parseInt(o.root.style.left  ))) o.root.style.left   = "0px";
				if (o.vmode  && isNaN(parseInt(o.root.style.top   ))) o.root.style.top    = "0px";
				if (!o.hmode && isNaN(parseInt(o.root.style.right ))) o.root.style.right  = "0px";
				if (!o.vmode && isNaN(parseInt(o.root.style.bottom))) o.root.style.bottom = "0px";
		
				o.minX	= typeof minX != 'undefined' ? minX : null;
				o.minY	= typeof minY != 'undefined' ? minY : null;
				o.maxX	= typeof maxX != 'undefined' ? maxX : null;
				o.maxY	= typeof maxY != 'undefined' ? maxY : null;
		
				o.xMapper = fXMapper ? fXMapper : null;
				o.yMapper = fYMapper ? fYMapper : null;
		
				o.root.onDragStart	= new Function();
				o.root.onDragEnd	= new Function();
				o.root.onDrag		= new Function();
			}
			catch(e) {
				
			}
		},
	
		start : function(e)
		{
			try {
				var o = Drag.obj = this;
				e = Drag.fixE(e);
				var y = parseInt(o.vmode ? o.root.style.top  : o.root.style.bottom);
				var x = parseInt(o.hmode ? o.root.style.left : o.root.style.right );
				o.root.onDragStart(x, y);
		
				o.lastMouseX	= e.clientX;
				o.lastMouseY	= e.clientY;
		
				if (o.hmode) {
					if (o.minX != null)	o.minMouseX	= e.clientX - x + o.minX;
					if (o.maxX != null)	o.maxMouseX	= o.minMouseX + o.maxX - o.minX;
				} else {
					if (o.minX != null) o.maxMouseX = -o.minX + e.clientX + x;
					if (o.maxX != null) o.minMouseX = -o.maxX + e.clientX + x;
				}
		
				if (o.vmode) {
					if (o.minY != null)	o.minMouseY	= e.clientY - y + o.minY;
					if (o.maxY != null)	o.maxMouseY	= o.minMouseY + o.maxY - o.minY;
				} else {
					if (o.minY != null) o.maxMouseY = -o.minY + e.clientY + y;
					if (o.maxY != null) o.minMouseY = -o.maxY + e.clientY + y;
				}
		
				document.onmousemove	= Drag.drag;
				document.onmouseup		= Drag.end;
		
				return false;
			}
			catch(e) {
				
			}
		},
	
		drag : function(e)
		{
			try {
				e = Drag.fixE(e);
				var o = Drag.obj;
		
				var ey	= e.clientY;
				var ex	= e.clientX;
				var y = parseInt(o.vmode ? o.root.style.top  : o.root.style.bottom);
				var x = parseInt(o.hmode ? o.root.style.left : o.root.style.right );
				var nx, ny;
		
				if (o.minX != null) ex = o.hmode ? Math.max(ex, o.minMouseX) : Math.min(ex, o.maxMouseX);
				if (o.maxX != null) ex = o.hmode ? Math.min(ex, o.maxMouseX) : Math.max(ex, o.minMouseX);
				if (o.minY != null) ey = o.vmode ? Math.max(ey, o.minMouseY) : Math.min(ey, o.maxMouseY);
				if (o.maxY != null) ey = o.vmode ? Math.min(ey, o.maxMouseY) : Math.max(ey, o.minMouseY);
		
				nx = x + ((ex - o.lastMouseX) * (o.hmode ? 1 : -1));
				ny = y + ((ey - o.lastMouseY) * (o.vmode ? 1 : -1));
		
				if (o.xMapper)		nx = o.xMapper(y)
				else if (o.yMapper)	ny = o.yMapper(x)
		
				Drag.obj.root.style[o.hmode ? "left" : "right"] = nx + "px";
				Drag.obj.root.style[o.vmode ? "top" : "bottom"] = ny + "px";
				Drag.obj.lastMouseX	= ex;
				Drag.obj.lastMouseY	= ey;
		
				Drag.obj.root.onDrag(nx, ny);
				return false;
			}
			catch(e) {
				
			}
		},
	
		end : function()
		{
			try {
				document.onmousemove = null;
				document.onmouseup   = null;
				Drag.obj.root.onDragEnd(	parseInt(Drag.obj.root.style[Drag.obj.hmode ? "left" : "right"]), 
											parseInt(Drag.obj.root.style[Drag.obj.vmode ? "top" : "bottom"]));
				Drag.obj = null;
			}
			catch(e) {
				
			}
		},
	
		fixE : function(e)
		{
			try {
				if (typeof e == 'undefined') e = window.event;
				if (typeof e.layerX == 'undefined') e.layerX = e.offsetX;
				if (typeof e.layerY == 'undefined') e.layerY = e.offsetY;
				return e;
			}
			catch(e) {
				
			}
		}
	};
	
	/**
	<p>
	This method creates an XMLHttpRequest object, reads the response as
	text, attempts to create a JSON object and passes that response as 
	a parameter to the method name indicated.
	</p>
	<p>
	This method is used by doJSONRequest and should not be called directly by
	the end-user.
	</p>
	@param {Function} method The end-user defined method that will be called upon successful completion of the request.
	*/
	getJSONRequest = function (method) {
		type = "json";
		log("----Registering client handler method for text request:<br/><blockquote><pre>" + method.toString().replace(/</g, "&lt;").replace(/>/g, "&gt;") + "</pre></blockquote>",1);
		handler = method;
		xmlhttp = getRequest();
		if (xmlhttp) {
	  		xmlhttp.onreadystatechange = parseJSONResponse;
	  	}
	}
	
	/**
	<p>
	This method creates an XMLHttpRequest object, reads the response as
	an XML document and passes that response as a DOM object parameter to 
	the method name indicated. 
	</p>
	<p>
	This method is used by doXMLRequest and should not be called directly by
	the end-user.
	</p>
	@param {Function} method The end-user defined method that will be called upon successful completion of the request.
	*/
	getXMLRequest = function (method) {
		type = "xml";
		log("----Registering client handler method for text request:<br/><blockquote><pre>" + method.toString().replace(/</g, "&lt;").replace(/>/g, "&gt;") + "</pre></blockquote>",1);
		handler = method;
		xmlhttp = getRequest();
		if (xmlhttp) {
	  		xmlhttp.onreadystatechange = parseXMLResponse;
	  	}
	}
	
	/**
	<p>
	This method creates an XMLHttpRequest object, reads the response as
	text and passes that response as a parameter to the method name indicated.
	</p>
	<p>
	This method is used by doTextRequest and should not be called directly by
	the end-user.
	</p>
	@param {Function} method The end-user defined method that will be called upon successful completion of the request.
	*/
	getTextRequest = function (method) {
		type = "text";
		log("----Registering client handler method for text request:<br/><blockquote><pre>" + method.toString().replace(/</g, "&lt;").replace(/>/g, "&gt;") + "</pre></blockquote>",1);
		handler = method;
		xmlhttp = getRequest();
		if (xmlhttp) {
	  		xmlhttp.onreadystatechange = parseTextResponse;
	  	}
	}
	
	/**
	<p>
	Used by getXMLRequest and getTextRequest to generate a cross-browser
	XMLHttpRequest object. This method should not be called directly by
	the end-user.
	</p>
	@type XMLHttpRequest
	*/
	getRequest = function () {
	    completed = false;
	    var xml;
	    /*@cc_on
	    @if (@_jscript_version >= 5) 
	        try {
	          xml = new ActiveXObject("Msxml2.XMLHTTP");
	          browser = true;
	        } 
	        catch (e) {
	          try {
	            xml = new ActiveXObject("Microsoft.XMLHTTP");
	            browser = true;
	          } 
	          catch (E) {
	            xml = false;
	          }
	        }
	    @else
	        xml = false;
	    @end @*/
	    if (!xml && typeof XMLHttpRequest != 'undefined') {
	        try {
	          xml = new XMLHttpRequest();
	          browser = false;
	        } 
	        catch (e) {
	          xml = false;
	          browser = false;
	        }
	    }
	    if (! xml) {
	    	this.log("------Unable to create XmlHTTPRequest.", 3);
	    }
	    return xml;
	}
	
	/**
	<p>
	This method reads a text response, attempts to create a JSON object
	out of it and calls the registered handler method. Called by getJSONRequest. 
	This method	should not be called directly by the end-user.
	</p>
	*/
	parseJSONResponse = function () {
		if (xmlhttp.readyState == 4) {
			log("------XmlHTTPRequest readystate is OK...");
			response_code = xmlhttp.status;
			completed = true;
	       	if (response_code == 200) {
	       		log("------XmlHTTPRequest status is OK...");
	       		log("");
	       		log("------Response received:<br/><blockquote><pre>" + xmlhttp.responseText + "</pre></blockquote>",1);
	       		try {
		    		value = eval('(' + xmlhttp.responseText + ')');   
			    }
			    catch(e) {
			    	log("------Error occurred assigning response to value: " + e.message + "...", 3);
			    	value = null
			    }
			    if (handler) {
					log("Forwarding control to client handler for XML request...");
			    	handler.call(this);  	
			    }
	       	}
	       	else {
	       		log("------XmlHTTPRequest status returned " + response_code + "...", 3);
	       		value = null;
	       	}
	       	if (document.getElementById('loadingDiv')) {
				document.getElementById('loadingDiv').style.display = 'none';
			}
	    }
	    else {
	    	log("------XmlHTTPRequest readystate is " + xmlhttp.readyState + "...", 2);
	    }
	}
	
	/**
	<p>
	This method reads the XML response and passes it as a DOM object parameter
	to the registered handler method. Called by getXMLRequest. This method
	should not be called directly by the end-user.
	</p>
	*/
	parseXMLResponse = function () {
		if (xmlhttp.readyState == 4) {
			log("------XmlHTTPRequest readystate is OK...");
			response_code = xmlhttp.status;
			completed = true;
	       	if (response_code == 200) {
	       		if (debug == true) {
		       		log("------XmlHTTPRequest status is OK...");
		       		var formatted = xmlhttp.responseText.replace(/</g, "&lt;").replace(/>/g, "&gt;");
	       			log("------Response received:<br/><blockquote><pre>" + formatted + "</pre></blockquote>",1);
	       		}
				value = xmlhttp.responseXML;
	    		if (handler) {
					log("Forwarding control to client handler for XML request...");
		    		handler.call(this);     	
	    		}
	       	}
	       	else {
	       		log("------XmlHTTPRequest status returned " + response_code + "...", 3);
	       		value = null;
	       	}
	       	if (document.getElementById('loadingDiv')) {
				document.getElementById('loadingDiv').style.display = 'none';
			}
	    }
	    else {
	    	log("------XmlHTTPRequest readystate is " + xmlhttp.readyState + "...", 2);
	    }
	}
	
	/**
	<p>
	This method reads the text response and passes it as a parameter
	to the registered handler method. Called by getTextRequest. This method
	should not be called directly by the end-user.
	</p>
	*/
	parseTextResponse = function () {
		if (xmlhttp.readyState == 4) {
			log("------XmlHTTPRequest readystate is OK...");
			response_code = xmlhttp.status;
			completed = true;
	       	if (response_code == 200) {
	       		log("------XmlHTTPRequest status is OK...");
	       		log("------Response received:<br/><blockquote><pre>" + xmlhttp.responseText + "</pre></blockquote>",1);
				value = xmlhttp.responseText;
	    		if (handler) {
	    			log("Forwarding control to client handler for XML request...");
		    		handler.call(this);     	
	    		}
	       	}
	       	else {
	       		log("------XmlHTTPRequest status returned " + response_code + "...", 3);
	       		value = null;
	       	}
	       	if (document.getElementById('loadingDiv')) {
				document.getElementById('loadingDiv').style.display = 'none';
			}
	    }
	    else {
	    	log("------XmlHTTPRequest readystate is " + xmlhttp.readyState + "...", 2);
	    }
	}

	/**
	<p>
	Called by the client javascript code to initiate a request that is going to return
	a JSON text string that is to be converted into a JSON object. 
	The resulting object will be stored in the value variable and
	can be retrieved using getValue();
	</p>
	@param {String} url The url to the server resource that will handle the request. (REQUIRED)
	@param {String} method The HTTP method to send the request. Must be "GET" or "POST". Default is "GET" (OPTIONAL)
	@param {String} parameters A url formatted list of parameter names and values. Parameters are specified as name=value&name=value.... Default is null. (OPTIONAL)
	@param {Function} callback The end-user defined method that will be called upon successful completion of the request. Default is null. (OPTIONAL)
	@param {Boolean} asynchronous. Set to true if the request is to be asynchronous, false if not. Default is true. (OPTIONAL)
	*/
	this.doJSONRequest = function (url, method, parameters, callback, asynchronous) {
		log("Beginning new JSON request...");
		if (url) {
			var defMethod = "GET";
			if (method) {
				defMethod = method;
			}
			log("--Request method set to " + defMethod + "...");
			async = true;
			if (! asynchronous) {
				async = asynchronous;
			}
			log("--Request set to asynchronous: " + async + "...");
			showLoadingDiv();
			getJSONRequest(callback);
			xmlhttp.open(defMethod, url, async);
			if (parameters) {
				xmlhttp.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
			}
			else {
				parameters = null;
			}
			log("--Sending request...");
			xmlhttp.send(parameters);
		}
		else {
			log("--Request URL is not set. Unable to process request.", 3);
		}
	}
	
	/**
	<p>
	Called by the client javascript code to initiate a request that is going to return
	an XML document. The resulting DOM object will be stored in the value variable and
	can be retrieved using getValue();
	</p>
	@param {String} url The url to the server resource that will handle the request. (REQUIRED)
	@param {String} method The HTTP method to send the request. Must be "GET" or "POST". Default is "GET" (OPTIONAL)
	@param {String} parameters A url formatted list of parameter names and values. Parameters are specified as name=value&name=value.... Default is null. (OPTIONAL)
	@param {Function} callback The end-user defined method that will be called upon successful completion of the request. Default is null. (OPTIONAL)
	@param {Boolean} asynchronous. Set to true if the request is to be asynchronous, false if not. Default is true. (OPTIONAL)
	*/
	this.doXMLRequest = function (url, method, parameters, callback, asynchronous) {
		log("Beginning new XML request...");
		if (url) {
			var defMethod = "GET";
			if (method) {
				defMethod = method;
			}
			log("--Request method set to " + defMethod + "...");
			async = true;
			if (! asynchronous) {
				async = asynchronous;
			}
			log("--Request set to asynchronous: " + async + "...");
			showLoadingDiv();
			getXMLRequest(callback);
			xmlhttp.open(defMethod, url, async);
			if (parameters) {
				xmlhttp.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
			}
			else {
				parameters = null;
			}
			log("--Sending request...");
			xmlhttp.send(parameters);
		}
		else {
			log("--Request URL is not set. Unable to process request.", 3);
		}
	}
	
	/**
	<p>
	Called by the client javascript code to initiate a request that is going to return
	a text string OR a request that returns an XML document that is desired as a string, 
	rather than a DOM object. The resulting string will be stored in the value variable and
	can be retrieved using getValue();
	</p>
	@param {String} url The url to the server resource that will handle the request. (REQUIRED)
	@param {String} method The HTTP method to send the request. Must be "GET" or "POST". Default is "GET" (OPTIONAL)
	@param {String} parameters A url formatted list of parameter names and values. Parameters are specified as name=value&name=value.... Default is null. (OPTIONAL)
	@param {Function} callback The end-user defined method that will be called upon successful completion of the request. Default is null. (OPTIONAL)
	@param {Boolean} asynchronous. Set to true if the request is to be asynchronous, false if not. Default is true. (OPTIONAL)
	*/
	this.doTextRequest = function (url, method, parameters, callback, asynchronous) {
		log("Beginning new text request...");
		if (url) {
			var defMethod = "GET";
			if (method) {
				defMethod = method;
			}
			log("--Request method set to " + defMethod + "...");
			async = true;
			if (! asynchronous) {
				async = asynchronous;
			}
			log("--Request set to asynchronous: " + async + "...");
			showLoadingDiv();
			getTextRequest(callback);
			xmlhttp.open(defMethod, url, async);
			if (parameters) {
				xmlhttp.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
			}
			else {
				parameters = null;
			}
			log("--Sending request...");
			xmlhttp.send(parameters);
		}
		else {
			log("--Request URL is not set. Unable to process request.", 3);
		}
	}
	
	/**
	<p>
	Convenience method that returns the completed status of the request.
	Returns - true if readyState = 4, otherwise false.
	</p>
	@type Boolean 
	*/
	this.isCompleted = function () {
		return completed;
	}
	
	/**
	<p>
	Convenience function that returns the value returned by the request.
	Returns - a String or XML DOM Object based on the type of request made.
	</p>
	@type Variant
	*/
	this.getValue = function () {
		return value;
	}
	
	/**
	<p>
	Convenience function that transforms the current XML DOM value
	based on the XSL file specified in the url, and places it's contents in
	the suggested DOM element.
	</p><p>
	Returns - a transformed XML string or null if the XSL could not be found.
	</p>
	@param {String} url The url of the XSL document to use for transformation.
	@type XML DOM Object
	*/
	this.transformValueInto = function (url, element) {
		if (type == "xml") {
			if (value && url && element) {
				if (typeof XSLTProcessor != 'undefined') {
					var processor = new XSLTProcessor();
					var request = getXMLHttpRequest();
					if (request) {
						request.open("GET", url, false);
						request.send(null);
						var xsl = request.responseXML;
						processor.importStylesheet(xsl);
						var fragment = processor.transformToFragment(value, document);
						if (element)
							element.appendChild(fragment);
					}
					else {
						return;
					}
				}
				else {
					var stylesheet = new ActiveXObject("Msxml2.DOMDocument.3.0");
					if (stylesheet) {
						stylesheet.async = false;
						stylesheet.load(url);
						var results = new ActiveXObject("Msxml2.DOMDocument.3.0");
						results.async = false;
						results.validateOnParse = true;
						value.transformNodeToObject(stylesheet, results);
						if (element) 
							element.innerHTML = results.documentElement.xml;
					}
					else {
						return;
					}	
				}
			}
		}
		else if (type == "text") {
			if (element && value) {
				element.innerHTML = value;
			}
		}
		else if (type == "json") {
			if (element && value) {
				element.append(value);
			}
		}
		else {
			return;
		}
	}
	
	/**
	<p>
	Convenience function that attempts to retrieve the number of XML elements 
	with the given name that exist in the current value object. This assumes that
	<ol>
	<li> The value is an XML DOM object
	</ol>
	Returns - the number of nodes with the given name or 0 if none exist.
	</p>
	@param {String} nodeName The node name to search for.
	@type int
	*/
	this.getNodeCount = function (nodeName) {
		try {
			var root = value.documentElement;
			return root.getElementsByTagName(nodeName).length;
		}
		catch (e) {
			return 0;
		}
	}
	
	/**
	<p>
	Convenience function that attempts to retrieve an XML DOMNode from the value
	variable if:
	<ol>
	<li> It is an XML DOM object
	<li> It has at least one tag with the given name.
	</ol>
	Otherwise, results are inconsistent. </p>
	<p>
	Returns - The DOMNode of the 'index' instance of 'nodeName' or null if it doesn't exist.
	</p>
	@param {String} nodeName The name of the node.
	@param {int} index The index. i.e. If there are expected to be 3 nodes with the name
	        'item', then you would enter 0 for the first instance, 1 for the
	        second instance and 2 for the third instance. If no index is provided
	        then 0 is assumed.
	@type DOMNode 
	*/
	this.getNode = function (nodeName, index) {
		if (! index)
			index = 0;
		try {
			var root = value.documentElement;
			var node = root.getElementsByTagName(nodeName)[index];
			return node;
		}
		catch (e) {
			return null;
		}
	}
	
	/**
	<p>
	Convenience function that attempts to retrieve an XML value from the value
	variable if:
	<ol>
	<li> It is an XML DOM object
	<li> It has at least one tag with the given name.
	</ol>
	Otherwise, results are inconsistent. 
	</p>
	<p>
	Returns - The value of the 'index' instance of 'nodeName' or null if it doesn't exist.
	</p>
	@param {String} nodeName The name of the node 
	@param {int} index The index. i.e. If there are expected to be 3 nodes with the name
	        'item', then you would enter 0 for the first instance, 1 for the
	        second instance and 2 for the third instance. If no index is provided
	        then 0 is assumed.
	@type String 
	*/
	this.getValueForNode = function (nodeName, index) {
		if (! index)
			index = 0;
		try {
			var root = value.documentElement;
			var nodeValue = root.getElementsByTagName(nodeName)[index].firstChild.data;	
			return nodeValue;
		}
		catch (e) {
			return null;
		}
	}
	
	/**
	<p>
	Convenience function that attempts to retrieve the number of XML elements 
	with the given name that exist under the parent node. This assumes that
	<ol>
	<li> The value is an XML DOM object
	</ol>
	Returns - the number of nodes with the given name or 0 if none exist.
	</p>
	@param {String} nodeName The node name to search for.
	@type int
	*/
	this.getNodeCountByParent = function (parentNode, nodeName) {
		try {
			return parentNode.getElementsByTagName(nodeName).length;
		}
		catch (e) {
			return 0;
		}
	}
	
	/**
	<p>
	Convenience function that attempts to retrieve an XML value from the value
	variable if:
	<ol>
	<li> It is an XML DOM object
	<li> It has at least one tag with the given name.
	</ol>
	Otherwise, results are inconsistent. 
	</p>
	<p>
	Returns - DOMNode of the 'index' instance of 'nodeName' with 'parentNode' as it's parent, or null if it doesn't exist.
	</p>
	@param {DomNode} parentNode The parent DOMNode under which the child node should be found.
	             See #getNode
	@param {String} nodeName The name of the node 
	@param {int} index The index. i.e. If there are expected to be 3 nodes with the name
	        'item', then you would enter 0 for the first instance, 1 for the
	        second instance and 2 for the third instance. If no index is provided
	        then 0 is assumed.
	@type DOMNode
	*/
	this.getNodeByParent = function (parentNode, nodeName, index) {
		if (! index) {
			index = 0;
		}
		try {
			var node = parentNode.getElementsByTagName(nodeName)[index];
			return node;
		}
		catch (e) {
			return null;
		}
	}
	
	/**
	<p>
	Convenience function that attempts to retrieve an XML value from the value
	variable if:
	<ol>
	<li> It is an XML DOM object
	<li> It has at least one tag with the given name.
	</ol>
	Otherwise, results are inconsistent. 
	</p>
	<p>
	Returns - The value of the 'index' instance of 'nodeName' or null if it doesn't exist.
	</p>
	@param {DomNode} parentNode The parent DOMNode under which the child node should be found.
	             See #getNode
	@param {String} nodeName The name of the node 
	@param {int} index The index. i.e. If there are expected to be 3 nodes with the name
	        'item', then you would enter 0 for the first instance, 1 for the
	        second instance and 2 for the third instance. If no index is provided
	        then 0 is assumed.
	@type String 
	*/
	this.getValueForNodeByParent = function (parentNode, nodeName, index) {
		if (! index) {
			index = 0;
		}
		try {
			var nodeValue = parentNode.getElementsByTagName(nodeName)[index].firstChild.data;
			return nodeValue;
		}
		catch (e) {
			return null;
		}
	}
	
	/**
	<p>
	Returns the HTTP response code of the last XMHttpRequest made, or null if none have
	been made.
	</p>
	<p>
	Returns - The response code of the last XMLHttpRequest made, or null.
	</p>
	@type int 
	*/
	this.getResponseCode = function () {
		return response_code;
	}
	
	/**
	<p>
	Returns if the last detected browser was IE or not. 
	</p>
	<p>
	Returns - True if IE was last detected, false otherwise.
	</p>
	@type boolean
	*/
	this.isIE = function () {
		if (browser) {
			return browser;
		}
		else {
			try {
				var test = new ActiveXObject("Msxml2.XMLHTTP");
				browser = true;
			}
			catch (e) {
				browser = false;
			}	
			return browser;
		}
	}
	
	/**
	 * <p>
	 * Displays a "loading" div message for non-asynchronous requests.
	 * Provides public access to the private method.
	 * </p>
	 */
	showLoadingDiv = function () {
		if (async == true) {
			if (document.getElementById('loadingDiv')) {
				document.getElementById('loadingDiv').style.display = 'block';
			}
			else {
				var loading = document.createElement("div");
				loading.id = 'loadingDiv';
				loading.innerHTML = message;
				loading.style.background = '#cc0000';
				loading.style.color = '#ffffff';
				loading.style.position = 'fixed';
				loading.style.top = 0;
				loading.style.right = 0;
				loading.style.paddingLeft = 5;
				loading.style.paddingRight = 5;
				loading.style.fontFamily = "Arial";
				loading.style.fontSize = "12";
				document.body.appendChild(loading);
			}
		}
	}
	
	/**
	 * <p>
	 * Creates a floating window (if necessary) and adds a message to the log.
	 * </p>
	 * @param message A message to add to the log window.
	 */
	this.log = function (message, severity) {
		log(message, severity);
	}
	
	/**
	 * <p>
	 * Creates a floating window (if necessary) and adds a message to the log.
	 * This version is internally accessible.
	 * </p>
	 * @param message A message to add to the log window.
	 */
	log = function (message, severity) {
		if (debug) {
			var bg = "#ffffff";
			if (severity) {
				if (severity > 2) {
					bg = "#ff0000";
				}
				else if (severity > 1) {
					bg = "#ffb500";
				}
				else if (severity > 0) {
					bg = "#ffff00";
				}
			}
			if (! document.getElementById("loggerDiv")) {
				var logger = document.createElement("div");
				logger.id = "loggerDiv";
				if (browser) {
					logger.style.position = "absolute";
				}
				else {
					logger.style.position = "fixed";
				}
				logger.style.top = "25px";
				logger.style.right = "25px";
				logger.style.display = "inline";
				logger.style.width = "400";
				logger.style.height = "400";
				logger.style.border = "1px solid #000000";
				logger.style.background = "#cccccc";
				var loggerBar = document.createElement("div");
				loggerBar.id = "loggerBar";
				loggerBar.style.height = 22;
				loggerBar.style.textAlign = "right";
				loggerBar.innerHTML = "<span width=\"100%\"><input type=\"button\" value=\"Clear\" onclick=\"document.getElementById('loggerStatusDetails').removeChild(document.getElementById('loggingDetailLines'));\"/><input type=\"button\" value=\"X\" onclick=\"document.body.removeChild(document.getElementById('loggerDiv'));\"/></span>";
				logger.appendChild(loggerBar);
				var loggerStatus = document.createElement("div");
				loggerStatus.style.overflow = "auto";
				loggerStatus.id = "loggerStatusDetails";
				loggerStatus.style.background = "#ffffff";
				loggerStatus.style.width = "100%";
				loggerStatus.style.height = 378;
				logger.appendChild(loggerStatus);
				document.body.insertBefore(logger, document.body.firstChild);
			}
			if (! document.getElementById('loggingDetailLines')) {
				var loggerDiv = document.getElementById("loggerStatusDetails");
				var loggingDiv = document.createElement("div");
				loggingDiv.id = "loggingDetailLines";
				loggerDiv.appendChild(loggingDiv);
			}
			var loggingDiv = document.getElementById('loggingDetailLines');
			var logLine = document.createElement("div");
			logLine.style.borderTop = "1px solid #cccccc";
			logLine.innerHTML = message;
			logLine.style.background = bg;
		    loggingDiv.appendChild(logLine);
		    Drag.init(document.getElementById('loggerBar'), document.getElementById('loggerDiv'));
		}
	}
	
	/**
	 * <p>Sets the display message that is presented while an AjaxRequest is
	 * processing.
	 * </p>
	 * @param text The message to display.
	 */
	 this.setDisplayMessage = function (text) {
	 	message = text;
	 }
	 
	 /**
	  * <p>
	  * Turns the debugging window on or off.
	  * </p>
	  * @param show True or false.
	  */
	  this.setDebugging = function (show) {
	  	debug = show;
	  }
}

/**
<p>Generic function that returns a new request, but does not map it to the xmlhttp variable.</p>
<p>Returns - an XMLHttpRequest</p>
*/
function getXMLHttpRequest() {
	var xml;
	/*@cc_on
	@if (@_jscript_version >= 5)
	  try {
	    xml = new ActiveXObject("Msxml2.XMLHTTP");
	  } 
	  catch (e) {
	    try {
	      xml = new ActiveXObject("Microsoft.XMLHTTP");
	    } 
	    catch (E) {
	      xml = false;
	    }
	  }
	@else
	 xml = false;
	@end @*/
	 if (!xml && typeof XMLHttpRequest != 'undefined') {
	  try {
	    xml = new XMLHttpRequest();
	  } 
	  catch (e) {
	    xml = false;
	  }
	}
	if (xml) {
		return xml;
	}
	else {
		return null;
	}
}


Documentation generated by JSDoc on Tue Feb 27 10:07:22 2007