//This provides an abstraction of the AJAX browser mess.
//For such a popular technique, it'd be nice if they standardized it!

//This becomes the constructor, where we determine how we make requests. The real code is at the very bottom.
function SafeXMLRequest() {
	var requestobject = null;
	var useiframe = false;
	var frameinterval = null;
	
	//This is a public variable indicating a two parameter callback function to be fired on completion.
	//The first parameter is the returned status code.
	//The second contains the data returned.
	var recvcallback = null;

	//Since Javascript has a weird (read: fake) OOP model, we'll put the rest of the class inside of the constructor.
	var that = this;
	function createNewRequest() {
		if (useiframe) {
			//No need to create a new request object.
			return;
		}
		
		try {
			//Try creating the request as a new object first.
			requestobject = new XMLHttpRequest();
		}
		catch (err) {
			try {
				//OK, they're probably using IE.
				requestobject = new ActiveXObject("Microsoft.XMLHTTP");
			}
			catch(err) {
					//Meh, use an iframe.
					requestobject = document.createElement("iframe");
					requestobject.style.width = "1px";
					requestobject.style.height = "1px";
					requestobject.style.position = "absolute";
					requestobject.style.left = "-1000px";
					document.body.appendChild(requestobject);
					useiframe = true;
			}
		}
		
		if (!useiframe) {
			requestobject.onreadystatechange = stateHandler;	//Do not call this directly!
		}
		else {
			//Try it on a timer.
			frameinterval = setInterval(stateHandler, 50);
		}
	}
	
	//Set up our class' public methods.	
	this.abort = function() {
		if (useiframe) {
			requestobject.src="about:blank";
		}
		else {
			requestobject.abort();
		}
	};
	
	this.open = function(method, url) {
		if (useiframe) {
			//Ignore method; iframes must use GET.
			requestobject.src=url;
		}
		else {
			//Create a request.
			var querystring = null;

			if (method == "POST") {
				var qpos = url.indexOf("?");
				if (qpos >= 0) {
					//Question mark found.
					querystring = url.substring(qpos+1);
					url = url.substring(0, qpos);
				}	
			}
			
			requestobject.open(method, url, true);
			
			if (method == "POST")
				requestobject.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
			else
				//Don't cache pages.
				requestobject.setRequestHeader('Cache-Control', 'no-cache');

			requestobject.send(querystring);
		}
	};
	
	this.setCallback = function(callbackfunction) {
		recvcallback = callbackfunction;
	};

	function stateHandler() {
		if (!useiframe && requestobject.readyState != 4) {
			//We don't care if it's still in progress.
			return;
		}

		if (useiframe) {
			var doccontent = (requestobject.contentDocument) ? requestobject.contentDocument.body : requestobject.contentWindow.document.body;
			
			if (doccontent != null) {
				recvcallback(null, doccontent.innerHTML, doccontent);
				clearInterval(frameinterval);
			}
		}
		else {
			recvcallback(requestobject.status, requestobject.responseText, requestobject.responseXML);
		}
		
		//Prepare for the next request.
		createNewRequest();
	}
	
	//Here's the actual code we needed a constructor for :)
	createNewRequest();
}

