
var DisplayErrors = true;

function XMLHTTPObj()
{
	var CreateXMLHTTPObj;
	try
	{
		CreateXMLHTTPObj = new ActiveXObject("Microsoft.XMLHTTP");
	}
	catch (err)
	{
		try {
				CreateXMLHTTPObj = new XMLHttpRequest();
			}
			catch (err) {return false;}
	}
	return CreateXMLHTTPObj;
}



//************************
// the 'ApplyTrans function' receive an object with the transfering data
// and the data concern to the action on the returned information.

// example object:
//----------------

//	var AjaxData = new Object();
	
		// [*compulsory* - how the request be posted]
//	AjaxData.Method = "POST";
	
		// [*compulsory* - asynchronous or synchronous]
//	AjaxData.Sync = false;
	
		// [*compulsory* - xml = the return format will be xml - 
		// text = the return format will be text]
//	AjaxData.ReturnDataType = "xml";
	
		// [*compulsory* - the data to transfer to the server.]
//	AjaxData.DataToTransfer = "some data comes here";
	
		// [*compulsory* - the url of the data source]
//	AjaxData.URL = "http://...";
	
		// [*compulsory* - the ContentType for the request. example: 
//		" application/x-www-form-urlencoded" or "text/xml; charset=utf-8"]
//	AjaxData.ContentType = "text/xml; charset=utf-8";
	
		// [*optional* - if the data recived is in a xml format than this xPath 
		// will attempt to fined a distinct node]
//	AjaxData.root_element_by_xPath = "//root";
	
		// [*optional* - if the data recived is in a xml format than this attribute
		// will determine the type of element to return. tow types are optional:
		// 'element' and 'document' the 'document' is the default]
//	AjaxData.return_node_type = "document";

		// [*optional* - in case of useing SOAP for the data transaction]
//	AjaxData.SOAPAction = "http://socrateslogic.com/GetAllMasterAttr";
	
		// [*optional* - if use the synchronous method, this attribute will
		// determine the function for which the return data be send]
//	AjaxData.get_method_return_function = "function name parentheses";

		// [*optional* - if use the synchronous method, this attribute will
		// point to a function that be called on every readystatechange
		// and send to it the readyState number]
//	AjaxData.OnReadystatechange = "function name parentheses";

		// [*optional* - Overwrite the global var and display/not display error
		// message if ther is any
//	AjaxData.DisplayErr = true/false;

		// [*optional* - Additional data can be send Along with the returnd 'http data'
		// this is used with the properties get_method_return_function and 'Sync = true'
//	AjaxData.AdditionalData = number/text/object...;

		// [*optional* - The calling window to the function. This can be use when the 'ApplyTrans'
		// function not located at the same window as the window making the call. if the
		// function required to send back the Transaction result then the window object
		// may be required.
//	AjaxData.callingWindow = window;

