function MyAjaxDoc(Local_Single_Use) {
	//this.requestIds = 0;
	this.doc = null;
	this.url = null;
	this.xmltype = null; //IE	
    this.parse2xml = false;
	this.parse2js = false;
	this.intv = null;
	this.inCB = false;
	this.loading = false;
	this.JSParser = new JSParser();
	this._LocalSingleUse = typeof Local_Single_Use == "undefined" ? true : Local_Single_Use;
	this.store = new Object();
	this.requestId = -1;
	
	this._varpos = null; this._varname = null; this._cbData = new Array(); this._cbKinds = new Object();
	
	this.MyAjax = function () {
		this.doc = null;
		
		try {
			this.doc = new XMLHttpRequest();			
		} catch (e) { }
		
		if (!this.doc) {				
			try {
				this.doc = new ActiveXObject('Msxml2.XMLHTTP');
			} catch (e) { }
		}
		
		if (!this.doc) {				
			try {
				this.doc = new ActiveXObject('Microsoft.XMLHTTP');
			} catch (e) { }
		}		
		
		if (!this.doc) {
			alert("Incompatible Browser. Please Consider IE/Opera/Mozilla");
			return false;
		}
		else {
		    $Lib.createGlobalVarName(this);
        }
		
	}
	this.useXML = function (pxml) {
		this.parse2xml = pxml;
	}
	this.useP2J = function (pjs) {
	    this.parse2js = pjs;
	}
	this.addDataHandler = function (callback, callbackobj /*String Value*/) {		
		return $Lib.createCallBack(this, 'data', callback, callbackobj);		
	}
	this.setErrorHandler = function (ecallback, ecallbackobj) {
	    return $Lib.createCallBack(this, 'error', ecallback, ecallbackobj);	
	}
	this._onReady = function () {
		if (this.inCB) return;
		this.inCB = true;
		try {
            if (this._doData()) {
                if (this._LocalSingleUse) this.Close();
            }
        }
        catch (e) {
             //
        }
		this.inCB = false;
	}
	this.errorFunc = function (msg) {
		msg = this.url + '\r\n' + msg;
		this.loading = false;
		
	    $Lib.callMultipleCallBack(this, 'error', this.doc, msg, this);
	    if (this._LocalSingleUse) this.Close();
	}
	this._doData = function () {
	    //alert(this.doc.readyState + " | " + this.doc.status + " | " + this.doc.statusText);
	    var o;
		if (this.doc.readyState == 4)  {
		   clearInterval(this.intv);
			this.intv = null;
			this.loading = false;
			if (this.doc.status == 200) {							
				if (this.parse2js) {					
                    o = this.parseP2J();
					if (o) {
						$Lib.callMultipleCallBack(this, 'data', this.doc, o, this);
						return true;
					}
					else this.errorFunc("Unknown Php2Jscript Error, Could not parse document: "/* + this.doc.responseText*/);
				}
				else if (this.parse2xml) {
					o = this.JSParser.parseOBJ(this.doc.responseText);
					if (o && o.parsed) {
						$Lib.callMultipleCallBack(this, 'data', this.doc, o, this);
						return true;
					}
					else this.errorFunc(this.JSParser.parseError);
				}
				else {
					$Lib.callMultipleCallBack(this, 'data', this.doc, null, this);
					return true;
				}
			}
         else this.errorFunc(this.doc.status + " : " + (this.doc.statusText || ""));
      }
	}
	this.loadSync = function (fname, meth, getdata, postdata) {
		var postlen, o, returnData = {ok: true, parsed: true, data: null, doc: null, error: null};
		
    	if (this.requestId == -1) this.requestId = MyAjaxDoc.prototype.nextRequestId();
    	
		this.abort();

      meth = meth ? meth.toLowerCase() : "get";
		getdata = getdata || null;
		postdata = postdata || null;
      
		if (getdata) {
		    if (fname.indexOf("?") >= 0) fname += "&" + getdata;
		    else fname += "?" + getdata;
	    }
	    
		fname = $Lib.wroot + fname;
	    
		if (meth == "get") postdata = null;
        
		this.url = fname;
		this.loading = true;

		try {
		   this.doc.open(meth, fname, false);
			this.doc.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
			if (meth == "post") {
				if (!postdata) postlen = 0;
				else {
					if (typeof postdata != 'string') postdata = '' + postdata + ''; //convert to a string
					postlen = postdata.length;
				}
				this.doc.setRequestHeader("Content-Length", postlen);
			}				
			this.doc.send(postdata);
         
         this.loading = false;
         
         returnData = {ok: false, parsed: false, data: null, doc: null, error: null};
         returnData.doc = this.doc;
         
         if (this.doc.status == 200) {
            returnData.ok = true;
            
            if (this.parse2js) {					
               o = this.parseP2J();
					if (o) {
                  returnData.parsed = true;
                  returnData.data = o;
               }
               else returnData.error = "Unknown Php2Jscript Error, Could not parse document: "/* + this.doc.responseText*/;
            }
            else if (this.parse2xml) {
					o = this.JSParser.parseOBJ(this.doc.responseText);
					if (o && o.parsed) {
						returnData.parsed = true;
                  returnData.data = o;
					}
					else returnData.error = this.JSParser.parseError;
				}
            else {
               //Nothing to do.
				}
         }
         else {
            returnData.ok = false;
            returnData.error = this.doc.status + " : " + (this.doc.statusText || "");
         }
		}
		catch (e) { }
      
      return returnData;
	}
	this.load = function (fname, meth, getdata, postdata) {
		var postlen;
		
    	if (this.requestId == -1) this.requestId = MyAjaxDoc.prototype.nextRequestId();
    	
		this.abort();

        meth = meth ? meth.toLowerCase() : "get";
		getdata = getdata || null;
		postdata = postdata || null;

		this.intv = setInterval(this._varname + "._onReady();", 100);

		if (getdata) {
		    if (fname.indexOf("?") >= 0) fname += "&" + getdata;
		    else fname += "?" + getdata;
	    }
	    
		fname = $Lib.wroot + fname;
	    
		if (meth == "get") postdata = null;
        
		this.url = fname;
		this.loading = true;

		try {
		    this.doc.open(meth, fname, true);
			this.doc.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
			if (meth == "post") {
				if (!postdata) postlen = 0;
				else {
					if (typeof postdata != 'string') postdata = '' + postdata + ''; //convert to a string
					postlen = postdata.length;
				}
				this.doc.setRequestHeader("Content-Length", postlen);
			}				
			this.doc.send(postdata);
		}
		catch (e) { }
	}
	this.abort = function () {
      clearInterval(this.intv);
      this.intv = null;
      try { this.doc.abort(); } catch (e) { }
      this.loading = false;
	}
	this._removeWhite = function (node) { //Edit the code.
		if (node.nodeType == 3 || node.nodeName == "#text") {
			var b = 0, strlen = node.nodeValue.length, tstr = "";;
			for (b = 0; b < strlen; b++) {
				if (b == 0) tstr += "\n";
				else tstr += " ";
			}						
			if (tstr == node.nodeValue) node.parentNode.removeChild(node);							
		}
		else if (node.nodeType == 1 || node.nodeType == 9) {
			var a = 0;
			for (a = 0; a < node.childNodes.length; a++) this._removeWhite(node.childNodes[a]);
		}
	}	
	this.Close = function () {
		try {
		    var i;
		    this.abort();
		    $Lib.deleteGlobalVarName(this);		
            $Lib.deleteCallBacks(this);
            
		    for (i in this) {
		        try {
		            delete this[i];
		        }
		        catch (e) {}
		    }
		}
		catch (e) { }
		this.Close = new Function("return;");
	}
	this.MyAjax();
};
MyAjaxDoc.prototype.requestIds = 0;
MyAjaxDoc.prototype.nextRequestId = function (){
    return ++MyAjaxDoc.prototype.requestIds;
}
MyAjaxDoc.prototype.parseP2J = function (str) {
    try {
        var keys = null, data = null;
        var o = function () {
            var args = o.arguments, i, nan = false;

            for (i = 0; i < args.length; i+=2) {
                if (nan = $Lib.isNaN(keys[args[i]])) break;
            }

            var obj = nan ? new Object() : new Array();

            for (i = 0; i < args.length; i+=2) obj[keys[args[i]]] = args[i + 1];
            return obj;
        }

         //eval will fill keys and data and evaluate.
        try { eval(str || this.doc.responseText); } catch (e) { }
        return data;
    }
    catch (e) { return false; }
}


