/**
 * JavaScript class for handling AJAX requests
 *
 * @author Philippe Manner
 * @copyright webmaster[AT]manner.ch
 * @since 10.01.2007
 * @version 1.0
 */
function AjaxRequest()
{
    var req = new Object();

    req.timeout           = null;
    req.generateUniqueUrl = true;
    req.url               = window.location.href;
    req.method            = "GET";
    req.async             = true;
    req.username          = null;
    req.password          = null;
    req.parameters        = new Object();
    req.requestIndex      = AjaxRequest.numAjaxRequests++;
    req.responseReceived  = false;
    req.groupName         = null;
    req.queryString       = "";
    req.responseText      = null;
    req.responseXML       = null;
    req.status            = null;
    req.statusText        = null;
    req.aborted           = false;
    req.xmlHttpRequest    = null;
    req.onTimeout         = null;
    req.onLoading         = null;
    req.onLoaded          = null;
    req.onInteractive     = null;
    req.onComplete        = null;
    req.onSuccess         = null;
    req.onError           = null;
    req.onGroupBegin      = null;
    req.onGroupEnd        = null;

    req.xmlHttpRequest = AjaxRequest.getXmlHttpRequest();

    if(req.xmlHttpRequest == null)
    {
        return null;
    }

    /*****************************************************************************************/
    req.xmlHttpRequest.onreadystatechange = function()
    {
        if(req == null || req.xmlHttpRequest == null)
        {
            return;
        }
        if(req.xmlHttpRequest.readyState == 1)
        {
            req.onLoadingInternal(req);
        }
        if(req.xmlHttpRequest.readyState == 2)
        {
            req.onLoadedInternal(req);
        }
        if(req.xmlHttpRequest.readyState == 3)
        {
            req.onInteractiveInternal(req);
        }
        if(req.xmlHttpRequest.readyState == 4)
        {
            req.onCompleteInternal(req);
        }
    };

    req.onLoadingInternalHandled     = false;
    req.onLoadedInternalHandled      = false;
    req.onInteractiveInternalHandled = false;
    req.onCompleteInternalHandled    = false;

    /*****************************************************************************************/
    req.onLoadingInternal = function()
    {
        if(req.onLoadingInternalHandled)
        {
            return;
        }
        AjaxRequest.numActiveAjaxRequests++;
        
        if(AjaxRequest.numActiveAjaxRequests == 1 && typeof(window['AjaxRequestBegin']) == "function")
        {
            AjaxRequestBegin();
        }
        if(req.groupName != null)
        {
            if(typeof(AjaxRequest.numActiveAjaxGroupRequests[req.groupName]) == "undefined")
            {
                AjaxRequest.numActiveAjaxGroupRequests[req.groupName] = 0;
            }
            AjaxRequest.numActiveAjaxGroupRequests[req.groupName]++;
            
            if(AjaxRequest.numActiveAjaxGroupRequests[req.groupName] == 1 && typeof(req.onGroupBegin) == "function")
            {
                req.onGroupBegin(req.groupName);
            }
        }
        if(typeof(req.onLoading) == "function")
        {
            req.onLoading(req);
        }
        req.onLoadingInternalHandled=true;
    };

    /*****************************************************************************************/
    req.onLoadedInternal = function()
    {
        if(req.onLoadedInternalHandled)
        {
            return;
        }
        if(typeof(req.onLoaded) == "function")
        {
            req.onLoaded(req);
        }
        req.onLoadedInternalHandled=true;
    };

    /*****************************************************************************************/
    req.onInteractiveInternal = function()
    {
        if(req.onInteractiveInternalHandled)
        {
            return;
        }
        if(typeof(req.onInteractive) == "function")
        {
            req.onInteractive(req);
        }
        req.onInteractiveInternalHandled=true;
    };

    /*****************************************************************************************/
    req.onCompleteInternal = function()
    {
        if(req.onCompleteInternalHandled || req.aborted)
        {
            return;
        }
        req.onCompleteInternalHandled = true;
        AjaxRequest.numActiveAjaxRequests--;

        if(AjaxRequest.numActiveAjaxRequests == 0 && typeof(window['AjaxRequestEnd']) == "function")
        {
            AjaxRequestEnd(req.groupName);
        }
        if(req.groupName != null)
        {
            AjaxRequest.numActiveAjaxGroupRequests[req.groupName]--;

            if(AjaxRequest.numActiveAjaxGroupRequests[req.groupName] == 0 && typeof(req.onGroupEnd) == "function")
            {
                req.onGroupEnd(req.groupName);
            }
        }
        req.responseReceived = true;
        req.status           = req.xmlHttpRequest.status;
        req.statusText       = req.xmlHttpRequest.statusText;
        req.responseText     = req.xmlHttpRequest.responseText;
        req.responseXML      = req.xmlHttpRequest.responseXML;

        if(typeof(req.onComplete) == "function")
        {
            req.onComplete(req);
        }
        if(req.xmlHttpRequest.status == 200 && typeof(req.onSuccess) == "function")
        {
            req.onSuccess(req);
        }
        else if(typeof(req.onError) == "function")
        {
            req.onError(req);
        }
        delete req.xmlHttpRequest['onreadystatechange'];
        req.xmlHttpRequest = null;
    };

    /*****************************************************************************************/
    req.onTimeoutInternal = function()
    {
        if(req != null && req.xmlHttpRequest != null && !req.onCompleteInternalHandled)
        {
            req.aborted =true;
            req.xmlHttpRequest.abort();
            AjaxRequest.numActiveAjaxRequests--;

            if(AjaxRequest.numActiveAjaxRequests == 0 && typeof(window['AjaxRequestEnd']) == "function")
            {
                AjaxRequestEnd(req.groupName);
            }
            if(req.groupName != null)
            {
                AjaxRequest.numActiveAjaxGroupRequests[req.groupName]--;

                if(AjaxRequest.numActiveAjaxGroupRequests[req.groupName] == 0 && typeof(req.onGroupEnd) == "function")
                {
                    req.onGroupEnd(req.groupName);
                }
            }
            if(typeof(req.onTimeout) == "function")
            {
                req.onTimeout(req);
            }
            delete req.xmlHttpRequest['onreadystatechange'];
            req.xmlHttpRequest =null;
        }
    };

    /*****************************************************************************************/
    req.process = function()
    {
        if(req.xmlHttpRequest != null)
        {
            if(req.generateUniqueUrl && req.method == "GET")
            {
                req.parameters["AjaxRequestUniqueId"]  =new Date().getTime() + "" + req.requestIndex;
            }
            var content =null;

            for(var i in req.parameters)
            {
                if(req.queryString.length > 0)
                {
                    req.queryString += "&";
                }
                req.queryString += encodeURIComponent(i) + "=" + encodeURIComponent(req.parameters[i]);
            }
            if(req.method == "GET")
            {
                if(req.queryString.length > 0)
                {
                    req.url += ((req.url.indexOf("?") > -1) ? "&" : "?") + req.queryString;
                }
            }
            req.xmlHttpRequest.open(req.method, req.url, req.async, req.username, req.password);

            if(req.method == "POST")
            {
                if(typeof(req.xmlHttpRequest.setRequestHeader) != "undefined")
                {
                    req.xmlHttpRequest.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
                }
                content = req.queryString;
            }
            if(req.timeout > 0)
            {
                setTimeout(req.onTimeoutInternal, req.timeout);
            }
            req.xmlHttpRequest.send(content);
        }
    };

    /*****************************************************************************************/
    req.handleArguments = function(args)
    {
        for(var i in args)
        {
            if(typeof(req[i]) == "undefined")
            {
                req.parameters[i] = args[i];
            }
            else
            {
                req[i] =args[i];
            }
        }
    };

    /*****************************************************************************************/
    req.getAllResponseHeaders = function()
    {
        if(req.xmlHttpRequest != null)
        {
            if(req.responseReceived)
            {
                return req.xmlHttpRequest.getAllResponseHeaders();
            }
            alert("Cannot getAllResponseHeaders because a response has not yet been received");
        }
    };

    /*****************************************************************************************/
    req.getResponseHeader = function(headerName)
    {
        if(req.xmlHttpRequest != null)
        {
            if(req.responseReceived)
            {
                return req.xmlHttpRequest.getResponseHeader(headerName);
            }
            alert("Cannot getResponseHeader because a response has not yet been received");
        }
    };

    return req;
}

