function objXHR()
{ // scan the function clicked and act on it using the Ajax interthingy
	var url; // URL to send HTTP requests to
	var timer; // timer for timing things
	var XHR; // XMLHttpRequest object
	var xmlDoc; // object for requesting XML documents from the server
	var xmlIEFlag; // linked to xmlDoc, this discerns between IE and the better browser XML implementations
	var _responseXML; // holds XML formed responses from the server
	var _responseText; // holds any textual response from the server
	var request; // associative array to hold requests to be sent
	var additional; // additional settings in an associative array
	
	// vars added in addition to base vars
	var session_id; // current customer session ID
	
	this.request = new Array();
	this.additional = new Array();
	this.createXHR();
}

objXHR.prototype.xmlDoc = function() {
	this.xmlDoc = false;
	if (document.implementation && document.implementation.createDocument)
	{ // decent browser
		this.xmlDoc = document.implementation.createDocument("", "", null);
		this.xmlIEFlag = false;
	} else if (window.ActiveXObject) { // crappy IE
		this.xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
		this.xmlIEFlag = true;
	} else { // hmm... no XML request support
		this.xmlDoc = false;
	}
	xmlDoc.async = false;
}

objXHR.prototype.createXHR = function () { // this code has been modified from the Apple developers website
	this.XHR = false;
    // branch for native XMLHttpRequest object
    if(window.XMLHttpRequest) { // decent, normal, law abiding browsers
    	try { // make sure the object can be created
			this.XHR = new XMLHttpRequest();
        } catch(e) { // it can't
			this.XHR = false;
        }
    // branch for IE/Windows ActiveX version
    } else if(window.ActiveXObject) { // this does stuff too
       	try {
        	this.XHR = new ActiveXObject("Msxml2.XMLHTTP");
      	} catch(e) {
        	try {
          		this.XHR = new ActiveXObject("Microsoft.XMLHTTP");
        	} catch(e) {
          		this.XHR = false;
        	}
		}
    }
}

objXHR.prototype.getData = function(strMode, resFunc) { // send a request to the server in either GET or POST
	// resfunc is the string name of the function that will handle the response when it arrives
	// determine the transport method (can only send POST for some reason)
	// resFunc is the name of the prototype function to be called on data arrival
	
	strMode = (strMode.toLowerCase() == 'post' ? 'post' : 'get');
	var _this = this; // scope resolution
	this.createXHR();

	if (this.XHR) {
		this.XHR.onreadystatechange = function () {
			if (_this.XHR.readyState == 4) {
			// only if "OK"
				if (_this.XHR.status == 200) {
					_this._responseXML = _this.XHR.responseXML;
					_this._responseText = _this.XHR.responseText;
					_this.responseHandler(resFunc);
				} else {
					alert('Status returned - ' + _this.XHR.statusText);
				}
			}
		}
		this.XHR.open(strMode.toLowerCase(), this.url+(strMode.toLowerCase() == 'get' ? '?' + this.compileRequest() : ''), true);
		if (strMode.toLowerCase() == 'post')	this.XHR.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
		this.XHR.send(this.compileRequest());
	} else {
		var mess = "I couldn't contact the server!\n\nIf you use IE please allow ActiveX objects to run";
		alert (mess);
	}
}

objXHR.prototype.getXML = function(strMode) { // send a request to the server in either GET or POST
	// resfunc is the string name of the function that will handle the response when it arrives
	// determine the transport method (can only send POST for some reason)
	// resFunc is the name of the prototype function to be called on data arrival
	
	strMode = (strMode.toLowerCase() == 'post' ? 'post' : 'get');
	var _this = this; // scope resolution
	this.createXHR();

	if (this.XHR) {
		this.XHR.onreadystatechange = function () {
			if (_this.XHR.readyState == 4) {
			// only if "OK"
				if (_this.XHR.status == 200) {
					alert (_this.responseText);
					return _this.responseXML;// = _this.XHR.responseXML;
		//			_this._responseText = _this.XHR.responseText;
		//			_this.responseHandler(resFunc);
				} else {
					alert('Status returned - ' + _this.XHR.statusText);
				}
			}
		}
		this.XHR.open(strMode.toLowerCase(), this.url+(strMode.toLowerCase() == 'get' ? '?' + this.compileRequest() : ''), true);
		if (strMode.toLowerCase() == 'post')	this.XHR.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
		this.XHR.send(this.compileRequest());
	} else {
		var mess = "I couldn't contact the server!\n\nIf you use IE please allow ActiveX objects to run";
		alert (mess);
	}
}

