/* --------------------------------------------------------------------------------------------------------------
*	API:			JSMX (JavaScript MX) - This is a ColdFusion API for AJAX.	
*	AUTHOR: 		Todd Kingham [todd@lalabird.com] - Jan Jannek [jan.jannek@Cetecom.de]
*	CREATED:		8.21.2005
*	VERSION:		2.5.1
*	DESCRIPTION:	This API uses XMLHttpRequest to post/get data from a ColdFusion interface.
*					The CFC's/CFM's will return a string representation of a JS variable: response_param.
*					The "onreadystatechange event handler" will eval() the string into a JS variable 
*					and pass the value back to the "return function". To Download a full copy of the sample 
*					application visit: http://www.lalabird.com/JSMX/?fa=JSMX.downloads
*
*	HISTORY:		2.0.0:	Todd: Scripted Out Original Version
*					2.1.0:	Todd: Modified for Download
*					2.2.0:	Todd: Modified the firstWord() function to be backward compatable with
*								  CF5 and to be more stable all-around.
*					2.3.0:	Todd: Added "wait div" functionality
*					2.4.0:	Todd: XML!!!! Now JSMX will allow you to pass XML Documents to the API in
*								  addition to the original JavaScript method.
*					2.4.1	Jan:  2006-02-16, XMLHTTP requests can now handle more than one request at once. By placing the onreadystatechange event as a local variable inside the actual http() function.
*							Jan:  Added fix for strange IE bug that returned Header Info.
*							Todd: Added the jsmx object to allow users to override defaults and set custom "async", "wait" and "error" methods
*					2.5.0:	Todd: Added JSON Support! So now you can pass JavaScript, XML, or JSON.
					2.5.1	Todd: Version 2.5.0 was premature. Needed to fix an eval() bug when I introduced JSON.
*
*	LICENSE:		THIS IS A OPEN SOURCE API. YOU ARE FREE TO USE THIS API IN ANY APPLICATION,
*               	TO COPY IT OR MODIFY THE FUNCTIONS FOR YOUR OWN NEEDS, AS LONG THIS HEADER INFORMATION
*              	 	REMAINS IN TACT AND YOU DON'T CHARGE ANY MONEY FOR IT. USE THIS API AT YOUR OWN
*               	RISK. NO WARRANTY IS EXPRESSED OR IMPLIED, AND NO LIABILITY ASSUMED FOR THE RESULT OF
*               	USING THIS API.
*
*               	THIS API IS LICENSED UNDER THE CREATIVE COMMONS ATTRIBUTION-SHAREALIKE LICENSE.
*               	FOR THE FULL LICENSE TEXT PLEASE VISIT: http://creativecommons.org/licenses/by-sa/2.5/
*
-----------------------------------------------------------------------------------------------------------------*/
/* UNCOMMENT THE FOLLOWING LINE IF YOU WILL BE RETURNING QUERY OBJECTS. (note: you may need to point the SRC to an alternate location.*/
//document.writeln('<SCRIPT TYPE="text/javascript" LANGUAGE="JavaScript" SRC="/CFIDE/scripts/wddx.js"></SCRIPT >');

jsmx = new jsmxConstructor();
function jsmxConstructor(){
	this.async = true;
	this.onError = onError;
	this.onWait = popWait;
	this.onWaitEnd = killWait;
}


// perform the XMLHttpRequest();
function http(verb,url,rm,qry) {
    //reference our arguments
	var callback = rm;
	//var re = new RegExp("\&");
	//Escaped_Password = New_Salted_Password.replace(re, '\&amp;');
	//alert(qry);
	
	var qryStr = (!qry) ? '' : toQueryString(qry);
	try{//this should work for most modern browsers excluding: IE Mac
		var req = ( window.XMLHttpRequest ) ? new XMLHttpRequest() : new ActiveXObject("Microsoft.XMLHTTP") ;
			req.onreadystatechange = function(){
			switch(req.readyState){
				case 1: jsmx.onWait(); break;
				case 2: break;
				case 3: break;
				case 4:
					jsmx.onWaitEnd();
					if ( req.status == 200 ){// only if "OK"
						try{
							rObj = parseResponse( req ) ;
							callback( rObj );
						}catch(e){ 
							jsmx.onError('Parsing Error: The value returned could not be evaluated.');
						}
					}else{ 
						jsmx.onError("There was a problem retrieving the data:\n" + req.statusText);
					}
					break;
				}
			}
			req.open( verb , noCache(url) , jsmx.async );
			if(verb.toLowerCase() == 'post')	
			req.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
			req.send(qryStr);
	}catch(e){//a browser not equiped to handle XMLHttp
		//jsmx.onError("There was a problem retrieving the data:");
	}
}

/*--- BEGIN: RESPONSE PARSING FUNCTIONS ---*/
	function parseResponse(rO){
		//if xml just send it on.
		if(rO.getResponseHeader("Content-Type").split(';')[0] == 'text/xml'){	
			return rO.responseXML;
		}	
		
		var str = rO.responseText;
		
		// jan.jannek@cetecom.de, 2006-02-16, weird error: some IEs show the responseText followed by the complete response (header and body again) 
		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);
			}
		}		
		
		//DO THE STRING EVAL
		try{//next try JSON eval();
			return parseJSON(str);
		}catch(e){//then try Classic eval();
			return parseJS(str);
		}
	}	
	function parseJS(str){ 
		eval(str);
		var r = eval(str.split('=')[0].replace(/\s/g,''));
		return r;
	}
	function parseJSON(str){
		return  eval('('+str+')');;
	}
/*--- END: RESPONSE PARSING FUNCTIONS ---*/


/*--- BEGIN: REQUEST PARAMETER FUNCTIONS ---*/
	function toQueryString(obj){
		//determine the variable type
		if(typeof(obj) == 'string')
			return obj;
		if(typeof(obj) == 'object'){
			if(typeof(obj.elements) == 'undefined')//It's an Object()!
				return object2queryString(obj);
			else //It's a form!
				return form2queryString(obj);
		}	
	}
	
	function object2queryString(obj){
		var ar = new Array();
		
		for(x in obj) ar[ar.length] = x+'='+obj[x];
		var temp = ar.join('::::::::::');
		temp = temp.replace(/&/g, "%26");
		temp = temp.replace(/::::::::::/g, "&");
		return temp;
	}
	
	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(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(elm.value);
							}	
							break;
						
						case "checkbox":
							if(elm.checked){
								if(typeof(obj[nm]) == 'undefined') obj[nm] = new Array();
								obj[nm][obj[nm].length] = escape(elm.value);
							}	
							break;
						
						default:
							if(typeof(obj[nm]) == 'undefined') obj[nm] = new Array();
							obj[nm][obj[nm].length] = escape(elm.value);
							break;
					}
				}
			}catch(e){}
		}
		for(x in obj) ar[ar.length] = x+'='+obj[x].join(',');
	return ar.join('&');
	}
/*--- END: REQUEST PARAMETER FUNCTIONS ---*/


//IE likes to cache so we will fix it's wagon!
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(){ 
	proc = document.getElementById("JSMX_loading");
	if( proc == null ){
		var p = document.createElement("div");
		p.id = "JSMX_loading";
		document.body.appendChild(p);
	}
}

function killWait(){
	proc = document.getElementById("JSMX_loading");
	if( proc != null ) document.body.removeChild(proc);
}

function onError(str){
	alert(str);
}