// ==== ajax ===================================================================
function wd_HttpReqDefProc() {void(0);}
function wd_HttpReq(bkwProcFoo, bAsinc) {
	/*
	INPUT:
		- bkwProcFoo - function - reference to the request processing function
		- bAsinc - boolean - request mode
			(false is required for serial requests to process all of them)
	PROPERTIES:
		- Req - object - XMLHttpRequest object
		- Processor - function - reference to the request processing function
		- MS - boolean - true for Microsoft IE client
		- async - boolean - request mode
	METHODS:
		- request (string request method, string request url, string username, string password, array request headers, string request body)
			makes request for url and passes rezult to the processing function
	USAGE:
		I. - in the global scope code:
			1. create function bkwFoo
			2. create wd_HttpReq instance:
				var theObj=new wd_HttpReq(bkwFoo)
			3. set necessary request properties and headers and make request:
				theObj.request(sMethod, sUrl, sUser, sPassword, arrHeaders, sReqBody)
		II. - in the bkwFoo:
			4. detect request state:
				theObj.Req.readyState, integer
				- 0 The object has been created, but not initialized (the open method has not been called). 
				- 1 The object has been created, but the send method has not been called. 
				- 2 The send method has been called, but the status and headers are not yet available. 
				- 3 Some data has been received. Calling the responseBody and responseText properties at this state to obtain partial results will return an error, because status and response headers are not fully available. 
				- 4 All the data has been received, and the complete data is available. 

			5. detect responce status code:
				theObj.Req.status, integer
			6. analize responce headers:
				theObj.Req.getAllResponseHeaders(), array
					Or
				theObj.Req.getResponseHeader(sHeaderName), string
			7. use responce data:
				theObj.Req.responseText, string
					Or
				theObj.Req.responseXML, object
		EXAMPLE:
		this code:

		function wd_HttpReqProcessor () {
			if (theWdHttpReq.Req.readyState === 4) {
				alert(theWdHttpReq.Req.status + "\n" + theWdHttpReq.Req.getResponseHeader('Content-Type') + "\n" + theWdHttpReq.Req.responseXML + "\n" + theWdHttpReq.Req.responseText);
			}
		}
		var theWdHttpReq=new wd_HttpReq(wd_HttpReqProcessor);
		var arrHeaders=new Array(); arrHeaders['someheader']="some value";
		theWdHttpReq.request('GET', "http://localhost/index.html", "", "", arrHeaders);

		will produce alert like this:
		|---------------------------|
		|	404						|
		|	text/html				|
		|							|
		|	<html>...</html>		|
		|---------------------------|
	*/
	// input validation:
	if (!bkwProcFoo || typeof(bkwProcFoo)!=="function") var bkwProcFoo=wd_HttpReqDefProc;
	if (typeof(bAsinc) === 'undefined' || !bAsinc) {
		var bAsync=false;
	} else {
		var bAsync=true;
	}
	// init properties:
	this.iLatestReqStart = 0;
	this.iLatestReqFin = 0;
	this.iLatestReqTime = 0;
	//
	this.latestUrl="";
	this.async=bAsync;
	this.vrmj=-1;
	this.Req=null;
	this.Processor=bkwProcFoo;
	this.MS=false;
	if (window.ActiveXObject) {
		this.MS=true;
	}
	// methods:
	this.request=function(sMethod, sUrl, sUser, sPassword, arrHeaders, sBody) {
		// input validation:
		if (!sMethod || typeof(sMethod)!=="string") sMethod='GET';
		if (!sUrl || typeof(sUrl)!=="string") sUrl='about:blank';
		if (!sUser || typeof(sUser)!=="string") sUser='';
		if (!sPassword || typeof(sPassword)!=="string") sPassword='';
		if (!arrHeaders || typeof(arrHeaders)!=="object") var arrHeaders=new Array();
		//
		this.latestUrl=sUrl;
		this.iLatestReqStart = new Date().valueOf();
		//
		this.Req=null;
		if (window.XMLHttpRequest) {
			this.Req = new XMLHttpRequest();
			//if (this.Req.overrideMimeType) this.Req.overrideMimeType('text/xml');
			this.vrmj=0.0;
		} else if (this.MS) {
			try {
				this.Req=new ActiveXObject('MSXML3.XMLHTTP');
				this.vrmj=3.0;
			} catch (theError10) {
				var iMbVer=9;
				for (iMbVer=9; iMbVer>=3; iMbVer--) {
					try {
						this.Req=new ActiveXObject('MSXML2.XMLHTTP.'+iMbVer+'.0');
						this.vrmj=2+(iMbVer/10);
					} catch (theError9) {
						void(0);
					}
					if (this.Req) break;
				}
				//
				if (!this.Req) {
					try {
						this.Req=new ActiveXObject('Msxml2.XMLHTTP');
						this.vrmj=2.0;
					} catch (theError2) {
						try {
							this.Req=new ActiveXObject('Microsoft.XMLHTTP');
							this.vrmj=1.0;
						} catch (theError) {
							void(0);
						}
					}
				}
			}
		}
		if (this.Req) {
			this.Req.onreadystatechange=this.Processor;
			if (!sUser) var sUser="";
			if (!sPassword) var sPassword="";
			var bSucc=this.Req.open(sMethod, sUrl, this.async, sUser, sPassword);
			if (!arrHeaders) var arrHeaders=new Array();
			var sHdrName="";
			for (sHdrName in arrHeaders) this.Req.setRequestHeader(sHdrName, arrHeaders[sHdrName]);
			if (this.MS) {
				if (sBody) {
					this.Req.send(sBody);
				} else {
					this.Req.send();
				}
			} else {
				if (sBody) {
					this.Req.send(sBody);
				} else {
					this.Req.send(null);
				}
			}
		}
	}
}
// =============================================================================