objXHR.prototype.compileRequest = function () {
	// parse the request array into a URL encoded string
	var ret = ''; // return request string
	
	for (var e in this.request) {
		ret += e + '=' + this.request[e].replace(/&/, '%26') + '&';
	}
	
	return (ret.substr(0, ret.length - 1));
}

objXHR.prototype.responseHandler = function (theFunction) { // redirect responses from the server to the right function
	// to add a function simply declare a prototype function and the pass the exact name
	// as the second parameter
	// ### NOTE ### function strings must be passed with parantheses
	
	this.request = new Array();
	eval('this.'+theFunction);
}

objXHR.prototype.getUKHMSearchInc = function (boolFirst) {
	// [specific to UKHM] get the search form from the include
	if (boolFirst === true) { // send the request rather than receive it
		this.url = ajaxSearchForm;
		this.request['stat'] = 'main_search';
		this.getData('post', 'getUKHMSearchInc(false)');
	} else { // receive the data and return it verbatim to the function that called
		cp.showSearch(this._responseText);
	}
}

/// prototype functions can be included in other files provided this file is included first

objXHR.prototype.showHelp = function (theA, boolFirst) {
	var holder = document.getElementById('snipHelpHolder');
	var titleDiv = document.getElementById('snipHelpTitle');
	var contentDiv = document.getElementById('snipHelpContent');
	this.url = mainAjaxForm;

	if (boolFirst === true)	{
		// compile the request and prepare the div
		for(var i=0; titleDiv.childNodes[i]; i++) {
			nodeRemover(titleDiv.childNodes[i]);
		}
		titleDiv.appendChild(document.createTextNode('Please wait'));
		
		for(var i=0; contentDiv.childNodes[i]; i++) {
			nodeRemover(contentDiv.childNodes[i]);
		}
		var waitingImg = document.createElement('IMG');
		waitingImg.src = cp.waitingLarge;
		contentDiv.style.textAlign = 'center';
		waitingImg.style.margin = '0.3em auto';
		contentDiv.appendChild(waitingImg);
		
		holder.style.left = (nMouseX + 15) + 'px';
		holder.style.top = (nMouseY - 10) + 'px';
		holder.style.display = 'block';

		this.request['stat'] = 'live_help';
		this.request['id'] = theA;
		this.getData('get', 'showHelp(false, false)');
	} else {
		contentDiv.style.textAlign = 'left';
		for(var i=0; titleDiv.childNodes[i]; i++) {
			nodeRemover(titleDiv.childNodes[i]);
		}
		var newTitle = this._responseXML.getElementsByTagName('title')[0].childNodes[0].data;
		var newContent = this._responseXML.getElementsByTagName('content')[0].childNodes[0].data;
		titleDiv.appendChild(document.createTextNode(newTitle));
		
		for(var i=0; contentDiv.childNodes[i]; i++) {
			nodeRemover(contentDiv.childNodes[i]);
		}
		contentDiv.appendChild(document.createTextNode(newContent));
	}
}

objXHR.prototype.hideHelp = function () {
	var holder = document.getElementById('snipHelpHolder');
	holder.style.display = 'none';
}

/* objXHR.prototype.example = function (theLink) {
	if (theLink !== false) { // theLink is an object, in this instace <a>, and not a server response
		// set the stat var for the formcatcher (defined as a prototype var in the head of the page before objXHR instantiation
		this.request['stat'] = 'getEventsForDay';
		
		// sample data that will be converted to standard FORM notation 'key=value' separated by & (ampersand)
		// the associative key of the this.request array comprises the key of the FORM pair
		// the value of this.request comprises the value of the FORM pair
		
		this.request['day'] = data[2];
		this.request['month'] = data[3];
		this.request['year'] = data[4];
		
		// this.getData has 2 parameters
		// the 1st parameter is the form method get or post
		// the second parameter can be the name (without the this.) of any function prototype of this object
		// in this function a valid object (<a>) is checked for; if it's not explicitely false data will be collected by your methods
		// and sent to the server.
		
		// The line below shows how to call this function again to handle the server response
		// * responses are supplied in either this._responseText or this._responseXML depending on the headers sent by the server
		this.getData('post', 'example(false)');
	} else { // theLink (in this case) is explitly false; this is a server response
		// in this (rather crappy) example the returned HTML is inserted directly a DIV
		eDiv.innerHTML = this._responseText;
	}
	
	return  false;
}*/

var xhr = new objXHR;