/*********************************************************************************************/
AjaxRequest.getXmlHttpRequest = function()
{
    if(window.XMLHttpRequest)
    {
        return new XMLHttpRequest();
    }
    else if(window.ActiveXObject)
    {
        try
        {
            return new ActiveXObject("Msxml2.XMLHTTP");
        }
        catch(e)
        {
            try
            {
                return new ActiveXObject("Microsoft.XMLHTTP");
            }
            catch(E)
            {
                return null;
            }
        }
    }
    else
    {
        return null;
    }
};

/*********************************************************************************************/
AjaxRequest.isActive = function()
{
    return(AjaxRequest.numActiveAjaxRequests > 0);
};

/*********************************************************************************************/
AjaxRequest.get = function(args)
{
    AjaxRequest.doRequest("GET",args);
};

/*********************************************************************************************/
AjaxRequest.post = function(args)
{
    AjaxRequest.doRequest("POST",args);
};

/*********************************************************************************************/
AjaxRequest.doRequest = function(method,args)
{
    if(typeof(args) != "undefined" && args != null)
    {
        var myRequest = new AjaxRequest();

        myRequest.method = method;
        myRequest.handleArguments(args);
        myRequest.process();
    }
};

/*********************************************************************************************/
AjaxRequest.submit = function(theform, args)
{
    var myRequest = new AjaxRequest();

    if(myRequest == null)
    {
        return false;
    }
    var serializedForm = AjaxRequest.serializeForm(theform);

    myRequest.method      = theform.method.toUpperCase();
    myRequest.url         = theform.action;
    myRequest.handleArguments(args);
    myRequest.queryString = serializedForm;
    myRequest.process();
    return true;
};

/*********************************************************************************************/
AjaxRequest.serializeForm = function(theform)
{
    var els         = theform.elements;
    var len         = els.length;
    var queryString = "";

    this.addField = function(name, value)
                    {
                        if(queryString.length > 0)
                        {
                            queryString += "&";
                        }
                        queryString += encodeURIComponent(name) + "=" + encodeURIComponent(value);
                    };

    for(var i = 0; i < len; i++)
    {
        var el = els[i];

        if(!el.disabled)
        {
            switch(el.type)
            {
            case 'text':
            case 'password':
            case 'hidden':
            case 'textarea':
                this.addField(el.name, el.value);
                break;

            case 'select-one':
                if(el.selectedIndex >= 0)
                {
                    this.addField(el.name, el.options[el.selectedIndex].value);
                }
                break;

            case 'select-multiple':
                for(var j = 0;j < el.options.length; j++)
                {
                    if(el.options[j].selected)
                    {
                        this.addField(el.name, el.options[j].value);
                    }
                }
                break;

            case 'checkbox': case 'radio':
                if(el.checked)
                {
                    this.addField(el.name, el.value);
                }
                break;
            }
        }
    }
    return queryString;
};

AjaxRequest.numActiveAjaxRequests      = 0;
AjaxRequest.numActiveAjaxGroupRequests = new Object();
AjaxRequest.numAjaxRequests            = 0;

