/* --------------------------------------------------------------------------------------------------------------
*	API:			JSMX (JavaScript MX) - Universal Ajax API for ColdFusion, PHP, .NET, or anything other language.
*	AUTHOR: 		Todd Kingham [todd@lalabird.com] with contributions by Jan Jannek [jan.jannek@Cetecom.de] and Yin Zhao [bugz_podder@yahoo.com]
-----------------------------------------------------------------------------------------------------------------*/

var jsmx=new jsmxConstructor()

function jsmxConstructor(){
	this.isJSMX=true
	this.async=true
	this.debug=false
	this.waitDiv='JSMX_loading'
	this.http=http
	this.onWait=_popWait
	this.onWaitEnd=_killWait
	this.onError=_onError
}

function xhr_createObj(){
    var requestObj=null
	try{requestObj=new XMLHttpRequest()}
	catch(e){
		var msObjects=new Array('MSXML2.XMLHTTP.6.0','MSXML2.XMLHTTP.5.0','MSXML2.XMLHTTP.4.0','MSXML2.XMLHTTP.3.0','MSXML2.XMLHTTP','Microsoft.XMLHTTP')
		for(var i=0;i<msObjects.length&&!this.requestObj;i++){
			try{requestObj=new ActiveXObject(msObjects[i])}
			catch(e){}
		}
	}
	return requestObj
}

function http(verb,url,cb,q){
	var self=(this.isJSMX)?this:jsmx 
	var qryStr=(!q)?'':_toQueryString(q)
	var calledOnce=false
	try{
		var xhr=xhr_createObj()
		xhr.onreadystatechange=function(){
			switch(xhr.readyState){
				case 1:
					if(!calledOnce){
						self.onWait(self.waitDiv)
						calledOnce=true
					}
				break
				case 2:break
				case 3:break
				case 4:
					self.onWaitEnd(self.waitDiv)
					if(xhr.status==200){
						var success=true
						try{var rObj=_parseResponse(xhr)}
						catch(e){
							self.onError(xhr,self,1)
							success=false
						}
						if(success)cb(rObj)
					}else self.onError(xhr,self,2)
					delete xhr
				break
			}
		}
		xhr.open(verb,_noCache(url),self.async)
		if(verb.toLowerCase()=='post')xhr.setRequestHeader('Content-Type','application/x-www-form-urlencoded')
		xhr.send(qryStr)
	}catch(e){self.onError(xhr,self,3)}
}

function _parseResponse($$){
	var str=_cleanString($$.responseText)
	var xml=$$.responseXML
	if(xml!=null&&xml.childNodes.length)return xml //XML
	if(str.indexOf('<wddxPacket')==0)return _parseWDDX(str) //WDDX
	try{return eval('('+str+')')} //JSON
	catch(e){return _parseJS(str)} //JavaScript
}

function _cleanString(str){
	var rex=/\S/i
	str=str.substring(str.search(rex),str.length)
	var i=str.indexOf('HTTP/1')
	if(i>-1){
		str=str.substring(i,str.length)
		i=str.indexOf(String.fromCharCode(13,10,13,10))
		if(i>-1)str=str.substring(i+2,str.length)
	}
	return str	
}

function _parseJS(str){
	eval(str)
	var r=eval(str.split('=')[0].replace(/\s/g,''))
	return r
}

function _parseWDDX(str){
	var wddx=xmlStr2Doc(str)
	var data=wddx.getElementsByTagName('data')
	return _parseWDDXnode(data[0].firstChild)
}

function xmlStr2Doc(str){
	var xml
	if(typeof(DOMParser)=='undefined'){
		xml=new ActiveXObject('Microsoft.XMLDOM')
		xml.async='false'
		xml.loadXML(str)
	}else{
		var domParser=new DOMParser()
		xml=domParser.parseFromString(str,'application/xml')
	}
	return xml
}

function _parseWDDXnode(n){
	var val
	switch(n.tagName){
		case 'string':
		val=_parseWDDXstring(n)
		break
		case 'number':val=parseFloat(n.firstChild.data);break
		case 'boolean':val=n.getAttribute('value');break
		case 'dateTime':val=Date(n.firstChild.data);break
		case 'array':val=_parseWDDXarray(n);break
		case 'struct':val=_parseWDDXstruct(n);break
		case 'recordset':val=_parseWDDXrecordset(n);break
		case 'binary':val=n.firstChild.data;break
		case 'char':val=_parseWDDXchar(n);break
		case 'null':val='';break
		default:val=n.tagName;break
	}
	return val
}

function _parseWDDXstring(node){
	var items=node.childNodes
	var str=''
	for(var x=0;x<items.length;x++){
		if(typeof(items[x].data)!='undefined')str+=items[x].data
		else str+=_parseWDDXnode(items[x])
	}
	return str
}

function _parseWDDXchar(node){
	switch(node.getAttribute('code')){
		case '0d':return '\r'
		case '0c':return '\f'
		case '0a':return '\n'
		case '09':return '\t'
	}
}

