
function getDomDocumentPrefix() {
	if (getDomDocumentPrefix.prefix) return getDomDocumentPrefix.prefix;
 	var prefixes = ["MSXML2", "Microsoft", "MSXML", "MSXML3"];
 	var o;
 	for (var i = 0; i < prefixes.length; i++) {
 		try {
 			o = new ActiveXObject(prefixes[i] + ".DomDocument");
 			return getDomDocumentPrefix.prefix = prefixes[i];
 		}
 		catch (ex) {};
 	}
 	throw new Error("Could not find an installed XML parser");
}
 
function getXmlHttpPrefix() {
 	if (getXmlHttpPrefix.prefix) return getXmlHttpPrefix.prefix;
 	var prefixes = ["MSXML2", "Microsoft", "MSXML", "MSXML3"];
 	var o;
 	for (var i = 0; i < prefixes.length; i++) {
 		try {
 			o = new ActiveXObject(prefixes[i] + ".XmlHttp");
 			return getXmlHttpPrefix.prefix = prefixes[i];
 		}
 		catch (ex) {};
 	}
 	throw new Error("Could not find an installed XML parser");
}

function XmlHttpParameter(name, value) {
	this.name = name;
	this.value = value;
}

function XmlHttp(url)
{

	//*********************************************************************************************
	// Public
	//_____________________________________________________________________________________________

	// Properties	
	
	this.url = url;
	this.trace = false;
	this.responseText = null;
	this.responseDocument = null;
	this.critical = true;
	
	
	// Events
	
	this.onInit = null;
	this.onDone = null;
	this.onError = null;
	
	
	// Methods
	
	this.addParam = function(name, value) {
		if (parameters == null)	parameters = new Array();
		parameters[parameters.length] = new XmlHttpParameter(name, value);
	}
	
	this.clearParams = function() {
		parameters = null;
	}
	
	this.send = function(requestDocument) {
				
		this.responseDocument = null;
		
		var bAsync = typeof(this.onDone) == "function";
		var bGet = typeof(requestDocument) == "undefined";

		if (busy) throw "An operation is already in progress";
		
		busy = true;

		var sUrl = this.url;
		if (parameters != null) 
		{
			for (var i=0; i < parameters.length; i++)
			{
				sUrl += (i==0 ? "?" : "&") + parameters[i].name + "=" + parameters[i].value;
			}
		}

		try
		{		
			xmlhttp.open(bGet ? "GET" : "POST", sUrl, bAsync);		
			xmlhttp.onreadystatechange = handleStateChange;
			if (!bGet) xmlhttp.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
			xmlhttp.send(bGet ? null : requestDocument);
			
			if (bAsync) {
				return null;
			} else {
				handleResponse();
				return this.responseText;
			}

		} 
		finally
		{
			if (!bAsync) busy = false;
		}
	}
		
		
	//*********************************************************************************************
	// Private
	//_____________________________________________________________________________________________

	// Variables
	var self = this;
	var xmlhttp = null;
	var busy = false;
	var traceWin = null;
	var parameters = null;
	var fullUrl = null;
	
	// Create XmlHttp
 	try {
 		if (window.XMLHttpRequest) {
 			xmlhttp = new XMLHttpRequest();
 			if (xmlhttp.readyState == null) {
 				xmlhttp.readyState = 1;
 				xmlhttp.addEventListener("load", function () {
 					xmlhttp.readyState = 4;
 					if (typeof xmlhttp.onreadystatechange == "function")
 						xmlhttp.onreadystatechange();
 				}, false);
 			}
 		} else if (window.ActiveXObject) {
 			xmlhttp = new ActiveXObject(getXmlHttpPrefix() + ".XmlHttp");
 		}
 	}
 	catch (ex) {}
 	if (xmlhttp == null) {
 		throw new Error("Your browser does not support XmlHttp objects");
 	}
	
	// State change handler
	var handleStateChange = function() {
	
		switch (xmlhttp.readyState) {
			case 1:
				if (typeof(self.onInit) == "function") {
					try	{
						self.onInit();
					} catch (e)	{
						traceMsg("Error handling onInit(): " + e);
					}
				}
				break;
				
			case 2:
                /*if (xmlhttp.status != 200) 
                {
					var status = xmlhttp.status;
					var statusText = xmlhttp.statusText;
					
                    xmlhttp.abort();
                    busy = false;
					
					if (typeof(self.onError) == "function")
					{
						try
						{
							this.onError(status, statusText);
						}
						catch (e)
						{
							// Ignore errors
						}
					}

				}*/
                break;
                			
			case 4:
				traceMsg("Request done");
				busy = false;
				if (typeof(self.onDone) == "function") {
					handleResponse();
					self.onDone(self.responseText);
				}
				break;
		} 
	}

	var handleResponse = function() {
		self.responseDocument = xmlhttp.responseXML;
		self.responseText = xmlhttp.responseText;
		if (xmlhttp.status != 200) {
			if (self.critical) {
				if (confirm("Request to server failed.\nURL: " + self.url + "\nStatus: " + xmlhttp.status + "\n\nShow details?")) {
					var oWin = window.open("about:blank", "debugwin");
					try { oWin.focus(); } catch(e) {}
					oWin.document.write(self.responseText);
				}
			}
			self.responseText = null;
			self.responseDocument = null;
		} 
	}
	
	var traceMsg = function(message) {
		if (self.trace) {
			if (traceWin == null) traceWin = window.open("", "SvrReqTrc");
			try	{
				traceWin.document.write(new Date().toString() + " " + message + "<br>");
			} catch(e) {
				// Seems like the trace window was closed
				// Ignore
			}
		}
	}

}

function getOuterXml(node) {
	try {
		if (window.XMLSerializer) {
 			return (new XMLSerializer()).serializeToString(node);
		} else if (window.ActiveXObject) {
			return node.xml;
		}
	} catch (e) {}
	throw "This browser does not support XML serialization.";
}

function getInnerXml(node) {
	if (node == null) return null;
	var xml = "";
	for (var i=0; i < node.childNodes.length; i++) {
		xml += getOuterXml(node.childNodes[i]);
	}
	return xml;
}

function xmlSelectSingleNode(element, nodeName, attrName, attrValue) {
	var bCheckAttr = typeof(attrName) != "undefined";
	var oNodes = element.getElementsByTagName(nodeName);
	for (var i=0; i < oNodes.length; i++) {
		if (!bCheckAttr || (oNodes[i].getAttribute(attrName) == attrValue)) {
			return oNodes[i];
		}
	}
	return null;
}
