
function ShowLoadMsg(s) {
	var w = 70;
	var o = document.createElement("DIV");
	o.id="_loadmsg";
	o.style.position="absolute";
	o.style.left=parseInt(document.body.clientWidth)-w;
	o.style.width=w;
	o.style.top=0;
	o.style.padding=3;
	o.style.backgroundColor="red";
	o.style.color="white";
	o.innerText = s ? s : 'Loading...';
	document.body.appendChild(o);
}

function HideLoadMsg() {
	setTimeout("Elem('_loadmsg').removeNode(true);",0);
}

//////////////////////////////////////////////////////////////////////////

var __COMM_OBJS	= [];

function Communicator(params) {
	if (typeof(params.url)=="undefined") throw "params";
	if (typeof(params.evalResponse)=="undefined") params.evalResponse=false;
	if (typeof(params.async)=="undefined") params.async=false;
	if (typeof(params.timeout)=="undefined") params.timeout=0;	// zero means no repeat and _autoshutdown_
	if (typeof(params.data)=="undefined") params.data="";
	if (typeof(params.method)=="undefined") params.method="GET";

	if (!params.dataCallback) params.dataCallback =	function() { alert("Data received, but no data callback specified.") }
	if (!params.errorCallback) params.errorCallback = function() { alert(lastErrorText) }

	var http = new ActiveXObject("Microsoft.XMLHTTP");
	var key = ArrayFindFree(__COMM_OBJS);
	__COMM_OBJS[key] = this;

	var loadingMsg, repeatTimeout;
	var lastErrorText	= "";

	var resetTimeout	= function() {
			if (params.timeout)
				repeatTimeout = window.setTimeout("__COMM_OBJS['"+key+"'].Send()",params.timeout);
			else
				__COMM_OBJS[key].Shutdown();
	}

	var checkState = function() {
		if (http.readyState==4) {
			if (loadingMsg) {
				HideLoadMsg();
				loadingMsg = false;
			}
			if (http.status==200) {
			//	alert(http.responseText);
				if (params.evalResponse) {
					try {
						eval(http.responseText);
						params.dataCallback();
					} catch(e) {
						lastErrorText = "Eval error: "+e.description;
						params.errorCallback();
					}
				} else {
					params.dataCallback(http.responseText);
				}
			} else {
				if (http.status>0) {
					lastErrorText = "HTTP code: "+http.status+"\n"+http.statusText;
					params.errorCallback();
				}
			}
			resetTimeout();
		}
	}

	this.Send = function() {
		try {
			this.Stop(true);
			if (window.event) {		// came from mouse click
				loadingMsg=true;
				ShowLoadMsg();
			}
			http.open(params.method, params.url, params.async);
			http.onreadystatechange = checkState;
			http.send(params.data);
		} catch(e) {
			lastErrorText = e.description;
			params.errorCallback()
			resetTimeout();
		}
	}

	this.SetParam = function(param, value) {
		this.Stop();
		params[param] = value;
	//	this.Send();
	}

	this.Stop = function(fromSend) {
		if (http.readystate>0)
			http.abort();
		clearTimeout(repeatTimeout);
		if (loadingMsg) {
			HideLoadMsg();
			loadingMsg = false;
		}
	}

	this.Shutdown = function() {
		this.Stop();
		delete __COMM_OBJS[key];
		http = null;
	}
}

function AsyncRequest(url, callback, s, err_callback) {
	var t = new Communicator( 
		{	url:url, async:true, timeout:0, dataCallback:callback, data:s, errorCallback:err_callback }
	);
	t.Send();
}
