//*************************** rbmAjax.js *******************************
//**** Version 2.03.0001
//**** last changed 14.02.2008
//**** (c) 2007, 2008 Bernd Rudolf
//
// 19.05.2007 rbmXMLObject.clearTarget() added
// 20.05.2007 rbmXMLObject.loadXML implemented
// 23.05.2007 url and formData of a Request is now stored for further use
// 23.05.2007 oFormToPost is already evaluated in getXML and loadHTTP receives
//				plain data now. This allows a direct call to loadHTTP with data
//
// 24.05.2007 ensure that "XMLeval=false"-requests to HTTP content use MSXML2.XMLHttp.3.0
// 24.05.2007 Param XMLeval implemented for constructor
// 28.07.2007 XMLObject.loadXML loads from XMLHTTPRequest.responseText instead of responseXML.xml
//            This is required if the xml is retrieved vom File instead of a Server probably due to
//			  missing request-headers (application/xml)
//
// v1.05.0001
// 05.09.2007 Error-Handling implemented. Object calls the function this.error() if defined
//
// v1.06.0001
// 22.09.2007 	getFormData updated for radio-Buttons
//				Object renamed to rbmAjax
//
// v2.02.0001
// 15.01.2008	getXML = function (strURL, formToPost, basync)	formToPost can either be an HTMLFormObject or a String
//			with name=value&name2=value2
//			getXML only triggers when readyState == 4 || 0. Note: abort-function still missing!!
//
//			renderToDoc extended by eval() for script fragments
//
// 23.01.2008	loadHTTP always uses onStateChange now, independent of sync or async transfers
//			add Opt. bReturn indicates whether to return a new object or to store the result in oXML
//
// 07.02.2008	Debug-Output for posted Formdata added
//
// 14.02.2008	onreadystatechange used xmlhttp.responseText to loadXML into the new MSXML object.
//			I cannot remember the reason why we initially switched form responseXML to responseText but 
//			I think it was for loading XML from files instead of a server.
//			But it caused encoding problems with some MSXML4 installations. So if a problem occurs we
//			now try to load the new object from responseXML.xml in a second step!
//**********************************************************************
//**********************************************************************


 
var $A = Array.from = function(iterable) {
if (!iterable) return [];
 if (iterable.toArray) {
 return iterable.toArray();
 } else {
 var results = [];
 for (var i = 0; i < iterable.length; i++)
 results.push(iterable[i]);
 return results;
 }
} 
 
Function.prototype.bind = function() {
 var __method = this, args = $A(arguments), object = args.shift();
 return function() {
 	return __method.apply(object, args.concat($A(arguments)));
 	}
} 

function globalEval(text)	{
	//alert(text);
	eval(text);
}
 
