/**
Cross-browser Ajax implementations
Copyright 2006 Adam R. Wolff
*/


var ajax = new function(){
	/**
	    Cross-browser engine for XML/JSON-HTTP
	    * Array errlog = log of errors encountered by this engine
	*/
	
	//Private fields
    if(typeof(strXMLVer)=="undefined") strXMLVer = ".4.0";

    var xml2json = "<xsl:stylesheet version=\"1.0\" xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\" xmlns:msxsl=\"urn:schemas-microsoft-com:xslt\" xmlns:js=\"http://www.json.org\"><xsl:output method=\"text\"/><xsl:strip-space elements=\"*\"/><xsl:template match=\"/\">{ <xsl:apply-templates select=\"*\" mode=\"object\"/> }</xsl:template><xsl:template match=\"*\" mode=\"object\"><xsl:if test=\"count(*) = 0 and count(@*) = 0 and normalize-space(.) = ''\">\"<xsl:value-of select=\"local-name()\"/>\": \"\" <xsl:if test=\"position() &lt; last()\">, </xsl:if></xsl:if><xsl:if test=\"count(*) = 0 and (count(@*) > 0 or normalize-space(.) != '')\">\"<xsl:value-of select=\"local-name()\"/>\": { <xsl:apply-templates select=\"@*\"/> <xsl:if test=\"normalize-space(.) != ''\"><xsl:if test=\"count(@*) > 0\"> , </xsl:if>\"text\":\"<xsl:value-of select=\"normalize-space(.)\"/>\"</xsl:if>} <xsl:if test=\"position() &lt; last()\">, </xsl:if></xsl:if><xsl:if test=\"count(*) &gt; 0\"><xsl:if test=\"count(@*) &gt; 0\">\"<xsl:value-of select=\"local-name()\"/>\": { <xsl:apply-templates select=\"@*\"/> <xsl:if test=\"normalize-space(.) != ''\"><xsl:if test=\"count(@*) &gt; 0\"> , </xsl:if>\"text\":\"<xsl:value-of select=\"normalize-space(.)\"/>\"</xsl:if></xsl:if><xsl:variable name=\"is_array\"><xsl:apply-templates select=\"*\" mode=\"is_array\"/></xsl:variable><xsl:choose><xsl:when test=\"contains(string($is_array), '1')\"><xsl:if test=\"count(@*) &gt; 0\">, </xsl:if>\" <xsl:value-of select=\"local-name()\"/>\": [ <xsl:apply-templates select=\"*\" mode=\"array_element\"/> ] <xsl:choose><xsl:when test=\"count(@*) > 0 and position() &lt; last()\">}, </xsl:when><xsl:when test=\"count(@*) > 0\">}</xsl:when><xsl:when test=\"position() &lt; last()\">, </xsl:when></xsl:choose></xsl:when><xsl:otherwise><xsl:if test=\"count(@*) &gt; 0\">, </xsl:if><xsl:apply-templates select=\"*\" mode=\"object\"/><xsl:choose><xsl:when test=\"count(@*) &gt; 0 and position() &lt; last()\">}, </xsl:when><xsl:when test=\"count(@*) &gt; 0\">}</xsl:when><xsl:when test=\"position() &lt; last()\">, </xsl:when></xsl:choose></xsl:otherwise></xsl:choose></xsl:if></xsl:template><xsl:template match=\"*\" mode=\"array_element\">{ <xsl:apply-templates select=\"@*\"/> <xsl:if test=\"normalize-space(.) != ''\"><xsl:if test=\"count(@*) &gt; 0\"> , </xsl:if>\"text\":\"<xsl:value-of select=\"normalize-space(.)\"/>\"</xsl:if><xsl:if test=\"count(*) &gt; 0\"><xsl:if test=\"(count(@*) &gt; 0 or normalize-space(.) != '')\">,</xsl:if><xsl:apply-templates select=\"*\" mode=\"object\"/></xsl:if>}<xsl:if test=\"position() &lt; last()\">,</xsl:if></xsl:template><xsl:template match=\"@*\"><xsl:if test=\"position() &gt; 1\">,</xsl:if>\"<xsl:value-of select=\"local-name()\"/>\":\"<xsl:value-of select=\"normalize-space(.)\"/>\"</xsl:template><xsl:template match=\"*\" mode=\"is_array\"><xsl:variable name=\"name\" select=\"local-name()\"/><xsl:choose><xsl:when test=\"$name=local-name(following-sibling::*) or $name=local-name(preceding-sibling::*)\">1</xsl:when><xsl:otherwise>0</xsl:otherwise></xsl:choose></xsl:template></xsl:stylesheet>";
	
	var cache = new Array();
	var cachetimeout = 60;
	var waitmsg = null;
	var threadokay = true;
	this.errlog = new Array();
	
	/**
	Change the ActiveX version (for backward compatibility)
	*/
	this.setAXVer=function(strNewVer){
	    strXMLVer = strNewVer;
	};
	
	this.setCacheTimeout = function(intTimeout){
	/**
	    Set the number of seconds for which to cache transactions
	    * Int intTimeout = number of seconds.
	*/
	    if(typeof(intTimeout)=="number"){
	        cachetimeout = intTimeout;
	    }
	};
	
	setInterval(function(){
	    cache = null;
	    cache = new Array();
	    //window.status = ("Cleared ajax cache...");
	},300000);
	
	this.getXMLDom = function(){
		var o;
		if(document.implementation.createDocument){
			o = document.implementation.createDocument("","",null);
		}else if(window.ActiveXObject){
			try{
				o = new ActiveXObject("MSXML2.DOMDocument"+strXMLVer);
				o.setProperty("SelectionLanguage", "XPath");
			}catch(e){
			    alert("Could not create XML Parser.");
				return null;
			}
		}else{
		    alert("Could not find a suitable XML Parser.");
			return null;
		}
		o.validateOnParse = false;
		return o;
	};
	
	this.clearCache = function(urlSvc,indCache){
	    /**
	        Erase all or part of the engine's cache. With no args, it removes everything. With one argument, it removes all data from the url; with two args, it removes only the data from the given input message.
	        * URL urlSvc = url of the service to remove from the cache
	        * String indCache = the message index of the cache to remove.
	    */
	    if(typeof(urlSvc)=="undefined"){
	        for(url in cache){
	            cache[url] = "";
	        }
	    }else{
	   	    if(typeof(cache[urlSvc])=="object"){
		       if(typeof(indCache)=="undefined"){
		            cache[urlSvc] = "";
		       }else{
		           cache[urlSvc][indCache] = ""; 
		       }
		    }
		}
	};
	
	this.callSvc = function(urlSvc,strMsg,objHeader,fnCallback,fnFail,intTimeout){
	/**
		Do HTTP transaction.
		* URL urlSvc = url of the service to invoke
		* String strMsg = message to post to service (if any)
		* Object objHeader = headers to add to message
		* Function fnCallback = function to invoke on callback; first argument will be response object; second argument is an array of the arguments passed to this method (start @[1][6])
		* Function fnFail = function to invoke when the call fails; first argument will be response object; second argument is an array of the arguments passed to this method (start @[1][6])
		* Integer intTimeout = number of seconds to wait for a response; defaults to 10 
	*/
	    
	    var theArgs = arguments;
	    var theAjax = this;
	    if(typeof(intTimeout)=="undefined") intTimeout = 10;
	    if(typeof(strMsg)=="undefined") strMsg = "";
	    if(strMsg==null) strMsg = "";
	    var indCache = (strMsg!="") ? strMsg : "_x";
	    
		intTimeout = ((!isNaN(intTimeout)) ? intTimeout:10);
		try{
			var xmlHTTP = ((window.ActiveXObject)? new ActiveXObject("MSXML2.XMLHTTP"+strXMLVer): new XMLHttpRequest());
		}catch(err){
			return false;
		}
        
        var oPub = {
        "endpoint":urlSvc
        ,"msg":strMsg
        ,"header":objHeader
        ,"success":fnCallback
        ,"failure":fnFail
        ,"args":theArgs
        };
        function publish(rsp,timeout){
            if(typeof(timeout)!="boolean"){timeout=false;}
            oPub["response"] = rsp;
            oPub["timeout"] = timeout;
            script.publish("/ajax/receive",oPub);
        }

		if(typeof(cache[urlSvc])=="object"){
		    if(typeof(cache[urlSvc][indCache])=="object"){
		        //window.status = ("using cache");
		        setTimeout(function(){
		            fnCallback(cache[urlSvc][indCache],theArgs);
		            publish(cache[urlSvc][indCache]);
		        },100);
		        return;
		    }
		}
		
		xmlHTTP.open(((strMsg=="")?"GET":"POST"),urlSvc);
		
		if(typeof(objHeader)=="object"){
			for(header in objHeader){
				xmlHTTP.setRequestHeader(header,objHeader[header]);
			}
		}
		xmlHTTP.setRequestHeader("Content-type",(strMsg.indexOf("<")==0)?"text/xml":"application/x-www-form-urlencoded");
		
		xmlHTTP.onreadystatechange = function(){
			if(xmlHTTP.readyState==4){
			    try{document.body.style.cursor = "";}catch(err){}
			    clearTimeout(tmrCancel);
				if(xmlHTTP.status==200){
					if(typeof(cache[urlSvc])!="object") cache[urlSvc] = new Array();
					cache[urlSvc][indCache] = xmlHTTP;
					setTimeout(function(){
					    theAjax.clearCache(urlSvc,indCache);
					},(cachetimeout*1000));
					if(typeof(fnCallback)=="function"){
					    fnCallback(xmlHTTP,theArgs);
					    publish(xmlHTTP);
					}else{
					/*
					
					*/
					}
				}else{
					theAjax.errlog.push("Service \""+urlSvc+"\" returned HTTP "+xmlHTTP.status);
					if(typeof(fnFail)=="function"){
					    fnFail(xmlHTTP,theArgs);
					    publish(xmlHTTP);
					}
				}
			}
		};
		
		var tmrCancel = setTimeout(function(){
		    try{document.body.style.cursor = "";}catch(err){}
			xmlHTTP.abort();
			theAjax.errlog.push("Service \""+urlSvc+"\" did not respond in a timely fashion.");
			if(typeof(fnFail)=="function"){
			    fnFail(xmlHTTP,theArgs);
			    publish(xmlHTTP,true);
			}
		},(intTimeout*1000));
		xmlHTTP.send(strMsg);
	};
	
	this.getLastError = function(){
	    return(this.errlog[this.errlog.length-1]);
	};
	
	this.serializeXML = function(objXML){
	/**
		Get string representation of an XMLDOM object
		* XMLDocumentObject objXML = object to serialize
	*/
		if(window.ActiveXObject){
			return objXML.xml;
		}else{
			var s = new XMLSerializer();
 			return s.serializeToString(objXML);
		}
	};
	
	this.insertContent = function(xmlContent,xslStylesheet,divParent,bReplace){
	    /**
	    Transform XML to HTML and include it in the document.
	        * XMLDocumentObject xmlContent = the XML to insert
	        * XMLDocumentObject xslStylesheet = the XSL stylesheet to use, to format the XML.
	        * URL xslStylesheet = the URL of the XSL stylesheet to use, to format the XML.
	        * HTMLElement divParent = the place in the document into which to insert.
	        * Boolean bReplace = replace existing content?; defaults to true
	    */
	    if(typeof(bReplace)!="boolean") bReplace = true;
	    if(typeof(divParent)=="string") divParent = document.getElementById(divParent);
	    if(typeof(divParent)=="undefined"){
	        divParent = document.body;
	    }
	    divParent.disabled = true;
	    divParent.title = "Content Updating...";
	    var strContent;
	    try{
	        if(typeof(xslStylesheet)=="object"){
	        	strContent = xmlContent.transformNode(xslStylesheet);
	        	divParent.innerHTML = ((!bReplace) ? divParent.innerHTML : "")  + strContent;
	        	divParent.disabled = false;
	        	if(typeof(script.publish)=="function"){script.publish("/add/element",{"element":divParent});}
	        }else{
	            var theAjax = this;
	            var theContent = xmlContent;
	            var theParent = divParent;
	            var theReplace = bReplace;
	            this.callSvc(xslStylesheet,"",null,function(me){
	                theAjax.insertContent(theContent,me.responseXML,theParent,theReplace);
	            },function(){theParent.disabled=false; });
	        }
	    }catch(err){
	        this.errlog.push(err);
	    }
	};
	
	this.transformContent = function(divMe, xslStylesheet, divDest, bReplace){
	    /**
	    Apply XSL stylesheet to an element, rendering new content.
	    * HTMLElement divMe = source element;
	    * XMLDocumentObject xslStylesheet = the XSL stylesheet to use, to format the XML.
	    * URL xslStylesheet = the URL of the XSL stylesheet to use, to format the XML.
	    * HTMLElement divDest = destination element for new content; defaults to divMe (for replacement) if null
	    * Boolean bReplace = replace existing content?; defaults to true
	    */
	    if(typeof(divDest)=="undefined") divDest = divMe;
	    if(typeof(bReplace)!="boolean") bReplace = true;
	    var xmlContent = this.htmlToXML(divMe.innerHTML);
	    this.insertContent(xmlContent,xslStylesheet,divDest,bReplace); 
	};
	
	this.deSerializeXML = function(strXML){
	/**
		Turn an XML string into an XMLDOM object
		* String strXML = raw XML string
	*/
		try{
			if(window.ActiveXObject){
				var xmlDom = this.getXMLDom();
				//xmlDom.setProperty("SelectionNamespaces","xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\" xmlns:msxsl=\"urn:schemas-microsoft-com:xslt\" xmlns:js=\"http://www.json.org\"");
				xmlDom.loadXML(strXML);
				return xmlDom;
			}else{
				var parser = new DOMParser();
				return parser.parseFromString(strXML, "text/xml");
			}
		}catch(err){
		    this.errlog.push(err);
		}
	};
	
	
	this.wait = function(strMsg){
	    /**
        Show a "wait" message while some processing happens.	    
	    strMsg = message to show.
	    */
	   
	    
        if(waitmsg!=null){
            return false;
        }
        threadokay = false;
        waitmsg = document.createElement("div");
        with(waitmsg.style){
            position="absolute";
            top="0px";
            left="0px";
            zIndex="100";
            height="100%";
            width="100%";
            backgroundColor="White";
            if(typeof(opacity)!="undefined"){
                opacity = "0.7";
            }else{
                filter="alpha(opacity=70)";
                
            }
        }
        var p = waitmsg.appendChild(document.createElement("p"));
        p.appendChild(document.createTextNode(strMsg));
        with(p.style){
            fontFamily="arial";
            fontSize="24pt";
            fontWeight="bold";
            position="absolute";
            top="50%";
            left="50%";
            width:"300px";
            marginLeft="-150px";
        }
        document.body.appendChild(waitmsg);
       
        threadokay = true;  
	};
	
	this.unWait = function(){
	    threadokay = false;
	    if(waitmsg!=null){
	        document.body.removeChild(waitmsg);
	        waitmsg = null;
	    } 
	    threadokay = true;
	};
	
	
	this.htmlToXML = function(strHTML){
	    /**
	    Convert arbitrary, well-formed or non-well-formed HTML to XML, for parsing and xformation
	    * String strHTML = serialized HTML docuemnt(-fragment) to convert.
	    */
	    
	    var d = document.createElement('div');
	    d.innerHTML = strHTML;
	    var dom = this.getXMLDom();
        dom.appendChild(this.tidyXML(dom,d));
        return dom;
	};
	
	this.xhtmlDomToXML = function(objDom){ 
	     /**
	    Get an XML representation of a well-formed, XHTML dom object, for xpath parsing, etc.
	    MUCH faster than htmlToXML
	    * HTMLElement objDom = the element to convert. Must be well-formed
	    */
		var strObj = objDom.nodeName.toLowerCase();
		var escapeHTML = String(objDom.innerHTML).replace(/\=([^ \>\<\"]+)/ig,"=\"$1\"");
		escapeHTML = String(escapeHTML).replace(/<LI/g,"</LI><LI");
		escapeHTML = String(escapeHTML).replace(/^<\/LI[^>]*>/,"");
		if((strObj=="ul" || strObj=="ol") && !escapeHTML.match(/<\/li>$/i)) escapeHTML+="</LI>";
	    escapeHTML = String(escapeHTML).replace(/<input ([^>]+)>/ig,"<INPUT $1/>");
        escapeHTML = String(escapeHTML).replace(/<br *>/ig,"<BR/>");
        escapeHTML = String(escapeHTML).replace(/<option ([^>]*) *selected>/ig,"<OPTION $1 selected=\"selected\">");
		
	    return ajax.deSerializeXML("<"+strObj+">"+escapeHTML+"</"+strObj+">");	
	};
	
	
	this.xmlToJS = function(xmlObj){
	    /**
	        Retunrn an arbitrary JSON object from an arbitrary XML object.
	        * XMLDOM xmlObj = object to cast
	    */
	    var txt = xmlObj.selectNodes("//text()");
	    for(var x=0; x< txt.length;  x++){
	    	if(txt[x].nodeValue.indexOf("\"")>-1){
	    		var newtext = (txt[x].nodeValue.replace(/\"/ig,"'"));
	  			var p = txt[x].parentNode;
	  			p.removeChild(txt[x]);
	  			p.appendChild(xmlObj.createTextNode(newtext));	
	    	}
	    }
	    var strJS = xmlObj.transformNode(this.deSerializeXML(xml2json));
	    strJS = strJS.replace(/<[^>]+>/ig,"");
	    strJS = strJS.replace(/\" /ig,"\"");
	    return eval("("+ strJS +")"); 
	};

	
	this.jsToXML = function(obj,root,child){
		/**
		XML representation of an arbitrary JS object.
		* Object obj = Javascript Object to serialize.
		* String root = name of root node.
		* String child = default name of child nodes, for Arrays.
		*/
		if(typeof(obj)=="object"){
			if(typeof(root)=="undefined") root = "root";
			if(typeof(child)=="undefined") child = "child";
			var dom = this.getXMLDom();
			var doc = dom.appendChild(dom.createElement(root));
			var memberName;
			for(member in obj){
				memberName = (isNaN(member)) ? member : child;
				switch(typeof(obj[member])){
					case "object":
						doc.appendChild(this.jsToXML(obj[member],memberName,child).documentElement.cloneNode(true));
					break;
					case "string":
						doc.appendChild(dom.createElement(memberName)).appendChild(dom.createTextNode(String(obj[member])));
					break;
				}
			}
			return dom;
		}
	};
	
	this.jsToXMLString = function(obj,root,child){
		/**
		Serialized XML representation of an arbitrary JS object.
		* Object obj = Object to serialize.
		* String root = name of root node.
		* String child = default name of child nodes, for Arrays.
		*/
		return this.serializeXML(this.jsToXML(obj,root,child));
	}
	
	this.addSOAP = function(strXML){
		/**
			Wrap an XML message up in a SOAP envelope.
			* String strXML = the raw message.
		*/
		return "<soap:Envelope xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\"><soap:Body>" + strXML + "</soap:Body></soap:Envelope>";
			
	};
	
	this.tidyXML = function(xmlDom,myHTMLNode,intDepth){
		/**
			XML representation of a node from the current document. Used for XPathing through the document.
		*/
		
		try{
			if(typeof(intDepth)=="undefined"){
				intDepth = 100;
			}
			var n = xmlDom.createElement(String(myHTMLNode.nodeName).toLowerCase());
			//window.status = "Converting: "+n.nodeName;
			var myAtt;
			for(var x=0; x<myHTMLNode.attributes.length; x++){
				myAtt = myHTMLNode.attributes[x];
				if(myAtt.nodeValue!=null && myAtt.nodeValue!=""){
					n.setAttribute(myAtt.nodeName, myAtt.nodeValue);	
				}
			}
			
			if(myHTMLNode.checked){
			    n.setAttribute("checked","checked");
			}
			
			var objStyle = myHTMLNode.style;
			n.setAttribute("style",objStyle.cssText);
		    
		    
		
			var cn = myHTMLNode.childNodes;
			for(var x=0; x<cn.length; x++){
				switch(cn[x].nodeType){
					case 1:
						if(cn[x].nodeName!="code"){
							if(intDepth >0) n.appendChild(this.tidyXML(xmlDom,cn[x],(intDepth -1)));
						}
					break;
					case 3:
						n.appendChild(xmlDom.createTextNode(cn[x].nodeValue));
					break;
				}
			}
					
			if(n.childNodes.length==0 && (n.nodeName=="textarea" || n.nodeName=="div")){
				n.appendChild(xmlDom.createTextNode(" "));
			}
			
			return n;
		}catch(err){
			window.status = (err);
			return (xmlDom.createElement("br"));
		}
	};
		
		/*
	Prefix-correcting evaluate statement from http://www.faqts.com/knowledge_base/view.phtml/aid/34022/fid/119
	*/
	
	
	
	
	if( document.implementation.hasFeature("XPath", "3.0") ){
	
	XMLDocument.prototype.transformNode = function(objXML){
		var processor = new XSLTProcessor();
		processor.importStylesheet(objXML);
		var s = new XMLSerializer();
		try{
			return (s.serializeToString(processor.transformToDocument(this)));
		}catch(err){
			return (s.serializeToString(processor.transformToDocument(this.documentElement)));
		}
	};
	
	
	 XMLDocument.prototype.selectNodes = function(cXPathString, xNode){
	  if( !xNode ) {
	   xNode = this;
	  };
	    
	  var defaultNS = this.defaultNS;
	
	  var aItems = this.evaluate(cXPathString, xNode,{
	   normalResolver:
	    this.createNSResolver(this.documentElement),
	        lookupNamespaceURI : function (prefix) {
	           switch (prefix) {
	             case "dflt":
	                return defaultNS;
	             default:
	                return this.normalResolver.lookupNamespaceURI(prefix);
	           }
	        }
	      },XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,null);
	
	  var aResult = [];
	  for( var i = 0; i < aItems.snapshotLength; i++){
	           aResult[i] =  aItems.snapshotItem(i);
	  }
	  return aResult;
	 };
	
	 Element.prototype.selectNodes = function(cXPathString){
	  if(this.ownerDocument.selectNodes){
	   return this.ownerDocument.selectNodes(cXPathString, this);
	  }else{
	   throw "For XML Elements Only";
	  }
	 };
	
	 /* set the SelectionNamespaces property the same for NN or IE: */
	 XMLDocument.prototype.setProperty = function(p,v){
	  if(p=="SelectionNamespaces" && v.indexOf("xmlns:dflt")==0){
	   this.defaultNS = v.replace(/^.*=\'(.+)\'/,"$1");
	  }
	 };
	
	 XMLDocument.prototype.defaultNS;
	
	}
	
	    /**
	Table from arbitrary XML
				@ HTMLElement elHost = where to put the new table
				@ XMLDOM xmlSource = source XML object from which to build the table
				@ XPath pathRows = Xpath selector for rows
				@ JSONArray oaCols = array of JSON objects defining the columns and their sources
					@name = colunm name
					@class = column CSS class
					@path = xpath relative to the row object. 
			*/
			this.xmlToTable = function(elHost,xmlSource,pathRows,oaCols){
				if(xmlSource == null || typeof(xmlSource) != "object"){return null;}
				
				var table = document.createElement("table");
				var thead = table.appendChild(document.createElement("thead")).appendChild(document.createElement("tr"));
				var tbody = table.appendChild(document.createElement("tbody"));
				for(var x=0; x<oaCols.length; x++){
					var th = thead.appendChild(document.createElement("th"));
					if(typeof(oaCols[x]["class"])!="undefined"){th.className=oaCols[x]["class"];}
					th.appendChild(document.createTextNode(oaCols[x]["name"]));
				}
				var row = xmlSource.selectNodes(pathRows);
				for(var x=0; x<row.length; x++){
					var tr = tbody.appendChild(document.createElement("tr"));
					for(var y=0; y<oaCols.length; y++){
						var td = tr.appendChild(document.createElement("td"));
						var data = row[x].selectNodes(oaCols[y]["path"]);
						td.appendChild(document.createTextNode( (data.length>0) ? data[0].nodeValue : String.fromCharCode(160)));
					}
				}
				
				elHost.appendChild(table);
				return table;
				
			};
			
			/**
			    Create an XML request for SOAP or POX services
			    @String meth = method (operation) name
			    @Object args = (complex?) key-value pairs reprenting the arguments
			    @Boolean soap = is this a SOAP service (needing an envelope)?
			    @String coll = name to use for multiple members of the same collection
			*/
			this.createRequest = function(meth,args,soap,coll){
                if(typeof(soap)!="boolean") soap = true;
                if(typeof(coll)!="string"){coll="item";}
                if(typeof(args)!="undefined"){
                    var r = ajax.jsToXML(args,meth,coll);
                }else{
                    var r = ajax.getXMLDom();
                    var d = r.appendChild(r.createElement(meth));
                }
               
                var str = ajax.serializeXML(r);
                if(soap){str = ajax.addSOAP(str);}
                return str;
            };
	
}

/**
Asynchronous, remote object
Object initAsynch
    String url = endpoint of service to hit.
    String operation = name of operation to invoke
    String params = string message to pass (URLEncoded / serialized XML)
    Object params = JSON object containing params to pass
    Boolean soap = does the service expect a SOAP wrapper?
    String xmlns = the default XMLNS of the payload message
    Object header = JSON object containing HTTP headers to pass (possibly including soapAction)
*/
  function AsynchRemote(initAsynch){
    ajax.setAXVer("");
  	var timeout = 10; /* default to 10-second timeout*/
  	this.remote = {data:null,xmldata:null,state:0,error:null};
  	var theAsynch = this;
  	this.asynch = (typeof(initAsynch)=="object") ? initAsynch : {};
  	
  	/**
  	    Set the timeout on the remote method call.
  	    @Int timeout = seconds to wait.
  	*/
  	this.setCancelTime = function(intTime){
  	    //window.status = ("Setting cancel time");
  	    timeout = intTime;
  	};
  	
  	this.load = function(){
  	    var strMsg;
  	    if(typeof(this.asynch.operation)=="string"){
  		    var xmlR = ajax.getXMLDom();
  		    var doc = xmlR.appendChild(xmlR.createElement(this.asynch.operation));
  		    if(typeof(this.asynch.xmlns)=="string") doc.setAttribute("xmlns",this.asynch.xmlns);
	  	    switch(typeof(this.asynch.params)){
	  		    case "string":
	  			    doc.appendChild(xmlR.createTextNode(this.asynch.params));
	  		    break;
	  		    case "object":
	  			    for(fld in this.asynch.params){
	  			        if(typeof(this.asynch.params[fld])=="string"){
	  				        doc.appendChild(xmlR.createElement(fld)).appendChild(xmlR.createTextNode(this.asynch.params[fld]));
	  			        }
	  			    }
	  		    break;
	  	    }
	  	    strMsg = ((this.asynch.soap) ? ajax.addSOAP(ajax.serializeXML(xmlR)) : ajax.serializeXML(xmlR));
  	    }else if(typeof(this.asynch.params)!="undefined"){
  	        switch(typeof(this.asynch.params)){
  	            case "string":
  	                strMsg = this.asynch.params;
  	            break;
  	            case "object":
  	                strMsg = "";
  	                for(fld in this.asynch.params){
  	                    if(typeof(this.asynch.params[fld])=="string"){
	  			            strMsg += fld+"="+escape(this.asynch.params[fld])+"&";
	  			        }
	  			    }
	  			    strMsg = strMsg.replace(/\&$/,"");
  	            break;
  	        }
  	    }
      	
  	    ajax.callSvc(this.asynch.url,strMsg,this.asynch.header,function(me){
  	        theAsynch.remote.status = 200;
  	        var responseXML = ajax.deSerializeXML(me.responseText);
  		    if(ajax.serializeXML(responseXML)!=""){
  		        theAsynch.remote.data = ajax.xmlToJS(responseXML);
  		        theAsynch.remote.xmldata = responseXML;
  		    	theAsynch.remote.state = 1;
  		    } else if(me.responseText.indexOf("<")==0){
  		    	var myXML = me.responseText;
  		    	try{
	  		    	theAsynch.remote.xmldata = ajax.deSerializeXML(myXML);
	  		    	if(theAsynch.remote.xmldata.parseError==0) theAsynch.remote.data = ajax.xmlToJS(theAsynch.remote.xmldata);
	  		    	theAsynch.remote.state = 1;
  		    	}catch(err){
  		    		/* not well formed. */
  		    		theAsynch.remote.error = "XML is not well-formed.";
  		    		theAsynch.remote.state = -1;
  		    	}
  		    }else{
  		    	try{
  		    		theAsynch.remote.data = eval("("+me.responseText+")");
  		    		theAsynch.remote.state = 1;
  		    	}catch(err){
  		    		/* Not correct JSON */
  		    		theAsynch.remote.error = "Bad JSON.";
  		    		theAsynch.remote.state = -1;
  		    	}
  		    }
  		     
  		    if(typeof(theAsynch.onload)=="function"){
  		        //window.status = ("Ajax success state");
  			    theAsynch.onload();	
  		    }
  	    },function(me){
  	        /* alert("Ajax error state.\n\n"+me.responseText); */
  	        if(me.state==4){
  		        theAsynch.remote.status = me.status;
  		        theAsynch.remote.error = me.responseText;
  		        theAsynch.remote.state = -1;
  		    }else{
  		        theAsynch.remote.status = 0;
  		        theAsynch.remote.error = "Response timed out";
  		        theAsynch.remote.state = -2;
  		    }
  		    if(typeof(theAsynch.onload)=="function") theAsynch.onload();	
  	    },timeout);
  	    
  	};
  	//this.load();
    
  };
