
var Ajax={
	getRequest:function(){
		var r;
		if(window.XMLHttpRequest){
			r = new XMLHttpRequest();
		}else if(window.ActiveXObject){
			var i = this.ACTIVEX_PROVIDERS.length-1;
			while(!r && i>0){
				try{r=new ActiveXObject(this.ACTIVEX_PROVIDERS[(i--)]);}catch(e){}
			}
		}
		return r;
	},
	ACTIVEX_PROVIDERS:["Microsoft.XMLHTTP","MSXML2.XMLHTTP","MSXML2.XMLHTTP.3.0","MSXML2.XMLHTTP.4.0","MSXML2.XMLHTTP.5.0","MSXML2.serverXMLHTTP"],
	Events:["onUnInitialized","onLoading","onLoaded","onInteractive","onComplete"],
	toString:function(){return "Ajax";}
};



Ajax.Request = function(){
	var r, o=this;
	r = this.constructor.getRequest();
	r.onreadystatechange = function(){
		var f, ev=o.constructor.Events[r.readyState];
		o.onProgress();

		if( r.readyState == 4 ) {
			try {
				if( r.status == undefined || r.status == 0) 
					return; //this.OnAbort(); //CATCH BY abort function
			}
			catch(e){
				// 13030 is the custom code to indicate the condition -- in Mozilla/FF --
				// when the o object's status and statusText properties are
				// unavailable, and a query attempt throws an exception.
				return;
			}		
			// TODO: Verify Error cases and possible events
			//else if( r.status != 200 || r.statusText != "OK" )
				//this.OnError( r.status, r.statusText, r.responseText);    
		}
		if((f = o[(o.constructor.Events[r.readyState])]))f.apply(o);
	}
	this.request = r;
};

Ajax.Request.prototype = {
	constructor:Ajax,
	toString:function(){return "Ajax.Request";},
	onProgress:function(){},
	params:{
		hash:{},
		add:function(p,v){
			if(typeof(p) == "object"){
				this.hash = p;
			}else{
				this.hash[p] = v;
			}
		},
		remove:function(p){
			if(!p){ 
				this.hash = {};
			}else{
				delete this.hash[p];
			}
		},
		toString:function(){
			var z="", s="";
			for(var i in this.hash){
				s += z + i + "=" + this.hash[i];
				z = "&";
			}
			return s;
		}
	},
	header:{
		defaultHash:{"Content-Type":"text/xml","encoding":"ISO-8859-1"},
		hash:{"Content-Type":"text/xml","encoding":"ISO-8859-1"},
		add:function(p,v){
			if(!p || !v) return false;
			this.hash[p] = v;
			return v;
		},
		remove:function(p){
			if(!p){
				this.hash = {}
			}else{
				delete this.hash[p];
			}
		},
		reset:function(){
			for(i in this.defaultHash){
				this.hash[i] = this.defaultHash[i];
			}
		},
		resolve:function(o){
			if(o.method.toUpperCase() == "POST"){
				this.add("Content-Type","application/x-www-form-urlencoded");
				this.add("Content-length", o.params.toString().length);
				this.add("Connection", "close");
			}
			for(var i in this.hash){
				o.request.setRequestHeader(i, this.hash[i]);
			}
		}
	},
	load:function(url){
		var u, b;
		u = url || this.url || window.location.href;
		if(this.method.toUpperCase() == "GET"){
			var p=this.params.toString();
			if(p.length){
				u += (this.url.indexOf("?")==-1 ? '?' : '&') + p;
			}
		}else if(this.method.toUpperCase() == 'POST'){
			b = this.postBody || this.params.toString();
		}else{
			b = null;
		}
		this.request.open(this.method, u, this.async);
		this.header.resolve(this);
		this.request.send(b);
	},
	abort:function(){
		this.request.abort();
		if(this.onAbort)
			this.onAbort();
	},	
	url:"",
	method:"POST",
	async:true,
	postBody:""
}