//************************
function ApplyTrans(Data)
{
	var valrand = Math.random();
	var XmlHttp = new XMLHTTPObj();
	// שנוצר XmlHttp אשר מצביע על אובייקט ה Data מאפיין נוסף מתווסף אל אובייקט ה
	// ומאפשר פנייה אליו גם מחוץ לפונקציה. למשל לצורך השמדתו במקרה הצורך
	Data.PointerToObject = XmlHttp;

	var Querystring = (Data.Method === "GET" ? "&"+Data.DataToTransfer : "");
	
	try{XmlHttp.open(Data.Method, Data.URL+"?rand="+valrand+Querystring, Data.Sync);}
	catch(err){AjaxErrors({err:err, fArguments:arguments, TopNote:"Error found at the 'XmlHttp.open' method!", DisplayErr:Data.DisplayErr});}
	
	try{XmlHttp.setRequestHeader("Content-Type", Data.ContentType);}
	catch(err){AjaxErrors({err:err, fArguments:arguments, TopNote:"Error found at the 'XmlHttp.setRequestHeader' method!", DisplayErr:Data.DisplayErr});}
	
	if (Data.SOAPAction)
	{
		XmlHttp.setRequestHeader("SOAPAction", Data.SOAPAction);
	}
	
	try{XmlHttp.send(Data.DataToTransfer);}
	catch(err){AjaxErrors({err:err, fArguments:arguments, TopNote:"Error found at the 'XmlHttp.send' method!",DisplayErr:Data.DisplayErr});}
	
	if (Data.Sync)
	{
		XmlHttp.onreadystatechange = function(){XMLHTTP_ReturnedData(XmlHttp, Data);};
	}
	else
	{
		if (XmlHttp.status == 0){return;}
		if (XmlHttp.status != 200){AjaxErrors({HttpErr:XmlHttp.status, XmlHttp:XmlHttp, Data:Data, TopNote:"Could not get the requested data (status: "+XmlHttp.status+")!",DisplayErr:Data.DisplayErr}); return false;}
		
		if (Data.ReturnDataType === "xml" || Data.ReturnDataType === "xsl")
		{
			var XmlDom = CreateXmlDom(XmlHttp.responseText, Data);
			return XmlDom;
		}
		else if (Data.ReturnDataType === "text")
		{
			return XmlHttp.responseText;
		}
	}
	function XMLHTTP_ReturnedData(XmlHttp, Data)
	{
		var callingWindow = Data.callingWindow;
		if (! callingWindow){callingWindow = window;}
		
		var OnReadystatechange = Data.OnReadystatechange;
		if (OnReadystatechange && ValidFunctionToCall(callingWindow, "OnReadystatechange", OnReadystatechange))
		{eval("callingWindow."+OnReadystatechange+"(XmlHttp)");}
	
		try
		{
			if(XmlHttp.readyState == 4)
			{
				if (XmlHttp.status == 0){return;}
				if (XmlHttp.status != 200){AjaxErrors({HttpErr:XmlHttp.status, XmlHttp:XmlHttp, Data:Data, TopNote:"Could not get the requested data (status: "+XmlHttp.status+")!",DisplayErr:Data.DisplayErr}); return false;}
				
				var get_method_return_function = Data.get_method_return_function;
				if ((! get_method_return_function) || (get_method_return_function === "")){return false;}
				//alert(ValidFunctionToCall(callingWindow, "get_method_return_function", get_method_return_function))
				if (! ValidFunctionToCall(callingWindow, "get_method_return_function", get_method_return_function)){return false;}
				
				if (Data.ReturnDataType === "xml" || Data.ReturnDataType === "xsl")
				{
					var XmlDom = CreateXmlDom(XmlHttp.responseText, Data);
					//alert(callingWindow)
					//alert(Data.get_method_return_function+"()")
					eval("callingWindow."+Data.get_method_return_function+"(XmlDom, Data.AdditionalData)");
					
					//var qq = callingWindow[Data.get_method_return_function];
					//alert(qq);
					//eval("qq["+Data.get_method_return_function(XmlDom, Data.AdditionalData)]");
					//callingWindow[eval(Data.get_method_return_function+"()")];
					//callingWindow[eval(Data.get_method_return_function+"(XmlDom, Data.AdditionalData)")];
				}
				else if (Data.ReturnDataType === "text")
				{
					eval("callingWindow."+Data.get_method_return_function+"(XmlHttp.responseText, Data.AdditionalData)");
				}
			}
		}
		catch(e){}
	}
}


function ValidFunctionToCall(callingWindow, Method, FunctionName)
{
	var Reg1 = /[^a-z0-9_.]/gi;
	var NotValidName = Reg1.test(FunctionName);

	if (NotValidName)
	{
		alert("The functions name '"+FunctionName+"'"
		+" as described by the '"+Method+"' attribute"
		+" seems unvalid!\n"
		+"Please try another name.\n"
		+"Also remember that the name should be without parentheses.");
		return false;
	}

	//if (callingWindow && (! callingWindow[FunctionName]))
	if (callingWindow && (! eval("callingWindow."+FunctionName)))
	{
		//alert("Could not found the function '"+FunctionName+"'!\n"
		//+"This function mentioned in the '"+Method+"' attribute.");
		return false;
	}
	
	return true;
}