function rbmAjax (XMLeval)	{

	this.debug = false;	//set this to true for debugging Mesage-Boxes
	
	this.info = false;	//set this to get the XML-Data retrieved
	
	this.XMLeval = (XMLeval == null? true : XMLeval);	//true: Object handles XML to be evaluatated, false: Object handles html
	
	this.url = null;
	this.formData = null;
	
	this.oXML = null;
	this.oXSL = null;
	this.oResult = null;
	
	this.xsltProcessor = null;
	this.readyState = 0;

	this.target = null;
	this.bappend = false;
	
	this.waitElement = null;
	this.waitNode = null;
	this.newNode = null;
	this.waitStatus = false;
	
	this.done = null;
	
	this.error = null;
	
	this.clearTarget = function ()	{
		oElement = document.getElementById(this.target);
		while (oElement.hasChildNodes())	{
			oElement.removeChild(oElement.firstChild);
		}
	}
	
	this.wait = function (bon)	{
		if (this.waitElement && this.waitNode)	{

			if (bon)	{
				if (!this.waitStatus)	{
					this.newNode = this.waitElement.cloneNode(true);
					this.waitNode.appendChild(this.newNode);
					this.waitStatus = true;
				}
			}
			else	{
				if (this.waitStatus)	{
					try	{
						this.waitNode.removeChild(this.newNode);
					}
					catch(e)	{}
					this.waitStatus = false;
				}
	
			}
		}		
	}

	try	{
		this.XMLHttp = rbmXML.createXMLHttp(this.XMLeval);	//use MSXML2.xmlhttp.3.0 if !XMLeval !!
	}
	catch(e)	{
		if(this.error)
			this.error(e);
	}
	
	this.xml = function()	{
			if (this.oXML)
			var out = rbmXML.showXML(this.oXML);
			return out;
		};

	this.xsl = function()	{
			if (this.oXSL)
			var out = rbmXML.showXML(this.oXSL);
			return out;
		};
		
	this.createDoc = function ()	{
		if ( rbmXML.buseActiveX )	{
		}
		else	{
		}
	}	
		
	this.loadXML = function (sXML)	{
		
		var oR = null;
		
		if (rbmXML.buseActiveX)	{
			oR = rbmXML.createDoc();
			oR.loadXML(sXML);
		}
		else if (typeof DOMParser != "undefined")	{	
			var parser = new DOMParser();
			oR = parser.parseFromString(sXML, "text/xml");
		}
		

		return oR;
	}

	this.createXML = function ()	{
		this.oXML = rbmXML.createDoc();
	}

	this.importNode = function (oNode)	{
		//var clone = this.oXML.documentElement.importNode(oNode, true);
		this.oXML.documentElement.appendChild(clone);

	}

	this.getXML = function (strURL, formToPost, basync)	{	//formToPost can either be an HTMLFormObject or a String

		if (this.readyState == 4 || this.readyState == 0)	{
//XXX abort operation here if wanted
			this.readyState = 1;
			this.wait(true);
			this.url = strURL;
	
			this.formData = this.getFormData(formToPost);
			
			this.loadHTTP(strURL, this.formData, basync)
		}
	}	

	this.getXSL = function (strURL)	{
		this.readyState = 1;

		if (strURL)
			this.oXSL = this.loadHTTP(strURL, null, false, true);
			
		if ( !rbmXML.buseActiveX )	{										
			this.xsltProcessor = new XSLTProcessor();
			

				this.xsltProcessor.importStylesheet(this.oXSL);
		}
		else	{
			if (!strURL)
				this.oXSL = document.XSLDocument;		
			//if no XSL is specified use the one from the doc. Especially for clientside XSL
					
		}
	
		if (this.debug)
			alert("getXSL: " + this.xsl());

	}	
	
	this.onStateChange = function()	{
		if (this.XMLHttp.readyState == 4)	{
			if (this.debug)
				alert(this.XMLHttp.getAllResponseHeaders());
		
			if ( rbmXML.buseActiveX )	{

				if (this.XMLeval)	{
					var newObj = rbmXML.createDoc(); // new ActiveXObject("Microsoft.XMLDOM");

					newObj.loadXML(this.XMLHttp.responseText);
//20080214 due to encoding problems with some MSXML4 installations changed to:
					if (newObj.parseError.errorCode != 0)		{	
						newObj.loadXML(this.XMLHttp.responseXML.xml);
						if (newObj.parseError.errorCode != 0)		{	
							rbmXML.displayParseError(newObj.parseError);
							alert("error: " + this.XMLHttp.responseText);
						}
					}
				}

				if (this.debug || this.info)
					alert("onStateChange " + this.XMLHttp.responseText);
					
				this.readyState = 4;
	
				this.oXML = newObj;
			}
			else	{
				this.readyState = 4;
				
				if (this.debug || this.info)
					alert("onStateChange " + this.XMLHttp.responseText);
	
				this.oXML = this.XMLHttp.responseXML;		
			}
			
			if (this.target && this.XMLeval)
				this.renderToDoc(this.target, this.bappend)
			else if(this.target)
				this.copyXMLHttpToDoc(this.target, this.bappend); //copy the XMLHttp.responsetext to the doc because it cannot be evaluated
				
			this.wait(false);
			if(this.done)
				this.done();
		}
	}
	
	this.loadHTTP = function (strURL, sFormData, basync, bReturn)	{
		
		if (typeof basync == "undefined")
			basync = false;	//sychron-mode

		if (typeof bReturn == "undefined")
			bReturn = false;	//use onStateChange, bReturn = true: Return an XML-Object, false: use this.oXML

				
		if (this.debug)	
			alert("URL: " + strURL );
			
		if(!sFormData)	
			this.XMLHttp.open("GET", strURL, basync);
		else	{
			if (this.debug)
				alert("Post: " + sFormData)
			this.XMLHttp.open("POST", strURL , basync);
		}

			
		this.XMLHttp.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
		this.XMLHttp.setRequestHeader("Encoding", "ISO-8859-1");

		if (!bReturn)
			this.XMLHttp.onreadystatechange = this.onStateChange.bind(this);
		else	
			this.XMLHttp.onreadystatechange = {}
		
		try	{
			if(!sFormData)	
				this.XMLHttp.send(null)
			else
				this.XMLHttp.send(sFormData);
		}
		catch(e)	{
			alert("LoadHTTP: " + e.description + ": " + strURL);

		}
	
	
		if (bReturn)	{
			if ( rbmXML.buseActiveX )	{
				if (this.XMLeval)	{
					var newObj = rbmXML.createDoc(); // new ActiveXObject("Microsoft.XMLDOM");

					newObj.loadXML(this.XMLHttp.responseText);
					if (newObj.parseError.errorCode != 0)		{		
						rbmXML.displayParseError(newObj.parseError);
						alert(this.XMLHttp.responseXML.xml);
					}
				}
				this.readyState = 4;
	
				var result = (newObj ? newObj : null);
			}
			else	{
				this.readyState = 4;
	
				var result = (this.XMLHttp.responseXML ? this.XMLHttp.responseXML : null);
			}

//XXX was ist hier wenn ein XSL Stylesheet geladen wird???
/*			if (this.target && this.XMLeval)
				this.renderToDoc(this.target, this.bappend)
			else if(this.target)
				this.copyXMLHttpToDoc(this.target, this.bappend); //copy the XMLHttp.responsetext to the doc because it cannot be evaluated
				
			this.wait(false);
			if(this.done)
				this.done();
*/			
				
			return result;


		}

	};


	this.renderToDoc = function (element, bappend, oXML)	{
		
		if (!oXML)
			oXML = this.oXML;
		
		if (this.debug)	{
			alert("render to: " + element + " - append: " + bappend);

		}
			
		var oElement = document.getElementById(element);
		if (!oElement)	{
			alert("renderToDoc: Element " + element + " not found!");
			return;
		}

		if ( rbmXML.buseActiveX )	{	
				if (!this.oXSL)	{
					this.getXSL();		//if oXSL is not available try to load the document.XSLdocument
					if (!this.oXSL)	{	//no XSL available so copy the XMLHttp.responseText to the output
						this.copyXMLHttpToDoc(element, bappend);
						return;
					}
				}
								
				var strOut = oXML.transformNode(this.oXSL);
				if (this.debug || this.info)
					alert(strOut);
				if (strOut == "")	{ //Fehlermeldung der ASP/PHP Seite
					strOut = this.XMLHttp.responseText;
				}
					
				strOut = strOut.replace(/&lt;br \/&gt;/g, "<br />");	
					
				if (!bappend)	{
					oElement.innerHTML = strOut;
				}
				else	{
					var oNode = document.createElement("div");
					oElement.appendChild(oNode);
					oNode.innerHTML = strOut;
				}

				//this.corrCRinTextAreas(oElement);

				var aScripts = $(oElement).getElementsByTagName("script");
				var i;
				
				//alert(oElement.innerHTML);
				for(i = 0; i<aScripts.length; i++)	{
					//alert(aScripts[i].innerHTML);
					globalEval(aScripts[i].innerHTML);
				}

/*			}
			catch(e)	{
				if (oXML.parseError.errorCode != 0)		{		
					rbmXML.displayParseError(oXML.parseError)
					alert("renderToDoc: " + oXML.xml);
				}
				else
					alert("renderToDoc: e" + e.description)
			}
*/		}
		else	{
			
			if (!this.oXSL)	{
				this.copyXMLHttpToDoc(element, bappend);
				return;
			}
				

			var objOut = this.xsltProcessor.transformToFragment(oXML, document);


			if (!bappend && oElement.hasChildNodes())	{
				while (oElement.hasChildNodes())	{
					oElement.removeChild(oElement.firstChild);
				}

			}
			oElement.appendChild(objOut);
		}
	}
	
	
	this.copyXMLHttpToDoc = function (element, bappend)	{

		if (this.debug)	{
			alert("copy to: " + element + " - append: " + bappend);
		}
		if(this.XMLHttp.responseText.length > 0)	{
			var oElement = document.getElementById(element);
			if (!oElement)	{
				alert("copyXMLHttpToDoc: Element " + element + " not found!");
				return;
			}
			if (!bappend)	{
				oElement.innerHTML = this.XMLHttp.responseText;
			}
			else	{
				var oNode = document.createElement("div");
				oElement.appendChild(oNode);
				oNode.innerHTML = this.XMLHttp.responseText;
			}
		}	
	}
	
	this.selectSingleNode = function (sXPath /*:String*/, oXmlNs /*:Object*/) {
		
		var oNode = rbmXML.selectSingleNode(this.oXML, sXPath, oXmlNs);
		return oNode
	};




	this.getFormData = function (element)	{	//element specifies the form

		var strPost = "";
		var i;
		
		if(!element || typeof (element) != "object")
			return element;

		var myInput = element.getElementsByTagName("input");


		for (i = 0; i < myInput.length; i++)	{
			//alert(i + ": " + myInput[i].id + " " + myInput[i].type);
			switch (myInput[i].type)	{
			case "checkbox":	
				if (strPost != "")
					strPost += "&";
				if (myInput[i].checked == true)	{
					strPost += myInput[i].name + "=1";
				}
				else	{
					strPost += myInput[i].name + "=0";
				}
				break;
			
			case "radio":	

				var thisName = myInput[i].name;
				while(thisName == myInput[i].name)	{
					if(myInput[i].checked)	{
						if (strPost != "")
							 strPost += "&"
						strPost += myInput[i].name + "=" + myInput[i].value;
					}
					i++;
				}
				i--;
				break;
				
			case "button":							
				break;
			
			default:	
				if (strPost != "")
					 strPost += "&" 
				strPost += myInput[i].name + "=" + this.urlEncode(myInput[i].value);	//.replace(/&/, "%%26");
				break;
			}
		}

		myInput = element.getElementsByTagName("select");
		for (i = 0; i < myInput.length; i++)	{
			if (strPost != "")
				 strPost += "&"
			strPost += myInput[i].name + "=" + myInput[i].value;
		}

		myInput = element.getElementsByTagName("textarea");
		for (i = 0; i < myInput.length; i++)	{
			if (strPost != "")
				 strPost += "&"
			if(!tinyMCE)	{
				//alert(myInput[i].innerHTML);
				var strCRkorrekt = myInput[i].innerHTML;
				//alert(strCR + "\n\n" + strCR.replace(/\r\n/g, "<br />"));
				strCRkorrekt = strCRkorrekt.replace(/&lt;/g, "<");
				strCRkorrekt = strCRkorrekt.replace(/&gt;/g, ">");
				strCRkorrekt = strCRkorrekt.replace(/\r\n/g, "<br />");
			}
			else {
				var ed = tinyMCE.get(myInput[i].id);
				//alert(ed.getContent());
				//ed.setProgressState(1); // Show progress
				strCRkorrekt = ed.getContent();
				
			}
			strPost += myInput[i].id + "=" + this.urlEncode(strCRkorrekt);
			//alert(strPost);
		
		}
		
		if (this.debug)
			alert("Post to Server: " + strPost)
		
		//var strEnc = this.urlEncode(strPost)
		
		return strPost;
	};


	this.urlEncode = function (strPost)	{
		var strEnc = "";
		for (i = 0; i < strPost.length; i++)	{
			
			c = strPost.charCodeAt(i);
			if ((c < 48 || c > 122))	{ //&& c != 38
				if ( c != 10 && c != 13)	
					strEnc += "%" + c.toString(16);
			}
			else	{
				strEnc += strPost.charAt(i);
			}
		}
		return strEnc
	};


	this.query = function (sXPath, sRoot)	{

		this.oResult = this.loadXML(sRoot);
		
		aSelection = this.selectNodes(sXPath);
		
		var clone;
		
		for (i = 0; i < aSelection.length; i++)	{
//XXX take care of DOM_Version since importNode is only supported from XMLDOM5.0
    			//clone = this.oResult.importNode(aSelection[i], true);
    			clone = aSelection[i].cloneNode(true);
  			this.oResult.documentElement.appendChild(clone);
		}		
		
		if (aSelection.length > 0 && this.target)
			this.renderToDoc(this.target, false, this.oResult)

	}
	
	this.selectNodes = function(sXPath)	{
		//XXX take care of the Namespace!!
		if (rbmXML.buseActiveX)	{
			var aSelection = this.oXML.selectNodes(sXPath);	
			if (this.debug)
				alert("selectNodes: " + aSelection.length);
			
			return aSelection;
		}
		else	{
			if (typeof XPathEvaluator != "undefined") {            //Firefox
			
				var oNSResolver = this.oXML.createNSResolver(this.oXML.documentElement)
				var aItems = this.oXML.evaluate(sXPath, this.oXML, oNSResolver, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null)
				var aResult = [];
				for( var i = 0; i < aItems.snapshotLength; i++)
				{
					aResult[i] =  aItems.snapshotItem(i);
				}
				
				return aResult;

			}

		}
	}

	this.corrCRinTextAreas = function(oElement)	{

		var aTextAreas = $(oElement).getElementsByTagName("textarea");
		var i;
		
		//alert(oElement.innerHTML);
		for(i = 0; i<aTextAreas.length; i++)	{
			//alert(aTextAreas[i].innerHTML);
			aTextAreas[i].innerHTML = aTextAreas[i].innerHTML.replace(/&lt;br \/&gt;/g, "\r\n");
		}
		
	}
}

