//
//	Request functions
//
//	Process asynchronous requests to a server.
//	Requests are:
//		loadHTMLContent		to load HTML into a specified control
//		makeRequest		to send a request to a URL and call a function with the results
//		sendRequest		to send a request to the address server and call a function with the result
//
function createRequestor()
//
// Creates an XMLHttpRequest object.  Returns the appropriate browser object or null
{
	var req=null;
	try {
		req=new ActiveXObject("Msxml2.XMLHTTP");
	} catch(e) {
		try {
			req=new ActiveXObject("Microsoft.XMLHTTP");
		} catch(oc) {
			req=null;
		}
	}
	if(!req && typeof XMLHttpRequest != "undefined") {
		req=new XMLHttpRequest()
	}
	return req
}
var _requestor=false;								// requestor used for all requests
var _queuedItems = new Array();							// array of queued requests
function sendRequest(queuedItem)
//
//	Send the queued request to the url
{
	if (!_requestor) {							// do we have an XMLHttpRequest object yet?
		_requestor = createRequestor();					// no - make one
	}
	if (queuedItem.data) {							// is there data for this request?
		_requestor.open('POST', queuedItem.url, true);			// Yes use a POST
	} else {
		_requestor.open('GET', queuedItem.url, true);			// No - a GET is required
	}
	_requestor.onreadystatechange = processResponse;			// set up the function to handle the response
	try {
		_requestor.send(queuedItem.data);				// make it happen
	} catch(e) {
		_requestor = false;						// get rid of the failing requestor
		sendRequest(queuedItem);					// and create a new one
	}
}
function processResponse()
//
// The server request has changed state.  If it has finished then call the function or load the HTML text
{
	if (_requestor.readyState == 4) {					// Finished loading the response?
		var request = _queuedItems.shift();				// remove the first entry from the queue
		if (_requestor.responseText  && request && request != 'undefined') {	// have we received a response that we know what to do with?
			var response = _requestor.responseText;			// extract the text
			if (request.funct) {					// does the caller want to call a function?
				var xml = _requestor.responseXML;		// yes extract the XML
				if (_requestor.status >= 200 && _requestor.status < 300) { // this is an OK response?
					request.funct(false, xml, response);	// and call the function with the XML and text
				} else {					// this is an invalid response
					var err = _requestor.status + " " + _requestor.statusText;
					request.funct(err, xml, response);	// call the function with a fail reason
				}
			} else if (request.ctrl) {				// there is no function to call is there a control to load?
				if (_requestor.status >= 200 && _requestor.status < 300) // this is an OK response?
					request.ctrl.innerHTML=response;	// load the received HTML into 
			} else {						// the control
			}							// we have no function or control - do nothing
		}
		if (_queuedItems.length) {					// are there any entries queued?
			sendRequest(_queuedItems[0]);				// yes send the first entry in the queue
		}

	}
}
function queuedRequest(url, ctrl, funct, data)
// 
// Constructor for a queuedRequest
//
//	url		The url that fulfills the request
//	ctrl		The control that returned HTML text is to be loaded into
//	funct		The function to be called wiht the result - call if funct(xml, text)
//	data		Data to be posted to the url
{
	this.ctrl = ctrl;
	this.url = url;
	this.funct = funct;
	this.data = data;
}	
function loadHTMLContent(url, ctrl, data) 
//
// Load HTML content into a control.  This allows for queued requests so if a request is outstanding 
// then any new ones are queued
{
	if (_queuedItems.push(new queuedRequest(url, ctrl, null, data)) == 1) {// Is this the first entry in the queue?
		sendRequest(_queuedItems[0]);				// yes send it
	}
}
function makeRequest(url, funct, data)
//
// make a server request and call a function when the data is returned
//	url		The url that fulfills the request
//	funct		The function to be called with the result - call funct(success, xml, text)
{
	if (_queuedItems.push(new queuedRequest(url, null, funct, data)) == 1) {
		sendRequest(_queuedItems[0]);
	}
}
/*
function serverRequest(request, qualifier, procFunctionName)
//
//	Make a request of the server - This will utilize the serveAddresses server to handle other requests
//	Call this function when a request needs to be made
//
//	request		The type of request - so far abn for ABN lookup, email for email address validation or delay to delay response
//	qualifier	request qualifier
//	nextcontrol	The control to receive focus when address selection is complete
{
	if (qualifier && qualifier > "") {					// Is there a question to ask?
		var message = '<?xml version="1.0" encoding="ISO-8859-1"?><lookup><type>'+request+'</type><qualifier>'+qualifier+'</qualifier></lookup>';
		var requestURL = location.protocol + "//" + location.hostname + "/ajax/serveAddress/";
		makeRequest(requestURL, procFunctionName, message);
	}
}
*/
function findNode(xmlnode, nodename)
//
//	Find the nodename in the specified XML fragment and it's siblings
{
	if (!xmlnode)
		return;
	if (xmlnode.nodeName) {							// does this node have a name?
		if (xmlnode.nodeName == nodename) {				// is it the name we are looking for?
			return xmlnode;						// yes - return it
		}
	}
	if (xmlnode.nextSibling) {						// does this node have a sibling?
		return findNode(xmlnode.nextSibling, nodename);			// yes - check it out
	}
	return null;								// that neame isn't here
}

function XMLfield(xmlitem, fieldname)
//
//	Extract a fully qualified field name from an XML document.
{
	var result = null;							// the default result
	var nameparts = fieldname.split(".");					// split the name into its component parts
	var nextnode = xmlitem;
	var thisname = nameparts.shift();					// pull out the first name
	var namednode = null;
	while (thisname) {							// and keep processing until we run out of name components
		namednode = findNode(nextnode, thisname);			// check to see tif this node or a sibling has this name
		if (!namednode)							// does the name exist on this level?
			return null;						// no - thats it
		thisname = nameparts.shift();					// get the next name
		nextnode = namednode.firstChild;
	}
	if (namednode) {							// if we found the node we were looking for
		if (namednode.nodeValue) {					// if this node has a value
			result = namednode.nodeValue;				// this is the value we want
		} else if (namednode.firstChild && (namednode.firstChild.nodeType == 3)) { // the value may be in the nodes child
			result = namednode.firstChild.nodeValue;		// get the value from the text node
		}
	}
	return result;								// return whatever result there is
}
