/*
  EXCMS(C) 2007-2009 Sinoican Inc.
  $Id: ajax.js 1489 2010-05-23 13:22:57Z zhangxuelin $
*/
ajax={
	isIE:!-[1,],
	TRANS_ID:1000,
	head:document.getElementsByTagName("head")[0],
	request:function(method,url,cb,data,options){
		if(options){
			var hs=options.headers;
			if(hs){for(var h in hs){if(hs.hasOwnProperty(h))this.initHeader(h,hs[h],false)}}
		}
		if(typeof data=="object"){data.ajax=1;data=this.urlEncode(data)}else{if(data)data+='&';else data='';data+='ajax=1';}
		method=method.toUpperCase();
		if(method=='GET'&&data){url+=(url.indexOf('?')!=-1?'&':'?')+data+'&excmstime='+(new Date().getTime())}
		var m=url.match(/.*\:\/\/([^\/]*).*/);
		var domain=typeof m != "undefined" && m != null ? m[1] : url;
		if(m && domain != document.domain){ // cross domain
			if(method=='POST'&&data){if(url.indexOf('?')<0)url+='?';url+=data}
			var transId = ++this.TRANS_ID;
			var trans = {
                id:transId,
                cb:"crossDomainCallback"+transId,
                scriptId:"crossDomainScript"+transId,
                url:url,
                callback:cb
            };
			var conn=this;
			window[trans.cb]=function(o){conn.handleResponse(o,trans)};
			url +=  '&crossDomainCallback=' + trans.cb;
			var script = document.createElement("script");
            script.setAttribute("src", url);
            script.setAttribute("type", "text/javascript");
            script.setAttribute("id", trans.scriptId);
            this.head.appendChild(script);
		}else{
			return this.asyncRequest(method,url,cb,data);
		}
	},
	
	serializeForm:function(f){
            if(typeof f=='string')f=(document.getElementById(f)||document.forms[f])
            var el,name,val,disabled,data='',hasSubmit=false;
            for(var i=0; i < f.elements.length; i++){
                el=f.elements[i];
                disabled=f.elements[i].disabled;
                name=f.elements[i].name;
                val=f.elements[i].value;
                if(!disabled&&name){
                    switch(el.type){
                        case 'select-one':
                        case 'select-multiple':
                            for(var j=0;j<el.options.length;j++){if(el.options[j].selected){if(this.isIE){data+=encodeURIComponent(name)+'='+encodeURIComponent(el.options[j].attributes['value'].specified?el.options[j].value:el.options[j].text)+'&'}else{data+=encodeURIComponent(name)+'='+encodeURIComponent(el.options[j].hasAttribute('value')?el.options[j].value:el.options[j].text)+'&'}}}
                            break;
                        case 'radio':
                        case 'checkbox':if(el.checked){data+=encodeURIComponent(name)+'='+encodeURIComponent(val)+'&'}break;
                        case 'file':
                        case undefined:
                        case 'reset':
                        case 'button':break;
                        case 'submit':if(hasSubmit == false){data+=encodeURIComponent(name)+'='+encodeURIComponent(val)+'&';hasSubmit=true}break;
                        default:data+=encodeURIComponent(name)+'='+encodeURIComponent(val)+'&'; break;
                    }
                }
            }
            data=data.substr(0,data.length - 1);
            return data;
        },
	
	asyncRequest:function(method,uri,callback,postData){
		var o=this.getConnectionObject();
		if(!o){return null}
		else{
			o.conn.open(method,uri,true);
			if(this.useDefaultXhrHeader){if(!this.defaultHeaders['X-Requested-With']){this.initHeader('X-Requested-With',this.defaultXhrHeader,true)}}
			if(postData&&this.useDefaultHeader &&(!this.hasHeaders||!this.headers['Content-Type'])){this.initHeader('Content-Type',this.defaultPostHeader)}
			if(this.hasDefaultHeaders||this.hasHeaders){this.setHeader(o)}
			this.handleReadyState(o,callback);
			o.conn.send(postData||null);
			return o;
		}
	},


	headers:{},
	hasHeaders:false,
	useDefaultHeader:true,
	defaultPostHeader:'application/x-www-form-urlencoded; charset=UTF-8',
	useDefaultXhrHeader:true,
	defaultXhrHeader:'XMLHttpRequest',
	hasDefaultHeaders:true,
	defaultHeaders:{},
	poll:{},
	timeout:{},
	pollInterval:50,
	transactionId:0,
	setProgId:function(id){this.activeX.unshift(id);},
	setDefaultPostHeader:function(b){this.useDefaultHeader=b},
	setDefaultXhrHeader:function(b){this.useDefaultXhrHeader=b},
	setPollingInterval:function(i){if(typeof i=='number'&&isFinite(i))this.pollInterval=i},

	createXhrObject:function(transactionId){
		var obj,http;
		try{http=new XMLHttpRequest();obj={conn:http,tId:transactionId}}
		catch(e){for(var i=0;i<this.activeX.length;++i){try{http=new ActiveXObject(this.activeX[i]);obj={conn:http,tId:transactionId};break}catch(e){}}}
		finally{return obj}
	},

	getConnectionObject:function(){
		var o;
		var tId=this.transactionId;
		try{o=this.createXhrObject(tId);if(o){this.transactionId++}}catch(e){}finally{return o}
	},

	handleReadyState:function(o,callback){
		var oConn=this;
		if(callback&&callback.timeout){this.timeout[o.tId]=window.setTimeout(function(){oConn.abort(o,callback,true)},callback.timeout)}
		this.poll[o.tId]=window.setInterval(
			function(){
				if(o.conn&&o.conn.readyState == 4){
					window.clearInterval(oConn.poll[o.tId]);
					delete oConn.poll[o.tId];
					if(callback&&callback.timeout){window.clearTimeout(oConn.timeout[o.tId]);delete oConn.timeout[o.tId]}
					oConn.handleTransactionResponse(o,callback);
				}
		},this.pollInterval);
	},

	handleTransactionResponse:function(o,callback,isAbort){
		if(!callback){this.releaseObject(o);return}
		var httpStatus,responseObject;
		try{if(o.conn.status !== undefined&&o.conn.status != 0){httpStatus=o.conn.status}else{httpStatus=13030}}catch(e){httpStatus=13030}
		if(httpStatus>=200&&httpStatus<300){
			responseObject=this.createResponseObject(o,callback.argument);
			if(callback.success){if(!callback.scope){callback.success(responseObject)}else{callback.success.apply(callback.scope,[responseObject])}}
		}
		else{
			switch(httpStatus){
				case 12002:
				case 12029:
				case 12030:
				case 12031:
				case 12152:
				case 13030:
					responseObject=this.createExceptionObject(o.tId,callback.argument,(isAbort?isAbort:false));
					if(callback.failure){if(!callback.scope){callback.failure(responseObject)}else{callback.failure.apply(callback.scope,[responseObject])}}
					break;
				default:
					responseObject=this.createResponseObject(o,callback.argument);
					if(callback.failure){if(!callback.scope){callback.failure(responseObject)}else{callback.failure.apply(callback.scope,[responseObject])}}
			}
		}
		this.releaseObject(o);
		responseObject=null;
	},

	createResponseObject:function(o,callbackArg){
		var obj={};
		var headerObj={};
		try{
			var headerStr=o.conn.getAllResponseHeaders();
			var header=headerStr.split('\n');
			for(var i=0; i < header.length; i++){
				var delimitPos=header[i].indexOf(':');
				if(delimitPos != -1){headerObj[header[i].substring(0,delimitPos)]=header[i].substring(delimitPos+2)}
			}
		}
		catch(e){}
		obj.tId=o.tId;
		obj.status=o.conn.status;
		obj.statusText=o.conn.statusText;
		obj.getResponseHeader=headerObj;
		obj.getAllResponseHeaders=headerStr;
		obj.responseText=o.conn.responseText;
		obj.responseXML=o.conn.responseXML;
		if(typeof callbackArg !== undefined){obj.argument=callbackArg}
		return obj;
	},

	createExceptionObject:function(tId,callbackArg,isAbort){
		var COMM_CODE=0;
		var COMM_ERROR='communication failure';
		var ABORT_CODE=-1;
		var ABORT_ERROR='transaction aborted';
		var obj={};
		obj.tId=tId;
		if(isAbort){obj.status=ABORT_CODE;obj.statusText=ABORT_ERROR}else{obj.status=COMM_CODE;obj.statusText=COMM_ERROR}
		if(callbackArg){obj.argument=callbackArg}
		return obj;
	},

	initHeader:function(label,value,isDefault){
		var headerObj=(isDefault)?this.defaultHeaders:this.headers;
		if(headerObj[label]===undefined){headerObj[label]=value}else{headerObj[label]=value+","+headerObj[label]}
		if(isDefault){this.hasDefaultHeaders=true}else{this.hasHeaders=true}
	},

	setHeader:function(o){
		if(this.hasDefaultHeaders){
			for(var prop in this.defaultHeaders){
				if(this.defaultHeaders.hasOwnProperty(prop)){o.conn.setRequestHeader(prop,this.defaultHeaders[prop])}
			}
		}
		if(this.hasHeaders){
			for(var prop in this.headers){
				if(this.headers.hasOwnProperty(prop)){o.conn.setRequestHeader(prop,this.headers[prop])}
			}
			this.headers={};
			this.hasHeaders=false;
		}
	},

	resetDefaultHeaders:function(){
		delete this.defaultHeaders;
		this.defaultHeaders={};
		this.hasDefaultHeaders=false;
	},

	abort:function(o,callback,isTimeout){
		if(this.isCallInProgress(o)){
			o.conn.abort();
			window.clearInterval(this.poll[o.tId]);
			delete this.poll[o.tId];
			if(isTimeout){delete this.timeout[o.tId]}
			this.handleTransactionResponse(o,callback,true);
			return true;
		}
		else{return false}
	},

	isCallInProgress:function(o){if(o.conn){return o.conn.readyState!=4&&o.conn.readyState!=0}else{return false}},
	releaseObject:function(o){o.conn=null;o=null},
	activeX:['MSXML2.XMLHTTP.3.0','MSXML2.XMLHTTP','Microsoft.XMLHTTP'],
	
	urlEncode:function(o){
		if(!o){return ""}
		var buf=[];
		for(var key in o){
			var ov=o[key],k=encodeURIComponent(key);
			var type=typeof ov;
			if(type == 'undefined'){buf.push(k,"=&")}
			else if(type != "function"&&type != "object"){buf.push(k,"=",encodeURIComponent(ov),"&")}
			else if(this.isArray(ov)){if(ov.length){for(var i=0,len=ov.length;i<len;i++){buf.push(k,"=",encodeURIComponent(ov[i]===undefined?'':ov[i]),"&")}}else{buf.push(k,"=&")}}
		}
		buf.pop();
		return buf.join("");
	},
	
	isArray:function(v){return v&&typeof v.length=='number'&&typeof v.splice=='function'},
	jsondecode:function(json){if(typeof json=='object')return json;try{return eval("("+json+")")}catch(e){return{}}},

	update:function(element,method,uri,data,callback){
		var tthis=this;
		this.request(method,uri,{success:function(response){
			if(typeof element!=='object'){element=tthis.getDom(element);}
			if(element){tthis.setInnerHTML(element, response.responseText)}
			if(callback){if(typeof(callback) == 'function'){callback()}else{try{eval(callback)}catch(e){}}}
		}},data);
	},
	
	getDom:function(o){if(document.getElementById&&document.getElementById(o)){return document.getElementById(o)}else if(document.all&&document.all(o)){return document.all(o)}else if(document.layers&&document.layers[o]){return document.layers[o]}else{return false}},
	
	destroyTrans:function(trans, isLoaded){
        this.head.removeChild(document.getElementById(trans.scriptId));
        //clearTimeout(trans.timeoutId);
        if(isLoaded){window[trans.cb] = undefined;try{delete window[trans.cb];}catch(e){}}
		else{window[trans.cb] = function(){window[trans.cb]=undefined;try{delete window[trans.cb]}catch(e){}}}
    },
	
	handleResponse : function(o, trans){
        this.trans = false;
        this.destroyTrans(trans, true);
       if(trans.callback.success)trans.callback.success({responseText:o});
    },
	setInnerHTML : function (el, html){ 
		var ua = navigator.userAgent.toLowerCase(); 
		if (ua.indexOf('msie') >= 0 && ua.indexOf('opera') < 0) { 
			html = '<div style="display:none">for IE</div>' + html;
			html = html.replace(/<script([^>]*)>/gi, '<script$1 defer>'); 
			el.innerHTML = html; 
			el.removeChild(el.firstChild); 
		}else{ 
			var el_next = el.nextSibling; 
			var el_parent = el.parentNode; 
			el_parent.removeChild(el); 
			el.innerHTML = html; 
			el_next ? el_parent.insertBefore(el, el_next) : el_parent.appendChild(el);
		} 
	} 
};