function AjaxErrors(ErrObject, Data)
{
	var DisplayErrors = window.DisplayErrors;
	if (ErrObject.DisplayErr == false){DisplayErrors = false;}
	else if (ErrObject.DisplayErr == true){DisplayErrors = true;}
	
	var ErrNote = "";
	var ExtendedDataToDisplay = "";
	if(ErrObject.TopNote)
	{
		ErrNote += ErrObject.TopNote+"\n\n";
		ErrNote += "\n**\n";
		ExtendedDataToDisplay += "<div style='font-size:18px; font-style: italic'>"+ErrObject.TopNote+"<br /><br /></div>";
	}

	if (ErrObject.err)
	{
		var ScriptErr = OnJSError(ErrObject.err, ErrObject.fArguments);

		ErrNote += ScriptErr;
		ExtendedDataToDisplay += "<div>"+ScriptErr.replace(/\n/g, "<br />")+"</div>";
		ErrNote += "\n**\n";
		ExtendedDataToDisplay += "<br /><br />";
	}
	
	if (ErrObject.HttpErr)
	{
		ErrNote += "http error: "+ErrObject.HttpErr;
		ExtendedDataToDisplay += "<div>http error: <strong>"+ErrObject.HttpErr+"</strong><br /><br /></div>";
		var Definition;
		
		if ((DisplayErrors) && (typeof(DomainURL) != "undefined"))
		{
			var AjaxData = new Object();
			AjaxData.Method = "GET";
			AjaxData.Sync = false;
			AjaxData.ReturnDataType = "xml";
			AjaxData.URL = DomainURL+"Status_Code_Definitions.xml";
			AjaxData.ContentType = "application/x-www-form-urlencoded";
			AjaxData.DisplayErr = false;
			var Status_Code_Definitions = ApplyTrans(AjaxData, true);
			
			Definition = Status_Code_Definitions.selectSingleNode("//div[@id='Status_"+ErrObject.HttpErr+"']");
		}
		ErrNote += "\n**\n";
		//ExtendedDataToDisplay += "<div><br /><br /></div>";
	}
	
	if (ErrObject.Data)
	{
		ErrNote += "Data passed to request:\n-----------------------------\n";
		ExtendedDataToDisplay += "<div>Data passed to request:<br />-----------------------------<br /></div>";
		var XmlSentToServer = "";
		for (var i in ErrObject.Data)
		{
			if (i == "DataToTransfer" && ErrObject.Data[i])
			{
				XmlSentToServer = CreateXmlDom(ErrObject.Data[i]);
				if (XmlSentToServer && ValidateXml(XmlSentToServer))
				{
					ErrNote += "   * "+i+": [See extended details]\n";
					XmlSentToServer = PrettyXmlPrint(XmlSentToServer);
					XmlSentToServer = XmlSentToServer.replace(/</g, "&lt;");
					XmlSentToServer = XmlSentToServer.replace(/\n/g, "<br />");
					XmlSentToServer = XmlSentToServer.replace(/	/g, "&nbsp;&nbsp;&nbsp;");
				}
				else if (ErrObject.Data[i].length > 100)
				{
					ErrNote += "   * "+i+": [See extended details]\n";
					XmlSentToServer = null;
				}
				else
				{
					XmlSentToServer = null;
					ErrNote += "   * "+i+": "+ErrObject.Data[i]+"\n";
					ExtendedDataToDisplay += "<div>&nbsp;&nbsp;&nbsp;* "+i+": <xmp>"+ErrObject.Data[i]+"</xmp><br /></div>";
				}
			}
			else
			{
				if (i == "PointerToObject"){continue;}
				ErrNote += "   * "+i+": "+ErrObject.Data[i]+"\n";
				ExtendedDataToDisplay += "<div>&nbsp;&nbsp;&nbsp;* "+i+": "+ErrObject.Data[i]+"<br /></div>";
			}
		}
		
		ErrNote += "**\n";
		ExtendedDataToDisplay += "<div>**<br /></div>";
	}
	
	if (DisplayErrors)
	{
		if (Definition)
		{
			var Confirm = confirm(ErrNote + "\nTo display a definition data click the OK button and hold the Ctrl key pressed");
			if (Confirm)
			{
				ExtendedDataToDisplay += "<div>"
				+"<span onclick='document.getElementById(\"StatusDef\").style.display=\"block\"' style='color: blue; cursor: pointer;'>Display status code definition</span>"
				+"<div id='StatusDef' style='color: red; display: none;'>"+DisplayXmlString(Definition)+"</div></div>";
			
				if (XmlSentToServer)
				{
					ExtendedDataToDisplay += "<div>"
					+"<span onclick='document.getElementById(\"XmlSentToServerData\").style.display=\"block\"' style='color: blue; cursor: pointer;'>Xml sent to server</span>"
					+"<div id='XmlSentToServerData' style='color: red; display: none;'>"+XmlSentToServer+"</div><br /></div>";
				}
				
				ExtendedDataToDisplay += "<div>"
				+"<span onclick='document.getElementById(\"HttpResponseDiv\").style.display=\"block\"' style='color: blue; cursor: pointer;'>Display http response</span>"
				+"<div id='HttpResponseDiv' style='color: red; display: none;'><iframe style='width: 100%;' name='frame1'></iframe></div>";
				
				var HttpErrWindow = window.open("about:blank","","width=600px,height=400px,resizable=1,scrollbars=1;");
				if (! HttpErrWindow){alert("Could not open Definition window!\n"
				+"Please try again while holding the Ctrl key pressed.");}
				else
				{
					HttpErrWindow.document.write(""
					+"<html><head><title>Status Code Definitions</title></head><body style='font:15px sans-serif'><div>"
					+"<div>"+ExtendedDataToDisplay+"</div>"
					+"</div></body></html>");
					HttpErrWindow.frames[0].document.write(ErrObject.XmlHttp.responseText);
				}
			}
		}
		else
		{
			alert(ErrNote);
		}
	}
}

