
/////////////////////////////////
//                             //
//  Ajax Communication Engine  //
//                             //
/////////////////////////////////

//singleton engine
//var ajaxReqeuestManager;

function AjaxRequestManager()
{
	this.is_ie = (navigator.userAgent.indexOf('MSIE') >= 0) ? 1 : 0;
	this.is_ie5 = (navigator.appVersion.indexOf('MSIE 5.5') != -1) ? 1 : 0;
	this.is_opera = ((navigator.userAgent.indexOf('Opera 6') != -1) || (navigator.userAgent.indexOf('Opera/6') != -1)) ? 1 : 0;
	this.is_netscape = (navigator.userAgent.indexOf('Netscape') >= 0) ? 1 : 0;

	this.use_native_xml_http_object = true;
	try
	{
		new XMLHttpRequest();
	}
	catch(e)
	{
		this.use_native_xml_http_object = false;
	}


	this.totalNrofRequests = 0;
	this.totalNrofResponses = 0;

	this.nrofRequests = 0;
	this.nrofConcurrentRequests = 0;
	//response and handler queues for coping with multiple concurrent requests
	this.callbacks = new Array();
	this.callbackInputObjects = new Array();
	this.ajaxRequests = new Array();

//	ajaxReqeuestManager = this;
}


/**
 *
 * @param requestURL http-request as URL
 * @param callback JavaScript function that will be called when response arrives
 *                 callback will be invoked with responseObject and possibly callbackInput
 * @param callbackInput object that will be fed back into callback function
 * @param postData HTML formdata that must be POSTed
 *
 */
AjaxRequestManager.prototype.doRequest = function(requestURL, callback, callbackInput, postData)
{
	try
	{
		document.body.style.cursor = 'wait';

		this.totalNrofRequests++;
		this.nrofConcurrentRequests++;
		var requestNr = this.nrofRequests++;

		if (typeof(callback) == 'undefined' || callback == null)
		{
			this.callbacks[requestNr] = ignoreResponse;
		}
		else
		{
			this.callbacks[requestNr] = callback;
		}

		this.callbackInputObjects[requestNr] = callbackInput;

		//hand each request its own private handler
		//construct request
		this.ajaxRequests[requestNr] = this.createAjaxRequest(new Function('dispatchResponse(' + requestNr + ');'));

		if (postData != null)
		{
			this.sendRequest(this.ajaxRequests[requestNr], requestURL, postData);
		}
		else
		{
			this.sendRequest(this.ajaxRequests[requestNr], requestURL);
		}
		return requestNr;
	}
	catch(e)
	{
		alert('unable to send AJAX request ' + requestURL + ' with message "' + e.message + '"');
	}
}



function dispatchResponse(requestNr)
{
	document.body.style.cursor = 'pointer';
	//	alert('handling result: ' + message);
	//serverResponse.status: 200, 500, 503, 404
	if (ajaxReqeuestManager.ajaxRequests[requestNr].readyState == 4 || ajaxReqeuestManager.ajaxRequests[requestNr].readyState == 'complete')
	{
		this.totalNrofResponses++;

		if(ajaxReqeuestManager.callbackInputObjects[requestNr] == null)
		{
			ajaxReqeuestManager.callbacks[requestNr](ajaxReqeuestManager.ajaxRequests[requestNr].responseText);
		}
		else
		{
			ajaxReqeuestManager.callbacks[requestNr](ajaxReqeuestManager.ajaxRequests[requestNr].responseText, ajaxReqeuestManager.callbackInputObjects[requestNr]);
		}

		ajaxReqeuestManager.ajaxRequests[requestNr] = null;
		ajaxReqeuestManager.callbacks[requestNr] = null;
		ajaxReqeuestManager.callbackInputObjects[requestNr] = null;

		ajaxReqeuestManager.nrofConcurrentRequests--;
		if (ajaxReqeuestManager.nrofConcurrentRequests == 0)
		{
			//clean up handler queue
			ajaxReqeuestManager.ajaxRequests = new Array();
			ajaxReqeuestManager.callbacks = new Array();
			ajaxReqeuestManager.callbackInputObjects = new Array();
			ajaxReqeuestManager.nrofRequests = 0;
		}
	}
}

//internal function
AjaxRequestManager.prototype.sendRequest = function(ajaxRequest, url)
{
	ajaxRequest.open('GET', url, true);
	ajaxRequest.send(null);
}

//internal function
AjaxRequestManager.prototype.sendRequest = function(ajaxRequest, url, postData)
{
	ajaxRequest.open('POST', url, true);
	ajaxRequest.setRequestHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");
	ajaxRequest.send(postData);
}

AjaxRequestManager.prototype.checkAjaxSupport = function()
{
	return (this.createAjaxRequest(ignoreResponse) != null);
}

AjaxRequestManager.prototype.createAjaxRequest = function(handler)
{
	var ajaxRequest = null;
	if (this.is_ie && !this.use_native_xml_http_object)
	{
		var strObjName = (this.is_ie5) ? 'Microsoft.XMLHTTP' : 'Msxml2.XMLHTTP';
		try
		{
			ajaxRequest = new ActiveXObject(strObjName);
			ajaxRequest.onreadystatechange = handler;
		}
		catch(e)
		{
			window.status = 'ERROR: Page cannot be updated. Verify that active scripting and activeX controls are enabled';
			return;
		}
	}
	else if (!this.use_native_xml_http_object)
	{
		window.status = 'ERROR: page cannot not be updated.';
		return;
	}
	else
	{
		ajaxRequest = new XMLHttpRequest();
		if (this.is_ie)
		{
			ajaxRequest.onreadystatechange = handler;
		}
		else
		{
			ajaxRequest.onload = handler;
			ajaxRequest.onerror = handler;
		}
	}
	return ajaxRequest;
}


function ignoreResponse()
{
}




















/**
 * Interpretes response as instructions that are either
 * evaluated in this function by 'eval()' or by a member 'evaluate()' of callbackInput
 */
AjaxRequestManager.prototype.evaluateResponse = function(contents, callbackInput)
{
	if(callbackInput != null && typeof(callbackInput.evaluate) == 'function')
	{
		callbackInput.evaluate(contents);
	}
	else
	{
		eval(contents);
	}
}


var ajaxReqeuestManager = new AjaxRequestManager();


