//© <stipuha /> development (2008)
//> AJAX
//-------------------------------- 
//  ___example#1___
//  (req=new AJAX()).onready=function(response){ready_func(response)};
//	req.file="index.php";
//	req.query="abc=123&def=456";
//  reg.hash={p1:"aaa",p2:8,p3:[1,2,6]};
//	req.send();
//
//  ___example#2___
//	new AJAX({
//		file:"index.php", 
//		query:"abc=123&def=456",
//		onready:function(response){ready_func(response)},
//		send:1
//	});


(AJAX=function(opt){this.init(opt)}).prototype={
	
	CACHE:{},
		
	init:function(opt){
		opt=opt || {};
		this.method=opt.method || "http";
		this.file=opt.file || "";
		this.query=opt.query || "";
		this.caching=opt.caching || false;
		this.hash=opt.hash || {};
		this.onready=opt.onready || function(){};
		if(opt.send) this.send();
	},
		
	send:function(){
		//add hash to query
		this.query+=this.json2query(this.hash);
		//if cache==true > call data from cache & return
		try{if(this.caching && this.CACHE[this.query]) return this.ondata(this.CACHE[this.query]);}catch(e){};
		
		var _this=this;
		var request, response;
		var SID=(new Date()).getTime()+Math.round(Math.random()*1000);
		
		switch(this.method){
			case "http":
				request=window.XMLHttpRequest?new XMLHttpRequest():(new ActiveXObject("Msxml2.XMLHTTP") || null); // ||"Microsoft.XMLHTTP" - ie5x
				if(request){
					request.open('POST', this.file, true);
					request.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); // $_POST[] || $_REQUEST[]
					request.onreadystatechange=function(){  
						if(request.readyState==4){
							if(request.getResponseHeader('Content-Type') && request.getResponseHeader('Content-Type').indexOf("/xml")!=-1) response=_this.xml2json(request); //xml
							else response=(new Function('return '+request.responseText))(); //json
							_this.ondata(response);
						}
					};
					request.send(this.query); //request send 
					break;
				}
				
			case "script":
				request=document.createElement("script");
				if(request){
					request.id=SID;
					var src=this.file+"?"+"_scriptID_="+request.id+"&"+this.query;
					if(ie) request.src=src.substr(0,2048); //MAX msie:2kb
					else{request.src=src; request.src=request.src.substr(0,4096)}; //MAX gesko:4Kb
					request.onreadystatechange=function(response){
						if(response && !response.initEvent){
							_this.ondata(response);
							setTimeout(function(){request.parentNode.removeChild(request)},13);
						}
					};
					document.body.appendChild(request); //request send 
					break;
				}
				
			case "form":
				var request=document.createElement(ie?"<iframe name="+SID+">":"iframe");
				if(request){
					request.name=SID;
					request.style.position="absolute";
					request.style.visibility="hidden";
					this.form.appendChild(request);
					//this.form.encoding="multipart/form-data";
					this.form.method="post";
					this.form.target=request.name;
					this.form.action=this.file+this.form.action.replace(/.*(\?.*)$/,"$1");
					request.onreadystatechange=request.onload=function(response){
						if(!request.readyState || request.readyState=="complete"){
							_this.ondata((new Function('return '+request.contentWindow.document.body.innerHTML))());
							setTimeout(function(){request.parentNode.removeChild(request)},13);
						}
					};
					this.form.submit(); //request send 
					break;
				}
				
			default: return request;
		}
	},
	
	ondata:function(response){
		if(this.caching || this.CACHE[this.query]) this.CACHE[this.query]=response; //cache response data
		this.response=response;
		this.onready(response);
	},
	
	json2query:function(hash, pref){
		var query="";
		for(var i in hash){
			var key=(pref?pref+"["+i+"]":i);
			query+=(typeof hash[i]=="object" ? this.json2query(hash[i],key) : "&"+key+"="+hash[i].toString().replace(/&/g, "%26"));
		}
		return query;
	},
	
	xml2json:function(request){
		var parseXML=function(node){
			if(node.childNodes.length==1 && (node.firstChild.nodeType==3 || node.firstChild.nodeType==4)) return node.firstChild.data; //if text node
			var hash={};
			for(var i=0, childs=node.childNodes, l=childs.length; i<l; i++)
				if(childs[i].nodeType==1)
					if(hash[childs[i].tagName]){ //if node has array type
						if(typeof hash[childs[i].tagName]=="string" || (typeof hash[childs[i].tagName]=="object" && !hash[childs[i].tagName].length)) 
							hash[childs[i].tagName]=[hash[childs[i].tagName]]; //reinit node (set array type)
						hash[childs[i].tagName][hash[childs[i].tagName].length]=parseXML(childs[i]);
						}
					else hash[childs[i].tagName]=parseXML(childs[i]);
			return hash;
		};
		var doc=ie?request.responseXML:(new DOMParser()).parseFromString(request.responseText, "text/xml"); //get XML content
		var response={obj:{}, text:''};
		if(doc && doc.documentElement) response.obj=parseXML(doc);
		return response;
	},
	
	onerror:function(message){alert("Server output error...\n"+message)}
};