/*** Ajax Wrapper Class ***/
/* Usage Example:
 * var myObject = new Ajax();
 * myObject.load(url, parameters, loadFunction, requestMethod, postContentType, errorFunction, element);
 *  
 * url = the url of the processing page.
 * parameters = an associative array or string representing parameters sent to the processing page. Examples:
 *     var myArray = new Array(); myArray['var1']='one'; myArray['var2']='two';
 *     var myString = 'var1=one&var2=two';
 * loadFunction = the un-quoted name of a custom function for processing results from the server. Default prints to parameter 'element'.
 * requestMethod = 'POST' or 'GET'. Default is 'GET'.
 * postContentType = the content type for post headers. Default is 'application/x-www-form-urlencoded; charset=UTF-8'.
 * errorFunction = the un-quoted name of a custom function for processing errors. Default alerts user.
 * element = the default id of a document element where the results will print. Can be
 *     - textfields
 *     - textareas
 *     - any element supporting the innerHTML property
 *
 *
 * assuming calendar.php creates a calendar given a month and a year, 
 * a displayCalendar function to display the results and
 * a displayError function to handle errors:
 *
 * var ajaxCalendar = new Ajax();
 * ajaxCalendar.load('calendar.php','month=3&year=2006',displayCalendar,'GET',null,displayError,null);
 */
 
function Ajax() {
	this.READY_STATE_INITIALIZED = 0;
	this.READY_STATE_LOADING 	 = 1;
	this.READY_STATE_LOADED		 = 2;
	this.READY_STATE_INTERACTIVE = 3;
	this.READY_STATE_COMPLETE 	 = 4;
}

Ajax.prototype.load = function(url, parameters, loadFunction, requestMethod, postContentType, errorFunction, element) {
	this.request = this.getRequestObject();
	var request = this.request;
	var _this = this;
	
	this.url = url;
	this.parameters = (parameters instanceof Array) ? Ajax.processParameters(parameters) : parameters;	
	this.loadFunction = (loadFunction) ? loadFunction : this.defaultOnload;
	this.requestMethod = (requestMethod && requestMethod == 'POST') ? 'POST' : 'GET';
	this.postContentType = (this.requestMethod == 'POST' && !postContentType) ? 'application/x-www-form-urlencoded; charset=UTF-8' : postContentType;
	this.errorFunction  = (errorFunction) ? errorFunction : this.defaultError;
	this.element = (element) ? element : null;

	if(request) {
		request.onreadystatechange = function() {
			_this.handleReadyState()
		}
		
		if(this.requestMethod == 'GET') {
			request.open(this.requestMethod, this.url + "?" + this.parameters, true);
			request.send(null);
		} else {
			request.open(this.requestMethod, this.url, true);
			request.setRequestHeader("Content-type", this.postContentType);
			request.setRequestHeader("Content-length", this.parameters.length);
			request.setRequestHeader("Connection", "close");
			request.send(this.parameters);
		}
	}
}

Ajax.prototype.getRequestObject = function() {
	var request;
	if(window.XMLHttpRequest) {
		request = new XMLHttpRequest();
	} else if(window.ActiveXObject) {
		try {
			request = newActiveXObject("Msxml2.XMLHTTP");
		} catch(e) {
			try {
				request = new ActiveXObject("Microsoft.XMLHTTP");
			} catch(e) {}
		}
	}
	return request;
}

Ajax.prototype.handleReadyState = function() {
	var request = this.request;
	
	if(document.getElementById && document.getElementById('msg')) {
		document.getElementById('msg').value += " readyState:" + request.readyState;
	}
	
	if(request.readyState == this.READY_STATE_COMPLETE) {
		if(request.status == 200 || request.status == 0) {
			this.loadFunction.call(this);
		} else {
			this.errorFunction.call(this);
		}
	}
}

Ajax.prototype.defaultError = function() {
	var error = "Error: Ready state:" + this.request.readyState + "; " + this.request.status + " - " + this.request.statusText;
	alert(error);
}

Ajax.prototype.defaultOnload = function() {
	//alert(document.getElementById(this.element));
	if(this.element) {
		if(document.getElementById && document.getElementById(this.element)) {
			element = document.getElementById(this.element);
		} else if(document.all) {
			element = document.all[element];
		}
		
		if(element) {
			if(element.type && (element.type == 'text' || element.type == 'textarea')) {
				element.value = this.request.responseText.trim();
			} else { //if(element.innerHTML) {
				element.innerHTML = this.request.responseText.trim();
			}
		}
	}
}

/** Helper method that creates url GET parameters from an associative array **/
Ajax.processParameters = function(parameters) {
	var myString = '';
	var counter = 0;

	if(parameters instanceof Array) {
		for(var name in parameters) {
			if(counter > 0) {
				myString += '&';
			}
			myString += name + '=' + parameters[name];
			counter++;
		}
		return myString;
	} else {
		return parameters;
	}
}

// Test Function.
function printResult() {
	document.getElementById('msg').value += '<br>\n' + this.request.responseText;
	
}

// Test Function.
function printError() {
	var error = "Error: Ready state:" + this.request.readyState + "; " + this.request.status + " - " + this.request.statusText;
	document.getElementById('msg').value += '<br>\n' + error;
	
}

String.prototype.trim = function() {
	a = this.replace(/^\s+/, '');
	return a.replace(/\s+$/, '');
};