function _parseWDDXarray(node){
	var items=node.childNodes
	var arr=new Array()
	for(var i=0;i<items.length;i++)arr[i]=_parseWDDXnode(items[i])
	return arr
}

function _parseWDDXstruct(node){
	var items=node.childNodes
	var obj=new Object()
	for(var i=0;i<items.length;i++)obj[items[i].getAttribute('name').toLowerCase()]=_parseWDDXnode(items[i].childNodes[0])
	return obj
}

function _parseWDDXrecordset(node){
	var qry=new Object()
	var fields=node.getElementsByTagName('field')
	var items
	var dataType
	var values
	for(var x=0;x<fields.length;x++){
		items=fields[x].childNodes
		values=new Array()
		for(var i=0;i<items.length;i++)values[values.length]=_parseWDDXnode(items[i])
		qry[fields[x].getAttribute('name').toLowerCase()]=values
	}
	return qry
}

function _toQueryString(obj){
	if(typeof(obj)=='string')return obj
	if(typeof(obj)=='object'){
		if(typeof obj.elements=='undefined')return _object2queryString(obj)
		else return _form2queryString(obj)
	}
}

function _object2queryString(obj){
	var ar=new Array()
	for(x in obj)ar[ar.length]=_escape_utf8(x)+'='+_escape_utf8(obj[x])
	return ar.join('&')
}

function _form2queryString(form){
	var obj=new Object()
	var ar=new Array()
	for(var i=0;i<form.elements.length;i++){
		try{
			elm=form.elements[i]
			nm=elm.name
			if(nm!=''){
				switch(elm.type.split('-')[0]){
					case 'select':
						for(var s=0;s<elm.options.length;s++){
							if(elm.options[s].selected){
								if(typeof(obj[nm])=='undefined')obj[nm]=new Array()
								obj[nm][obj[nm].length]=_escape_utf8(elm.options[s].value)
							}
						}
					break
					case 'radio':
						if(elm.checked){
							if(typeof(obj[nm])=='undefined')obj[nm]=new Array()
							obj[nm][obj[nm].length]=_escape_utf8(elm.value)
						}
					break
					case 'checkbox':
						if(elm.checked){
							if(typeof(obj[nm])=='undefined')obj[nm]=new Array()
							obj[nm][obj[nm].length]=_escape_utf8(elm.value)
						}
					break
					default:
						if(typeof(obj[nm])=='undefined')obj[nm]=new Array()
						obj[nm][obj[nm].length]=_escape_utf8(elm.value)
					break
				}
			}
		}catch(e){}
	}
	for(x in obj)ar[ar.length]=x+'='+obj[x].join(',')
	return ar.join('&')
}

function _noCache(url){
	var qs=new Array()
	var arr=url.split('?')
	var scr=arr[0]
	if(arr[1])qs=arr[1].split('&')
	qs[qs.length]='noCache='+new Date().getTime()
	return scr+'?'+qs.join('&')
}

function _popWait(id){
	proc=document.getElementById(id)
	if(proc==null){
		var p=document.createElement('div')
		p.id=id
		document.body.appendChild(p)
	}
}

function _killWait(id){
	proc=document.getElementById(id)
	if(proc!= null)document.body.removeChild(proc)
}

function _onError(obj,inst,errCode){
	var msg
	switch(errCode){
		case 1:msg=(inst.debug)?obj.responseText:'Parsing Error: The value returned could not be evaluated.';break
		case 2:msg=(inst.debug)?obj.responseText:'There was a problem retrieving the data:\n' + obj.status+':'+obj.statusText;break
		case 3:msg='Unsupported browser detected.';return;break
	}
	if(inst.debug){
		var debugWin=window.open('','error')
		debugWin.document.write(msg)
		debugWin.focus()
	}else alert(msg)
}

function _escape_utf8(data){
	if(data==''||data==null)return ''
	data=data.toString()
	var buf=''
	for (var i=0;i<data.length;i++){
		var c=data.charCodeAt(i)
		var bs=[]
		if(c>0x10000){
			bs[0]=0xF0 | ((c & 0x1C0000) >>> 18)
			bs[1]=0x80 | ((c & 0x3F000) >>> 12)
			bs[2]=0x80 | ((c & 0xFC0) >>> 6)
			bs[3]=0x80 | (c & 0x3F)
		}else if(c>0x800){
			bs[0]=0xE0 | ((c & 0xF000) >>> 12)
			bs[1]=0x80 | ((c & 0xFC0) >>> 6)
			bs[2]=0x80 | (c & 0x3F)
		}else if(c>0x80){
			bs[0]=0xC0 | ((c & 0x7C0) >>> 6)
			bs[1]=0x80 | (c & 0x3F)
		}else bs[0]=c
		if(c==10||c==13)buf+='%0'+c.toString(16)
		else if(bs.length==1&&c>=48&&c<127&&c!=92)buf+=data.charAt(i)
		else{for(var j=0;j<bs.length;j++)buf+='%'+bs[j].toString(16)}
	}
	return buf
}

function $(id){return document.getElementById(id)}
