function getElementsByClass(searchClass,node,tag) {
	var classElements = new Array();
	if ( node == null )
		node = document;
	if ( tag == null )
		tag = '*';
	var els = node.getElementsByTagName(tag);
	var elsLen = els.length;
	var pattern = new RegExp('(^|\\\\s)'+searchClass+'(\\\\s|$)');
	for (i = 0, j = 0; i < elsLen; i++) {
		if ( pattern.test(els[i].className) ) {
			classElements[j] = els[i];
			j++;
		}
	}
	return classElements;
}

Array.prototype.inArray = function (value) {
	var i;
	for (i=0; i < this.length; i++) {
		if (this[i] === value) {
			return true;
		}
	}
	return false;
};

function $() {
	var elements = new Array();
	for (var i = 0; i < arguments.length; i++) {
		var element = arguments[i];
		if (typeof element == 'string')
			element = document.getElementById(element);
		if (arguments.length == 1)
			return element;
		elements.push(element);
	}
	return elements;
}


function createXMLHttpRequest() {
	try { return new XMLHttpRequest(); } catch(e) {}
	try { return new ActiveXObject("Msxml2.XMLHTTP"); } catch (e) {}
	try { return new ActiveXObject("Microsoft.XMLHTTP"); } catch (e) {}
	return null;
}


function AjaxQueue() {
    this._xr = createXMLHttpRequest();
	this._priq = new Array();
	this._urlq = new Array();
	this._parmq = new Array();
	this._cbs = new Array();
	this._retries = 3;
}


AjaxQueue.prototype._xr;
AjaxQueue.prototype._priq;
AjaxQueue.prototype._urlq;
AjaxQueue.prototype._parmq;
AjaxQueue.prototype._timer;
AjaxQueue.prototype._cbs;
AjaxQueue.prototype._retries;


AjaxQueue.prototype.requestNext = function () {
	if (this._xr.readyState != 0 && this._xr.readyState != 4) {
	    return;
	}
	if (this._urlq.length < 1) {
	    return;
	}
	var pri = this._priq[0];
	var url = this._urlq[0];
	var params = this._parmq[0];
	this._retries = (pri*2)+1;
	var timout = 20000 * pri + 10000;
	this._xr.open("POST", url, true); 
	this._timer = setTimeout(function() {
		ajaxq._xr.abort();
		ajaxq.retry();
	}, timout);
	this._xr.onreadystatechange = function() {
		ajaxq.handler();
	}
	this._xr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded; charset=utf-8"); 
	this._xr.send(params); 
}


AjaxQueue.prototype.retry = function () {
	if (this._retries-- <= 0) {
		var pri = this._priq.shift();
		this._urlq.shift();
		this._parmq.shift();
		this._retries = 3;
		if (pri > 0) {
			alert("Server didn't respond to AJAX request.  Code "+this._xr.status);
		}
	}
	setTimeout('ajaxq.requestNext();', 3000);
}


AjaxQueue.prototype.handler = function () {
	if (this._xr.readyState != 4) {
		return;
	}
	clearTimeout(this._timer);
	if (this._xr.status != 200) { 
		this.retry();
		return;
	}
	var rpri = this._priq.shift();
	var rurl = this._urlq.shift();
	var rparm = this._parmq.shift();
	this._retries = 3;
	var xml = this._xr.responseXML;
	if (!xml) {
	    alert('AJAX response is badly formed XML: '+rurl+"?"+rparm+"\n"+this._xr.responseText.substr(0,250));
		this.requestNext();
	    return;
	}
	var found = false;
	for (var tag in this._cbs) {
	    var tagels = xml.getElementsByTagName(tag);
		if (tagels.length > 0) {
			found = true;
			for (var tel = 0; tel < tagels.length; tel++) {
				this._cbs[tag](tagels[tel]);
			}
		}
	}
	this.requestNext();
	if (!found) {
	    alert('No handler for AJAX return:\n'+this._xr.responseText.substr(0,250));
	}
}


AjaxQueue.prototype.addHandler = function (tag,cb) {
	this._cbs[tag] = cb;
}


AjaxQueue.prototype.addLowPriorityRequest = function (url,params) {
    this._priq.push(0);
    this._urlq.push(url);
    this._parmq.push(params);
	this.requestNext();
}


AjaxQueue.prototype.addRequest = function (url,params) {
    this._priq.push(1);
    this._urlq.push(url);
    this._parmq.push(params);
	this.requestNext();
}


var ajaxq = new AjaxQueue();

ajaxq.addHandler('error', function(xml) {
	var msg = xml.firstChild.nodeValue;
	alert('AJAX Error: '+msg);
});


/* vim: set ts=4 sw=4 ai nowrap noexpandtab: settings */

