var ajax=new Object();

ajax.READY_STATE_UNINITIALIZED  = 0;
ajax.READY_STATE_LOADING        = 1;
ajax.READY_STATE_LOADED         = 2;
ajax.READY_STATE_INTERACTIVE    = 3;
ajax.READY_STATE_COMPLETE       = 4;

// ########################################################################################
// url:         URL fŸr das AJAX-Servlet ggf. auch mit Parametern. Action-Code z.B.
// onload:      Callback-Methode dir gerufen wird, wenn der Request fertig ist
//              und die gelieferten Daten plaziert werden sollen.
// onerror:     Callback-Methode, die im Fehlerfall gerufen wird.
// method:      "GET" (default) oder "POST".
// params:      URL-Parameter. Kann man aber auch direkt an der URL dran hŠngen
// contentType: "application/x-www-form-urlencoded" (default bei "POST")
// timeout:     Wenn ein Req. nicht in timeout Sekunder fertig ist, wird der abgebrochen
// singleton:   Anzahl Millisekunden bis erneut ein Req. abgesetzt werden kann.
//intervall:    Wenn interwall > 0, wird der Req. wiederholt in dem interwall ausgefŸhrt
// ########################################################################################
ajax.ContentLoader = function(onload, onerror, onwait, method, contentType, timeout, singleton, intervall) {
    this.m_req = null;
    this.m_method = null;
    this.m_method = ((method) ? method : "GET");
    this.m_contentType = ((!contentType && method=="POST") ? "application/x-www-form-urlencoded" : contentType);
    this.m_onload = onload;
    this.m_onerror = ((onerror) ? onerror : this.defaultError);
    this.m_onwait  = onwait;
    this.m_timeout = ((timeout) ? timeout : 10000);
    this.m_RequestAbortTimerID = null;
    this.m_singleton = ((singleton) ? singleton : 0);
    this.m_RequestStop = false;
    this.m_intervall = ((intervall) ? intervall : 0);
    this.m_CatchErr = null;
}

ajax.ContentLoader.prototype.Load =
    function(url, params) {
        var tmpLoader = this;
        if (this.m_intervall > 0) {
            window.setInterval(function() {
                                    tmpLoader.LoadHelper(url, params, false);
                               }, tmpLoader.m_intervall);
        } else {
            tmpLoader.LoadHelper(url, params, false);
        }
        
    }

ajax.ContentLoader.prototype.LoadInterupt =
    function(url, params) {
        var tmpLoader = this;
        tmpLoader.LoadHelper(url, params, true);
    }

ajax.ContentLoader.prototype.LoadHelper =
    function(url, params, interupt) {
        //Wenn Timergesteuert eine Funktion gerufen wird, kennt die 
        //Funktion "this" nicht mer...
        var tmpLoader = this;

        //Wenn man die url nicht jedes mal Šndert kommt das ergebnis aus dem Cache!
        url = url + "&ts=" + new Date().getTime();

        if (this.m_onwait) {
            //Eine Funktion fŸr das Anzeigen der Sanduhr ist hinterlegt
            this.m_onwait.call(this);
        }

        //Wenn ein interwall eingestellt ist und eine Anfrage dazwischen kommt,
        //brechen wir ggf. ein laufender Request ab und starten den der gerade
        //abgesetzt worden ist.
        if (interupt) {
            //ggf. Timer fŸr die ZeitŸberschreitung zurŸcksetzen
            if (this.m_RequestAbortTimerID) {
                window.clearTimeout(this.m_RequestAbortTimerID); //Timeout fŸr das abbrechen von Req. lšschen
            }
            //ggf. laufender Request abbrechen.
            if (this.m_req) {
                if (this.m_req.readyState != ajax.READY_STATE_COMPLETE) {
                    this.m_req.abort();
                }
            }
            //Wenn ein singleton (schutz vor nervšse Finger) setzen wir den auch zurŸck,
            //damit die "zwichen-Abfrage" davon nicht ausgebremstz wird.
            tmpLoader.resetRequestStop.call(tmpLoader);
        }

        //XMLHttpRequest-Objekt erstellen
        //Hier wŸrde man gerne testen "if (!this.m_req)", aber der MS Browser 
        //verliert dann ab dem zweiten Aufruf (bei wederholten Aufrufen) die
        //verknŸpfung zur Callbackroutine, die den Responsetext liefert.
        if (window.XMLHttpRequest){
            this.m_req = new XMLHttpRequest();
        } else if (window.ActiveXObject){
            this.m_req = new ActiveXObject("Microsoft.XMLHTTP");
        }

        if (this.m_req) {
            try {
                if (!this.m_RequestStop) {
                    this.m_req.onreadystatechange =
                        function() {
                            tmpLoader.onReadyState.call(tmpLoader);
                        }
                    this.m_req.open(this.m_method, url, true); //true = Async aufruf!
                    if (this.m_contentType) {
                        this.m_req.setRequestHeader('Content-Type', this.m_contentType);
                    }
                    //FŸr das Abbrechen von hŠngende Requests
                    if (this.m_timeout > 0) {
                        this.m_RequestAbortTimerID = window.setTimeout(function() {
                                                                            tmpLoader.timerAbortRequest.call(tmpLoader);
                                                                        }, tmpLoader.m_timeout);
                    }
                    //Gegen nerwšse Finger...
                    if (this.m_singleton > 0) {
                        this.m_RequestStop = true;
                        window.setTimeout(function() {
                                            tmpLoader.resetRequestStop.call(tmpLoader);
                                            }, tmpLoader.m_singleton);
                    }
                    this.m_req.send(params);
                }
            } catch (err) {

                tmpLoader.m_CatchErr = err;
                tmpLoader.m_onerror.call(tmpLoader);
            }
        }
    }

ajax.ContentLoader.prototype.onReadyState =
    function() {
        if (this.m_req.readyState == ajax.READY_STATE_COMPLETE) {
            if (this.m_RequestAbortTimerID) {
                window.clearTimeout(this.m_RequestAbortTimerID); //Timeout fŸr das abbrechen von Req. lšschen
            }
            if (this.m_req.status == 200 || this.m_req.status == 0) {
                //Wir prŸfen, ob ein Callback fŸr die Ergebnisbehandlung Ÿbergeben worde ist.
                //Es muss ja nicht immer ein Ergebnis an den Client geliefert werden.
                //Mann kan ja z.B. auch nur ein DB-Eintrag lšschen!
                if (this.m_onload) {                    
                    this.m_onload.call(this);
                }
            } else {
                this.m_onerror.call(this);
            }
        }
    }

ajax.ContentLoader.prototype.timerAbortRequest =
    function() {
        if(this.m_req.readyState != ajax.READY_STATE_COMPLETE) {
            this.m_req.abort();
        }
    }

ajax.ContentLoader.prototype.resetRequestStop =
    function() {
        this.m_RequestStop = false;
    }

ajax.ContentLoader.prototype.defaultError =
    function() {
        alert("Error fetsching data!" +
            "\n\nreadyState:" + this.m_req.readyState +
            "\nstatus: " + this.m_req.status +
            "\nheaders: " + this.m_req.getAllResponseHeaders() +
            "Catch: " + this.m_CatchErr);
    }