function JSParser() {
	this.lastParse = null;
	this.parseError = "";
	this.version = 1.0;
	
	this.parseOBJ = function (str) {
		try {
            var x = new Object();
    		try { eval("x = " + str); } catch (e) { }
    		var obj = null;
    		if (typeof x.obj != "undefined") {
    			this.lastParse = true;
    			obj = this.parseOBJ1(x.obj, null); //JSXML Var
    			if (obj) {
    				obj.parsed = this.lastParse;
    				if (obj.childNodes.length == 1) obj.documentElement = obj.childNodes[0];
    			}
    			//alert(obj.documentElement.childNodes[1].childNodes[0].getAttribute("TITLE"));
    		}
    		return obj;
    	}
    	catch (e) { this.parseError = "Could not parse Document"; }
	};
	this.parseOBJ1 = function (y, parent) {
		var type, obj, cnt, a;
	
		if ( typeof y.vs != "undefined") type = "document";
		else if ( typeof y.el != "undefined") type = "element";
		else if ( typeof y.tx != "undefined") type = "text";
		else {
			this.lastParse = false;
			this.parseError = "Unknown Node Type"
			return null;
		} //alert( + y);
		
		obj = new nodeObj(); obj.SetNodeType(type);	obj.parentNode = parent;
		
		if (type == "element" || type == "document") {
			if (type == "document") {
				if (y.vs > this.version) {
					this.lastParse = false;
					this.parseError = "JSParser Version too Low for Document. Document: " +
					y.vs + " JSParser " + this.version;
					return null;
				}
				obj.version = y.vs;
				obj.parentNode = null;
			}
			else {
				obj.nodeName = y.el;
				if (typeof (y.at) != "undefined") {	
					cnt = y.at.length;
					for (a = 0; a < cnt; a++) {
						obj.attributes[a] = new nodeObj();
						obj.attributes[a].parentNode = obj;
						obj.attributes[a].nodeName = y.at[a].n;
						obj.attributes[a].nodeValue = y.at[a].v;
						obj.attributes[a].SetNodeType("attribute");
					}
				}
			}	
			if (typeof (y.cn) != "undefined") {	
				cnt = y.cn.length;
				for (a = 0; a < cnt; a++) {
					obj.childNodes[a] = this.parseOBJ1(y.cn[a], obj);
					if (!obj.childNodes[a]) return null;
				}
			}
		}
		else if (type == "text") {
			obj.nodeValue = y.tx;			
		}
		return obj;
	}		
};

