// AJAX OBJECT
/*
Example GET Requests:
// XML
ajax.getRequest('ajax.xml', 'XML', parseXML, true);
// JSON
ajax.getRequest('ajax.json', 'JSON, 'text', parseJSON, true);
// TEXT
ajax.getRequest('ajax.txt', 'TEXT', parseTXT, true);
// HTML
ajax.getRequest('ajax.html', 'HTML', parseHTML, true);
*/
function ajax () {
	// Public members
	this.getRequest = getRequest;
	this.postRequest = postRequest;
	this.suppressCache = true;
	this.setTimeoutPeriod = setTimeoutPeriod;
	// Private members
	var requestStack = new Array();
	var stackPosCounter = 0;
	var timeoutPeriod = 60000; // You have 60 seconds to comply
	function getHTTPObject() {
		var xhr = false;
		// All standards compliant browsers
		if (window.XMLHttpRequest) {
			xhr = new XMLHttpRequest();
		// Microsoft IE
		} else if (window.ActiveXObject) {
			try {
				xhr = new ActiveXObject("Msxml2.XMLHTTP");
			} catch(e) {
				try {
					xhr = new ActiveXObject("Microsoft.XMLHTTP");
				} catch(e) {
					xhr = false;
				}
			}
		}
		return xhr;
	}
	// url = the url to send request to [string]
	// type = the format of the returned data from server: xml, json, text, html [string]
	// callback = the function you want to callback upon success [string]
	// async = to perform the action asynchronously [boolean]
	function getRequest(url, type, callback, async) {
		// Create a new XHR object and add it to the stack, addToStack then returns the objects position in the array, so we can target it
		var request = new Object();
		request.xhr = getHTTPObject();
		request.callback = callback;
		request.url = (this.suppressCache !== false) ? suppressCache(url) : url;
		request.type = type;
		request.async = async;
		request.timeout = setTimeout(function(){ request.xhr.onreadystatechange = function() {}; request.xhr.abort(); errorHandler('TIMEOUT: A timeout has occurred', request.callback); }, timeoutPeriod);
		addToStack(request);
		if (request.xhr) {
			request.xhr.onreadystatechange = function() {
				checkStatus(request);
			}
			request.xhr.open('GET', url, request.async);
			request.xhr.send(null);
			return true;
		} else {
			return false;
		}
	}
	// url = the file you want to post to [string]
	// type = the format of the returned data from server: xml, json, text, html [string]
	// callback = the function you want to callback upon success [string]
	// async = to perform the action asynchronously [boolean]
	// args = arguments to send [string]
	function postRequest(url, type, callback, async, args) {
		var request = new Object();
		request.xhr = getHTTPObject();
		request.callback = callback;
		request.url = (this.suppressCache !== false) ? suppressCache(url) : url;
		request.type = type;
		request.async = async;
		request.timeout = setTimeout(function(){ request.xhr.onreadystatechange = function() {}; request.xhr.abort(); errorHandler('TIMEOUT: A timeout has occurred', request.callback); }, timeoutPeriod);
		request.args = args;
		addToStack(request);
		if (request.xhr) {
			request.xhr.onreadystatechange = function() {
				checkStatus(request);
			}
			request.xhr.open('POST', url, request.async);
			request.xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
			request.xhr.send(request.args);
			return true;
		} else {
			return false;
		}
	}
	// Add the request object to the stack array
	function addToStack(request) {
		request.stackPos = stackPosCounter;
		requestStack[request.stackPos] = request;
		stackPosCounter++;
	}
	function checkStatus(request) {
		if (request.xhr.readyState == 4) {
			clearTimeout(request.timeout);
			requestStack.splice(request.stackPos-1, 1);
			if (request.xhr.status == 200 || request.xhr.status == 304) {
				// Do something with the response
				switch (request.type) {
					case 'XML':
					request.callback(request.xhr.responseXML);
					break;
					case 'JSON':
					request.callback(eval('('+request.xhr.responseText+')'));
					break;
					case 'TEXT':
					request.callback(request.xhr.responseText);
					break;
					case 'HTML':
					request.callback(request.xhr.responseText);
					break;
				}
			} else {
				errorHandler('ERROR: Could not retrieve data from server', request.callback);
			}
		}
	}
	// Adds a 10 digit random number to the url to suppress cache
	function suppressCache(url) {
		var num = Math.round(Math.random()*10000000000);
		if (url.indexOf('?') == -1) {
			url += '?disableCache='+num;
		} else {
			url += '&disableCache='+num;
		}
		return url;
	}
	// Error handler returns an object to the callback with a property of 'error'
	// The parser should check this property exists before continuing to parse
	function errorHandler(errMsg, callback) {
		var obj = new Object();
		obj.error = errMsg;
		callback(obj);
	}
	// Public method for altering the timeout period
	function setTimeoutPeriod(time) {
		timeoutPeriod = time;
		return true;
	}
}
var ajax = new ajax();