﻿// =====================================================================
// CLASS TO AID CUSTOM AJAX CALLS
// =====================================================================
//  1. Create a new Ajax Request Handler, specify target Url
//     and optionally parameters for the page.
//
//  2. Optionally call SpecifySuccessCallback and 
//     SpecifyFailureCallback with function references
//     to be called when the Ajax request either
//     succeeds or fails. If not specified, a
//     messagebox will be displayed.
//
//  3. Call MakeRequest() to initiate the call.
//
//  4. The Success / Failure callbacks will be called
//     with a reference to the XMLHTTP object used
//     in the call, from which .responseText can
//     be retrieved, for example.
//
//  Example:
//   var DataRequest = new Ajax.RequestHandler();
//   DataRequest.SpecifyUrl("DataRequests/Test1.aspx");
//   DataRequest.AddParameter("Param1", "Value1");
//   DataRequest.AddParameter("Param2", "Value2");
//   DataRequest.SpecifySuccessCallback(ServerCallComplete);
//   DataRequest.MakeRequest();
// =====================================================================

var Ajax = new CAjax();
function CAjax()
{
    // =============================================================
    // CROSS-BROWSER ACCESS TO XMLHTTP OBJECT
    // =============================================================
    this.GetXMLHTTP = GetXMLHTTP;
    function GetXMLHTTP()
    {
        var xmlHttp = null;
        if (window.XMLHttpRequest)
            xmlHttp = new XMLHttpRequest();
        else if (window.ActiveXObject)
            xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
        return xmlHttp;
    }

    // =============================================================
    // WRAPPER FOR XMLHTTP HANDLING
    // =============================================================
    this.RequestHandler = RequestHandler;
    function RequestHandler()
    {
        // =========================================================
        // CLASS INITIALISATION
        // =========================================================
        var _arrArgs = new Array();
        var _bWaitingOnResults = false;
        var _objComms = null;
        var _strUrl = null;
        
        var _fncSuccess = null;
        var _fncFailure = null;
        
        // =========================================================
        // SET UP REQUEST (SPECIFY PAGE AND PARAMETERS)
        // =========================================================
        this.SpecifyUrl = SpecifyUrl;
        function SpecifyUrl(strUrl)
        {
            _strUrl = strUrl;
        }
        
        this.AddParameter = AddParameter;
        function AddParameter(strName, strValue)
        {
            // Record a new parameter to pass
            var objTemp = new Object();
            objTemp.Name = strName;
            objTemp.Value = strValue;
            _arrArgs[_arrArgs.length] = objTemp;
        }
        
        // =========================================================
        // SET UP CALLBACKS
        // =========================================================
        this.SpecifySuccessCallback = SpecifySuccessCallback;
        function SpecifySuccessCallback(fncCallback)
        {
            _fncSuccess = fncCallback;
        }

        this.SpecifyFailureCallback = SpecifyFailureCallback;
        function SpecifyFailureCallback(fncCallback)
        {
            _fncFailure = fncCallback;
        }
        
        // =========================================================
        // INITIATE THE DATA REQUEST
        // =========================================================
        this.MakeRequest = MakeRequest;
        function MakeRequest(bAsync)
        {
            // Optional make-async-request parameter: default true
            if ((typeof(bAsync) == "undefined") || (bAsync != false))
                bAsync = true;

            // Generate the whole url string
            // Ensure that there's a random entry to get around
            // the caching (esp. on Pocket Internet Explorer)
            var strUrl = _strUrl;
            for (var intLoop = 0; intLoop < (_arrArgs.length + 1); intLoop++)
            {
                strUrl += ((intLoop == 0) ? "?" : "&");
                if (intLoop < _arrArgs.length)
                    strUrl += _arrArgs[intLoop].Name + "=" + escape(_arrArgs[intLoop].Value);
                else
                    strUrl += "__nocache=" + (Math.random() * 10);
            }

            // Initiate the request
            try
            {
                _objComms = GetXMLHTTP();
                _objComms.open("GET", strUrl, bAsync);
                _objComms.onreadystatechange = ReadyStateChangeHandler;
                _bWaitingOnResults = true;
                _objComms.send(null);
            }
            catch(e)
            {
                RaiseFailure(_objComms, "Ajax.RequestHandler Failed: Error initialising XMLHTTP");
                return;
            }
        }
        
        // =========================================================
        // HANDLE DATA RECEIPT FROM REQUEST
        // =========================================================
        function ReadyStateChangeHandler()
        {
            // On Pocket Internet Explorer, for some reason receiving
            // multiple callbacks from each request. Use a flag to
            // keep track of when we're waiting for data, and when
            // we can ignore it.
            if (!_bWaitingOnResults)
                return;

            // In case we made an Ajax request and then the resources
            // are no longer available (eg. closing page), ignore any
            // errors.
            try
            {                
                if (_objComms.readyState == 4)
                {
                    if (_objComms.status != 200)
                    {
                        // Error occured
                        _bWaitingOnResults = false;
                        RaiseFailure(_objComms, "Ajax.RequestHandler Failed: " + _strUrl);
                        return;
                    }
                    else
                    {
                        // Success!
                        _bWaitingOnResults = false;
                        RaiseSuccess();
                        return;
                    }
                }
            }
            catch(e) {}
        }

        // =========================================================
        // RAISE EVENT CALLBACKS
        // =========================================================
        function RaiseSuccess()
        {
            if (typeof(_fncSuccess) == "function")
                _fncSuccess(_objComms);
            else
                alert("Ajax.RequestHandler Success!\n[No callback specified]");
        }
        
        function RaiseFailure(_objComms, strError)
        {
            if (typeof(_fncFailure) == "function")
                _fncFailure(_objComms, strError);
            else
                alert(strError);
        }
    }
}
