if (window.ActiveXObject && !window.XMLHttpRequest) {
    window.XMLHttpRequest = function() {
        var activeX = new Array("Msxml2.XMLHTTP.6.0", "Msxml2.XMLHTTP.5.0", "Msxml2.XMLHTTP.4.0", "Msxml2.XMLHTTP.3.0", "Msxml2.XMLHTTP", "Microsoft.XMLHTTP");
        for (i in activeX) {
            try {
                return new ActiveXObject(activeX[i]);
            }
            catch(ex) {
            }
        }
        return null;
    };
}

Ajax = {
	request: function(url, post, callback, tag, timeout, loopdelay) {
		if (!window.XMLHttpRequest) {
		    callback(null, tag, -1, 'Not supported by browser.', null);
		    return null;
		}
		var id = ++this._lastid;
		var request = {id: id, url: url, post: post, callback: callback, tag: tag, timeout: (timeout ? timeout : 30), loopdelay: loopdelay, xhr: null, refresh: false};
		this._requests.push(request);
		this._exec(request);
		return id;
	},
	
	_exec: function(request) {
        var id = request.id;
        request.xhr = new XMLHttpRequest();
        request.xhr.onreadystatechange = function() { Ajax._onreadystatechange(id); };
        request.xhr.open(request.post ? "POST" : "GET", request.url, true);
        request.xhr.setRequestHeader('User-Agent', 'Code That Grid');
        request.xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
        request.laststate = 0;
        request.timeoutid = setTimeout("Ajax._ontimeout(" + id + ")", request.timeout * 1000)
        request.xhr.send(request.post);
    },

	_findidindex: function(id) {
        for (var i = 0;  i < this._requests.length;  i++) {
            if (this._requests[i].id == id) {
                return i;
            }
        }
        return -1;
    },

	refresh: function(id, force) {
        var i = this._findidindex(id);
        if (i < 0) {
            return;
        }
        var request = this._requests[i];
        if (force || request.laststate < 0) {
            this._cleanup(request);
            this._exec(request);
        }
        else {
            request.refresh = true;
        }
    },

	_onreadystatechange: function(id) {
        var i = this._findidindex(id);
        if (i < 0) {
            return;
        }
        var request = this._requests[i];
        if (!request.xhr) {
            return;
        }
        var readyState = request.xhr.readyState;
        if (request.laststate < 0) {
            return;
        }
        request.laststate = request.xhr.readyState;
        if (request.xhr.readyState != 4) {
            return;
        }
        var status = request.xhr.status;
        var responseText = request.xhr.responseText;
        var responseXML = request.xhr.responseXML;
        this._cleanup(request);
        if (request.refresh) {
            request.refresh = false;
            Ajax.refresh(id, true);
        }
        else if (request.loopdelay > 0) {
            request.timeoutid = setTimeout("Ajax.refresh(" + request.id + ", false)", request.loopdelay * 1000);
        }
        else {
            this._requests.splice(i, 1);
        }
        request.callback(id, request.tag, status, responseText, responseXML);
    },

	remove: function(id) {
        var i = this._findidindex(id);
        if (i < 0) {
            return;
        }
        var request = this._requests[i];
        this._requests.splice(i, 1);
        this._cleanup(request, true);
    },

	_cleanup: function(request, abort) {
        var ls = request.laststate;
        request.laststate = -1;
        if (request.timeoutid) {
            clearTimeout(request.timeoutid);
            request.timeoutid = null;
        }
        if (ls >= 0) {
            delete request.xhr['onreadystatechange'];
            if (abort && request.xhr.abort) {
                request.xhr.abort();
            }
            delete request['xhr'];
        }
    },

	_ontimeout: function(id) {
        var i = this._findidindex(id);
        if (i < 0) {
            return;
        }
        var request = this._requests[i];
        if (request.laststate < 0) {
            return;
        }
        this._cleanup(request, true);
        if (request.refresh) {
            request.refresh = false;
            Ajax.refresh(id, true);
        }
        else if (request.loopdelay > 0) {
            request.timeoutid = setTimeout("Ajax.refresh(" + request.id + ", false)", request.loopdelay * 1000);
        }
        else {
            this._requests.splice(i, 1);
        }
        request.callback(id, request.tag, -2, 'Request timed out.', null);
    },


	// PRIVATE:
    
    _lastid: 0,
    _requests: new Array()
}
