﻿var ajaxCaller =
{
    shouldDebug: false, 
    shouldEscapeVars: true, 
    shouldMakeHeaderMap: true, 
    calls : new Array(), 
    pendingResponseCount : 0, 
    getXML: function(url, callbackFunction)
    {
        this.get(url, null, callbackFunction, true, null);
    },
    getPlainText: function(url, callbackFunction)
    {
        this.get(url, null, callbackFunction, false, null);
    }, 
    postForPlainText: function(url, vars, callbackFunction)
    {
        this.postVars(url, vars, null, callbackFunction, false, null, "POST", null, null, null);
    }, 
    postForXML: function(url, vars, callbackFunction)
    {
        this.postVars(url, vars, null, callbackFunction, true, null, "POST", null, null, null);
    }, 
    get: function(url, urlVars, callbackFunction, expectingXML, callingContext)
    {
        this._callServer(url, urlVars, callbackFunction, expectingXML, callingContext, "GET", null, null, null);
    }, 
    postVars: function(url, bodyVars, optionalURLVars, callbackFunction, expectingXML, callingContext)
    {
        this._callServer(url, optionalURLVars, callbackFunction, expectingXML, callingContext, "POST", bodyVars, null, null);
    }, 
    postBody: function(url, optionalURLVars, callbackFunction, expectingXML, callingContext, bodyType, body)
    {
        this._callServer(url, optionalURLVars, callbackFunction, expectingXML, callingContext, "POST", null, bodyType, body);
    }, 
    putBody: function(url, optionalURLVars, callbackFunction, expectingXML, callingContext, bodyType, body)
    {
        this._callServer(url, optionalURLVars, callbackFunction, expectingXML, callingContext, "PUT", null, bodyType, body);
    }, 
    options: function(url, optionalURLVars, callbackFunction, expectingXML, callingContext, bodyType, body)
    {
        this._callServer(url, optionalURLVars, callbackFunction, expectingXML, callingContext, "OPTIONS", null, bodyType, body);
    }, 
    trace: function(url, optionalURLVars, callbackFunction, expectingXML, callingContext, bodyType, body)
    {
        this._debug("trace");this._callServer(url, optionalURLVars, callbackFunction, expectingXML, callingContext, "TRACE", null, bodyType, body);
    }, 
    deleteIt: function(url, urlVars, callbackFunction, expectingXML, callingContext)
    {
        this._callServer(url, urlVars, callbackFunction, expectingXML, callingContext, "DELETE", null, null, null);
    }, 
    head: function(url, urlVars, callbackFunction, expectingXML, callingContext)
    {
        this._callServer(url, urlVars, callbackFunction, expectingXML, callingContext, "HEAD", null, null, null);
    }, 
    _callServer: function(url, urlVars, callbackFunction, expectingXML, callingContext, requestMethod, bodyVars, explicitBodyType, explicitBody)
    {
        if(urlVars==null)
        {
            urlVars=new Array();
        }
        var xReq=this._createXMLHttpRequest();
        xReq.onreadystatechange=function()
        {
            ajaxCaller._onResponseStateChange(call);
        };
        var call = 
        {
            xReq: xReq, 
            callbackFunction: callbackFunction, 
            expectingXML: expectingXML, 
            callingContext: callingContext, 
            url: url
        };
        if(urlVars!=null)
        {
            var urlVarsString=this._createHTTPVarSpec(urlVars);
            if(urlVarsString.length>0)
            {
                url+="?"+urlVarsString;
            }
        }
        xReq.open(requestMethod, url, true);
        if(requestMethod=="GET" || requestMethod=="HEAD" || requestMethod=="DELETE")
        {
            this._debug("Body-less request to URL "+url);
            xReq.send(null);return;
        }
        if(requestMethod=="POST" || requestMethod=="PUT" || requestMethod=="OPTIONS" || requestMethod=="TRACE")
        {
            bodyType=null;
            body=null;
            
            if(explicitBodyType==null)
            {
                bodyType='application/x-www-form-urlencoded;charset=UTF-8';
                body=this._createHTTPVarSpec(bodyVars);
            }
            else
            {
                bodyType=explicitBodyType;
                body=explicitBody;
            }
            this._debug("Content-Type: ["+bodyType+"]\nBody: ["+body+"].");
            xReq.setRequestHeader('Content-Type', bodyType);
            xReq.send(body);
            return;
        }
        this._debug("ERROR: Unknown Request Method: "+requestMethod);
    }, 
    _onResponseStateChange: function(call)
    {
        xReq=call.xReq;
        if(xReq.readyState<4){return;}
        if(xReq.readyState==4)
        {
            callbackFunction=call.callbackFunction;
            if(!callbackFunction)
            {
                setTimeout( function(){_onResponseStateChange(call);}, 100);
            }
            var content=call.expectingXML ? xReq.responseXML : xReq.responseText;
            responseHeaders=xReq.getAllResponseHeaders();
            headersForCaller=this.shouldMakeHeaderMap ? this._createHeaderMap(responseHeaders): responseHeaders;
            callbackFunction(content, headersForCaller, call.callingContext);
        }
        call=null;
        this.pendingResponseCount--;
    }, 
    _createXMLHttpRequest: function()
    {
        try { return new ActiveXObject("Msxml2.XMLHTTP"); } catch(e) {}
        try { return new ActiveXObject("Microsoft.XMLHTTP"); } catch(e) {}
        try { return new XMLHttpRequest(); } catch(e) {}
        alert("XMLHttpRequest not supported!");
        return null;
    }, 
    _createHTTPVarSpec: function(vars)
    {
        var varsString="";
        for(key in vars)
        {
            value=vars[key];
            if(this.shouldEscapeVars)
            {
                escapePlusRE=new RegExp("\\\+");
                value=value.replace(escapePlusRE, "%2B");
            }
            varsString+='&'+key+'='+value;
        }
        if(varsString.length>0)
        {
            varsString=varsString.substring(1);
        }
        this._debug("Built var String: "+varsString);
        return varsString;
    }, 
    _createHeaderMap: function(headersText)
    {
        extractedHeaders=headersText.split("\n");
        delete extractedHeaders[extractedHeaders.length];
        headerMap=new Array();
        for(i=0;i<extractedHeaders.length-2;i++)
        {
            head=extractedHeaders[i];
            fieldNameEnding=head.indexOf(":");
            field=head.substring(0, fieldNameEnding);
            value=head.substring(fieldNameEnding+2, head.length);
            value=value.replace(/\s$/, "");
            headerMap[field]=value;
        }
        return headerMap;
    }, 
    _debug: function(message)
    {
        if(this.shouldDebug)
        {
            alert("AjaxJS Message:\n\n"+message);
        }
    }, 
    _error: function(message)
    {
        if(this.shouldDebug)
        {
            alert("AjaxJS ERROR:\n\n"+message);
        }
    }
};
