/*****************************************************
* Copyright Aaron Latham-Anderson 2008,2009
* breaks.nz@gmail.com
*
* ---------------------------------------
* KNOWN BUGS / ISSUES
* ---------------------------------------

  Bug: sending another request before the last one has returned prevents the first one from being retreivable
  Workaround: make another instance of the ajax object and use that if the requests are going to be fired in quick succession

* ---------------------------------------
* USAGE
* ---------------------------------------

<script language="javascript" type="text/javascript" src="ajax.js"></script>
<script language="javascript" type="text/javascript">
//Response Function
function ajax_response(r_type,r_data,args){
	switch(r_type){
		case "xml":
			var r_xml = r_data;
			var names = r_xml.getElementsByTagName("from");
			alert(names[0].childNodes[0].nodeValue)
		break;
		case "txt":
			var r_txt = r_data;
			alert('r_txt')
		break;
	}
}
//Load Status function
function ajax_load(loading,args){
	if(loading){
		document.getElementById("load").innerHTML = "<img src='templates/img/load.gif' style='vm' /> Loading...";
	}else{
		document.getElementById("load").innerHTML = "";	
	}	
}
//No Data function
function ajax_no_data(args){
	alert('No Data');
}

//constructor: var a = new ajax(params, script_name, s_method, output_format, response_func, load_func, no_data_func);
//sendrequest: ajax.sendData(params, script_name, s_method, output_format, response_func, load_func, no_data_func, response_func_arg_array, load_func_arg_array, no_data_func_arg_array);

//define new object
var a = new ajax('x=666','ajax_test.xml.php','get','xml',ajax_response,ajax_load,ajax_no_data);

</script>

*****************************************************/

function ajax(params, script_name, s_method, output_format, response_func, load_func, no_data_func, rf, lf, nd, send_now){
	
	//use constructor function ajax(script_name, params) / assignment of object.script_name or object.params / object.sendData(script_name,params) to set params and script name
	//all other constructor args have defaults
	
	//init vars / set defaults	
	typeof output_format 	!= 'undefined' ? this.output_format = output_format : this.output_format 	= 'xml';
	typeof response_func 	!= 'undefined' ? this.response_func = response_func : this.response_func 	= null;
	typeof load_func 		!= 'undefined' ? this.load_func	 	= load_func		: this.load_func		= null;
	typeof no_data_func 	!= 'undefined' ? this.no_data_func	= no_data_func	: this.no_data_func		= null;
	typeof s_method 		!= 'undefined' ? this.s_method 		= s_method 		: this.s_method 		= 'get';
	typeof script_name 		!= 'undefined' ? this.script_name 	= script_name 	: this.script_name 		= null;
	typeof params 			!= 'undefined' ? this.params 		= params 		: this.params 			= null;
	typeof rf 				!= 'undefined' ? this.rf			= rf	 		: this.rf				= null;
	typeof lf 				!= 'undefined' ? this.lf 			= lf 			: this.lf 				= null;
	typeof nd 				!= 'undefined' ? this.nd 			= nd 			: this.nd 				= null;

	this.sendData = function(params, script_name, s_method, output_format, response_func, load_func, no_data_func, rf, lf, nd){
		
		//Update Properties
		if(params){			this.params 		= params}
		if(script_name){	this.script_name 	= script_name}
		if(s_method){		this.s_method 		= s_method}
		if(response_func){	this.response_func	= response_func}
		if(load_func){		this.load_func	 	= load_func}
		if(no_data_func){	this.no_data_func 	= no_data_func}
		if(output_format){	this.output_format 	= output_format}
		if(rf){				this.rf	 			= rf}
		if(lf){				this.lf 			= lf}
		if(nd){				this.nd 			= nd}
		
		this.xmlHttp=this.GetXmlHttpObject();
		
		if (this.xmlHttp==null){
			alert ("Browser does not support HTTP Request");
			return;
		}
		
		// Set Callback
		this.stateChangedWrap = this.curry(this.stateChanged,this);
		this.xmlHttp.onreadystatechange=this.stateChangedWrap;
	
		if(this.s_method=='post'){
			//Post Syntax
			this.xmlHttp.open("POST",this.script_name,true);
			//Additional Headers for POST Method
			this.xmlHttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
			this.xmlHttp.setRequestHeader("Content-length", this.params.length);
			this.xmlHttp.setRequestHeader("Connection", "close");
			//POST params
			this.xmlHttp.send(this.params);
		}else{
			//Get Synatx
			this.xmlHttp.open("GET",this.script_name+"?"+this.params,true);
			this.xmlHttp.send(null);
		}
	}
	
	// Call Back
	this.stateChanged = function(_this){
		if ( (_this.xmlHttp.readyState==4 || _this.xmlHttp.readyState=="complete") && _this.xmlHttp.status == 200){
			if(_this.xmlHttp.responseText==null || _this.xmlHttp.responseText==""){
				_this.no_data_func(_this.nd);
			}else{
				(_this.output_format=='txt') ? _this.response_func('txt', _this.xmlHttp.responseText, _this.rf) : _this.response_func('xml', _this.xmlHttp.responseXML, _this.rf) ;
			}
			_this.load_func(false, _this.lf);
		}else{
			_this.load_func(true, _this.lf);
		}
	}
	
	// Supporting  Methods
	this.curry = function(method){
		var curried = [];
		for (var i = 1; i < arguments.length; i++) {
			curried.push(arguments[i]);
		}
		return function() {
			var args = [];
			for (var i = 0; i < curried.length; i++) {
				args.push(curried[i]);
			}
			for (var i = 0; i < arguments.length; i++) {
				args.push(arguments[i]);
			}
			return method.apply(null, args);
		}
	}
	
	this.GetXmlHttpObject = function(){ 
		var objXMLHttp = null;
		if(window.XMLHttpRequest){
			objXMLHttp = new XMLHttpRequest();
		}else if(window.ActiveXObject){
			objXMLHttp = new ActiveXObject("Microsoft.XMLHTTP");
		}
		return objXMLHttp;
	}
	
	this.abort = function(){
		this.xmlHttp.abort();
	}

	// Send Now?
	if(send_now) { this.sendData(); }

}