/*************************************************\
jax functions
Written by Andrew Green
This is a very large over haul of an old script I
once got from somewhere and have overcome its
problems as well as added features such as post,
creating multiple connections, url chache fix,
abort(cross browser support) and url encoding.

works in IE,FF,Oprah other browsers untested
\*************************************************/




/*************************************************\
url_encode method
Converts a string into a paramater friendly format
similar to php's add_slashes method for sql
\*************************************************/
function url_encode(content){
	var _find =    new Array("!",	"*",	"'",	"(",	")",	";",	":",	"@",	"&",	"=",	"+",	"$",	",",	"/",	"?",	"%",	"#",	"[",	"]");//Reserved charecters
	var _replace = new Array("%21",	"%2A",	"%27",	"%28",	"%29",	"%3B",	"%3A",	"%40",	"%26",	"%3D",	"%2B",	"%24",	"%2C",	"%2F",	"%3F",	"%25",	"%23",	"%5B",	"%5D");//Replacement charecters
	var _encoded="";
	for(var i=0;i<content.length;i++){
		var done=false;
		/*if(content.charCodeAt(i)>256){//not required if page type is utf8
			_encoded+=url_encode("&#" + content.charCodeAt(i) + ";");
			done=true;
		}else{*/
			for(var x=0;x<_find.length;x++){
	
				if(_find[x]==content.charAt(i)){
					_encoded +=_replace[x] ;
					done=true;
					break;
				}
			}
		//}
		
		
		if(!done)
			_encoded +=content.charAt(i);
	}
	return _encoded;
}
/*************************************************\
getHTTPObject
Creates a http object for various browsers
note: IE 7 has Native XMLHttpRequest, though this still
	uses IE's ActiveXObject if available
\*************************************************/
function getHTTPObject() {
	var http = false;
	
	//use the XMLHttpRequest of Firefox/Mozilla/IE7 ect. if available.
	 if (window.XMLHttpRequest) {
		try {http = new XMLHttpRequest();}
		catch (e) {http = false;}
	} else
	//Use IE's ActiveX items to load the file if available.
	if(window.ActiveXObject) {
		try {http = new ActiveXObject("Msxml2.XMLHTTP");}
		catch (e) {
			try {http = new ActiveXObject("Microsoft.XMLHTTP");}
			catch (E) {http = false;}
		}
	}
	return http;
}


/*************************************************\
jax object
Every instance of the object can handle one
connection at a time 2 connections made on the same
object will whipe out the first one if callback has
not already been fired.

note: a http protocol rule is that 2 connections
can be handled at any one time for a given domain
giving a que effect
(though this will probably change)

functions
load(url,params,method,callback(callback function))
close() //aborts current connection

error=function(exception,errNo,errText)
//set callback function for error here

\*************************************************/
function jax() {
	this.http = getHTTPObject();
	this.callback=function(data){};
	this.error = false;
	this.ready = true;
	this.async = true;
	
	this.close = function() {//abort the httpObject
		self.ready = true;//must be set to true so that onReadyStateChange events can be skipped
		self.http.abort();//aborts connection and in some browsers fires onReadyStateChange 
	}


	this.load = function (url,params,method,callback) {
			if(!url) return;//if no url dont initialise
			
			if(self.ready==false){//if in use then abort previous request
				self.close();
			}

			self.ready=false;//set as httpObject is in use

			if(callback)
				self.callback=callback;//set callback function
	

			//Kill the Cache problem in IE and other browsers, by makeing a unique id from time in the url.
			var now = "uid=" + new Date().getTime();
			url += (url.indexOf("?")+1) ? "&" : "?"; //if "?" exists in url then put "&" else "?"
			url += now;
	
			if(method=="GET" && params!=""){//if method is get and has params then add params on end of url
				url += "&" + params;
			}
	
			if (self.http.overrideMimeType) self.http.overrideMimeType('text/xml');
	
			self.http.open(method, url, self.async);
			
			
			
			self.http.onreadystatechange =self.onreadystatechange;
			try{//for sync request
				if(method=="GET"){//if get then send null
	
					self.http.send(null);
				} else {//else set its headers and send the params
					self.http.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
					self.http.setRequestHeader("Content-length", params.length);
					self.http.setRequestHeader("Connection", "close");
	
					self.http.send(params);
				}
			}catch(e){//an exception occured
				//Give true that it is an exception, error number and description to error callback function,
				//though these messages are generally useless across browsers,
				//exception is thrown if connection is unavailable for ff,ie and oprah though all exception number and message are different if they even exist.
				if(self.error) self.error(true,e.number,e.message);
			}	
			if(self.async==false){
				self.onreadystatechange();
			}

		}
		
		this.onreadystatechange = function () {//Deal with state changes.
				var http = self.http;
				if (self.ready == true){//if status has changed when object not in use
					try{//check if getting status throws exception
						http.status;
					}
					catch(e){
						self.http = getHTTPObject();
						//Recreate so http object can be used instantly
						//work around for FF
					}
				}
				
				//Ready State will be 4 when the document is loaded.
				//in ff Abort also returns 4 and accessing http.status crashes it
				//So check if the httpObject should be in use before continuing
				if (self.ready != true && http.readyState == 4) {
	
					self.ready=true;//if the request has finished then it is no longer in use
					try{//try to use normal logic, but if exception call error callback

						if(http.status == 200) {// Successful 200,  
							var result = "";
							if(http.responseText) result = http.responseText;
	
							//Give the data to the callback function.
							if(self.callback) self.callback(result);

						} else { //An error occured
							//Give false that it is not exception, the error number to error callback function
							if(self.error) self.error(false, http.status, http.statusText);
						}
					}catch(e){//an exception occured
						//Give true that it is an exception, error number and description to error callback function,
						//though these messages are generally useless across browsers,
						//exception is thrown if connection is unavailable for ff,ie and oprah though all exception number and message are different if they even exist.
						if(self.error) self.error(true,e.number,e.message);
					}	
				}
			}
	var self=this;
}