// הפונקציה מחזירה הודעת שגיאה ואת שם הפונקציה
function OnJSError(err, fArguments)
{
	var ScriptErr = "";
	// שתוצג URL אשר מכיל כתובת Error בדיקה האם הוגדר מאפיין לאובייקט ה
	// אם כן אז המאפיין הזה יוצג
	if (err.Location)
	{
		ScriptErr += "URL: "+err.Location()+"\n";
	}
	// אם לא הוגדר מאפיין אחר אז תוצג כתובת הדף הנוכחית
	else
	{
		ScriptErr += "URL: "+window.location.href+"\n";
	}
	
	if (ScriptErr != ""){ScriptErr += "\n";}
	if (fArguments && fArguments.callee)
	{
		var Callee = ""+fArguments.callee;
		//var Reg = /function (\w+\w)[(]/;
		var Reg = /function (\w+\w)(\(.*?\))/;
		var CalleeRegExec = Reg.exec(Callee);
		if (CalleeRegExec)
		{
			var FuncName = CalleeRegExec[1]+CalleeRegExec[2];
			//if (fArguments.length)
			//{FuncName += "(...)";}
			//alert("function name: "+CalleeRegExec[1]+"\n\nError: \n"+ScriptErr);
			ScriptErr += "Error at function: '"+FuncName+"'\n\n";
		}
	}
	if (err && typeof(err) == "object")
	{
		if (navigator.appName != "Microsoft Internet Explorer")
		{
			ScriptErr += err+"\n\n";
		}
		else
		{
			ScriptErr += "Error name: "+err.name+"\n"
			+"Error Description: "+err.description+"\n"
			+"Error message: "+err.message+"\n"
			+"Error number: "+err.number;
			
		}
	}
	else if(err)
	{
		ScriptErr = err;
	}
	return ScriptErr;
}