function nodeObj() {
	this.nodeName = "";
	this.nodeValue = "";
	this.parentNode = null;
	this.nodeTypeString = "";
	this.version = "";
	this.attributes = new Array();
	this.childNodes = new Array();
	this._pos = 0;
	this.parsed = false;	
	
	this.SetNodeType = function (type) {
		var arr = {attribute: 2, document: 9, element: 1, text: 3};
		if (typeof(arr[type]) == "undefined") return false; //Unknown Node Type nodeObj::SetNodeType
		this.nodeType = arr[type];
		this.nodeTypeString = type;
		if (type == "text") this.nodeName = "#text";
		return true;
	}	
	this.hasAttribute = function (name) {
		var cnt, a;
		if (this.nodeTypeString == "element") {		 	
			cnt = this.attributes.length;
		 	for (a = 0; a < cnt; a++) {
			 	if (this.attributes[a].nodeName.toLowerCase() == name.toLowerCase()) {
				 	this._pos = a;
					return true;
			 	}
		 	}
			return false;
		}
		return null;
	}
	this.getAttribute = function (name) {
		if (this.nodeTypeString == "element") {
			if (this.hasAttribute(name)) return this.attributes[this._pos].nodeValue;
			else return null;
		}
		else return null;
	}
	this.XML = function (op, format, pad) {
		var arr, a, s, cnt, tmp, val;
		if (!op) arr = this.getAsArray();
		else arr = op;
		if (!format || !pad) pad = 0;
		//for (i in arr.ChildNodes[0].ChildNodes[1]) alert(i + " " + arr.ChildNodes[0].ChildNodes[1][i]);
		//alert(arr["Version"]);
		s = "";	
		val = arr["Value"];
		if (arr["Type"] == "text") s = String.repeat(" ", pad * 3) + val + (format ? "\r\n" : "");
		else if (arr["Type"] == "attribute") s = arr["Name"]+"=\"" + val + "\"";
		else {
			if (arr["Type"] == "document")
				s = "<?xml version=\"" + arr["Version"] + "\"?" + ">" + (format ? "\r\n" : "");
			else {				
				s = String.repeat(" ", pad * 3) + "<" + arr['Name'] + "";				
				if (typeof(arr["Attributes"]) != "undefined") {
					cnt = arr["Attributes"].length; tmp = new Array();					
					for (a = 0; a < cnt; a++)
						tmp[a] = this.XML(arr["Attributes"][a]);
					s += " " + tmp.join(" ");
				}
				if (typeof(arr["ChildNodes"])) s += ">" + (format ? "\r\n" : "");
				else s += "/>" + (format ? "\r\n" : "");
			}
			if (typeof(arr["ChildNodes"]) != "undefined") {
				cnt = arr["ChildNodes"].length; tmp = new Array();
				for (a = 0; a < cnt; a++)
					tmp[a] = this.XML(arr["ChildNodes"][a], format, pad + 1);
				s += tmp.join("");
				if (arr["Type"] != "document")
				s +=  String.repeat(" ", pad * 3) + "</" + arr['Name'] + ">" + (format ? "\r\n" : "");
			}
		}
		return s;
	}	
	this.getAsArray = function () {		
		var arr, cnt, a;
		arr = {Name: this.nodeName, Version: "", Type: this.nodeTypeString, Value: this.nodeValue
		, Attributes: new Array(), ChildNodes: new Array()};
		
		if (this.nodeTypeString == "text") {
			arr["Name"] = "#text";
			arr["Attributes"] = arr["ChildNodes"] = arr["Version"] = undefined;
		}
		else if (this.nodeTypeString == "attribute") {
			arr["Attributes"] = arr["ChildNodes"] = arr["Version"] = undefined;
		}
		else {
			arr["Value"] = undefined;
			if (this.nodeTypeString == "document") {
				arr["Name"] = arr["Attributes"] = undefined;
				arr["Version"] = this.version;
			}
			else {	
				arr["Version"] = undefined;			
				cnt = this.attributes.length;
				if (cnt > 0) {
					for (a = 0; a < cnt; a++)
						arr["Attributes"][a] = this.attributes[a].getAsArray(false);
				}
				else arr["Attributes"] = undefined;
			}
			cnt = this.childNodes.length;
			if (cnt > 0) {
				for (a = 0; a < cnt; a++)
					arr["ChildNodes"][a] = this.childNodes[a].getAsArray(false);
			}
			else arr["ChildNodes"] = undefined;
		}
		return arr;
	}	
};