function CreateXmlDom(XmlString, Data)
{
	var XmlDom;
	var BaseString = XmlString;
	if ((! BaseString) || (BaseString == ""))
	{
		BaseString = '<?xml version="1.0" encoding="utf-8"?>';
	}
	
	if ((document.implementation) && (document.implementation.createDocument))
	{
		try
		{
			XmlDom = new DOMParser();
			XmlDom = XmlDom.parseFromString(BaseString, 'application/xml');
		}
		catch(err){return false;}
	}
	else if (window.ActiveXObject)
	{
		if (! Data || Data.ReturnDataType === "xml") {
			XmlDom = new ActiveXObject("Microsoft.XMLDOM");
			XmlDom.setProperty("SelectionLanguage", "XPath");
		} else if (Data.ReturnDataType === "xsl") {
			XmlDom = new ActiveXObject("MSXML2.FreeThreadedDOMDocument");
		}	
		//
		XmlDom.async = false;
		XmlDom.loadXML(BaseString);
		
	}
	if (Data)
	{
		if (Data.root_element_by_xPath)
		{
			var RootElement = XmlDom.selectSingleNode(Data.root_element_by_xPath);
			if (! RootElement)
			{
				//alert("Could not found a node by using the xPath:\n"+Data.root_element_by_xPath);
				return null;
			}
			
			if (Data.return_node_type === "element")
			{XmlDom = RootElement;}
			else 
			{
			/*
				if (XmlDom.loadXML)
				{
					XmlDom.loadXML(DisplayXmlString(RootElement));
				}
				else
				{
					XmlDom = new DOMParser();
					XmlDom = XmlDom.parseFromString(DisplayXmlString(RootElement), 'application/xml');
				}
				*/
				return CreateXmlDom(DisplayXmlString(RootElement));
			}
			//else {XmlDom.loadXML(RootElement.xml);}
		}
	}
	return XmlDom;
}

/*
function Check_root_element_by_xPath(Data)
{
	if (! Data || ! Data.root_element_by_xPath){return false;}
	
}
*/

function ValidateXml(XmlObj)
{
	if (typeof(XmlObj.parseError) != "undefined")
	{
		if (XmlObj.parseError != 0){return false;}
		return XmlObj.parseError; 
	}
	else
	{
		if(XmlObj.documentElement.tagName === "parsererror"){return false;}
	}
	return true;
}


function DisplayXmlString(XmlObj)
{
	var XmlCode = XmlObj.xml;
	if (! XmlCode)
	{
		XmlCode = new XMLSerializer().serializeToString(XmlObj);
	}
	
	return XmlCode;
}


function PrettyXmlPrint(XmlDom)
{
	if (XmlDom.documentElement){XmlDom = XmlDom.documentElement;}
	var ww = DisplayXmlString(XmlDom).replace(/	/g, "");
	ww = ww.replace(/\r/g, "");
	ww = ww.replace(/\n/g, "");

	var AllDomColl = XmlDom.getElementsByTagName("*");

	cc = ww.split("<");
	
	var XmlStr = "";
	var ElementsCounter = 0;
	var TagText;
	var Indent = "";
	
	for (var i = 1;i < cc.length;i ++)
	{	
		TagText = "<"+cc[i];
		if (TagText.indexOf("</") == -1)
		{
			Indent = ReturnTagIndent(AllDomColl[ElementsCounter]);
			if (AllDomColl[ElementsCounter] && TagText.indexOf(AllDomColl[ElementsCounter].tagName) == -1){XmlStr += TagText; continue;}
			ElementsCounter ++;
			
			XmlStr += "\n"+Indent + TagText;
		}
		else
		{
			XmlStr += TagText;
		}
	}
 
	function ReturnTagIndent(Element)
	{
		var XmlStr = "";
		if (! Element){return XmlStr;}

		var DomElement = Element;
		while (DomElement.nodeName != "#document")
		{
			XmlStr += "	";
			DomElement = DomElement.parentNode;
		}
		return XmlStr;
	}

	return XmlStr;
}



