﻿// ###
//  This is the Bellwether Web Solutions (www.bellwetherwebsolutions.com) AJAX JavaScript.
//      It can be used to perform a request and get a response.
//
//  2008 (c) Bellwether Web Solutions
// ###

// This class handles sending and receiving AJAX requests
function BellwetherAjax( obj, customJavascript )
{
    // This handles the task of communicating with the web server and getting an XML
    var m_objHttpHandler = null;
    // This is a global value to tell if we successfully received data from the request
    var m_bHasResponse = false;
    // The timeout (in mili-seconds) after which the request will be aborted
    var m_dTimeout = 60000;
    // This keeps track of the date-time when the ajax request was sent to the web server
    var m_dtRequestSent;
    // We can have multiple Ajax requests at one time, this is the unique identifier
    var m_nGUID;
    // This is the HTML object we will populate with the input
    var m_objHTMLResult = obj;
    // This is the Ajax response text
    var m_szAjaxResult = "";
    // The user can define a custom javascript (array) to be run after an ajax result is received
    var m_a_szCustomJavascript = customJavascript;
    
    this.initialize = function()
    {
        // Resets member variables
        if(window.XMLHttpRequest)
        {
            // Mozilla, Safari
            m_objHttpHandler = new XMLHttpRequest();
            if(m_objHttpHandler.overrideMimeType)
            {
                m_objHttpHandler.overrideMimeType('text/xml');
            }
        }
        else if(window.ActiveXObject)
        {
            // Internet explorer
            try
            {
                m_objHttpHandler = new ActiveXObject("Msxml2.XMLHTTP");
            }
            catch(e)
            {
                try
                {
                    m_objHttpHandler = new ActiveXObject("Microsoft.XMLHTTP");
                }
                catch(e) { m_objHttpHandler = null; }
            }
        }
        
        m_nGUID = new Date().getTime();
    }
    
    this.HasResponse = function()
    {
        return m_bHasResponse;
    }
    
    this.AjaxResult = function()
    {
        return m_szAjaxResult;
    }
    
    this.SynchronousRequest = function( url )
    {
        // This performs a request just like AJAX, but it is synchronous (so the calling method will
        //      be halted until we receive a result)
        
        // Check to see if our XML Http Handler has been initialized
        if(!m_objHttpHandler) this.initialize();
        
        // Reset our handling variables
        m_bHasResponse = false;
        m_dtRequestSent = new Date();
        
        // Open the connection to the server
        m_objHttpHandler.open("GET", url, false);
        
        // Send the request
        m_objHttpHandler.send(null);
        
        // Wait for the response and set the member value
        m_szAjaxResult = m_objHttpHandler.responseText;
    }
    
    this.AjaxRequest = function( url )
    {
        // Check to see if our XML Http Handler has been initialized
        if(!m_objHttpHandler) this.initialize();
        
        // Reset our handling variables
        m_bHasResponse = false;
        m_dtRequestSent = new Date();
        
        // Open the connection to the server
        m_objHttpHandler.open("GET", url, true);
        
        // Assign the callback function for after the request has been completed successfully
        var objSelf = this;
        // We created an objSelf because we anticipate multiple ajax requests at once. By declaring
        //  the object, the javascript will be better able to determine which request is being handled
        m_objHttpHandler.onreadystatechange = objSelf.AcceptAjaxResponse;
        
        // Set the timeout for the request
        var id = m_nGUID;
        setTimeout(function() { objSelf.AjaxRequestTimeout(id) }, m_dTimeout);
        
        // Send the request
        m_objHttpHandler.send(null);
    }
    
    this.AcceptAjaxResponse = function()
    {
        // Check to see if we have a response
        if(m_objHttpHandler && m_objHttpHandler.readyState == 4)
        {        
            m_bHasResponse = true;
            
            // Get the status code for the ajax request. Wrap the work in a try catch b/c in firefox
            //      if the user leaves the page while we're working, we'll get an error
            var nStatusCode = 0;
            try { nStatusCode = m_objHttpHandler.status; }
            catch(e) { nStatusCode = 0; }
            
            if(nStatusCode != 0 && nStatusCode != 200 && m_objHttpHandler.responseText.length)
            {
                // We've received a web server error so abort the request and reset our variables
                m_objHttpHandler.onreadystatechange = function () { return false }
                m_objHttpHandler.abort();
                m_nGUID = null;
                m_dtRequestSent = null;
                m_bHasResponse = true;
                m_szAjaxResult = "";
            
                return false;
            }
            else
            {
                m_bHasResponse = true;
                m_szAjaxResult = m_objHttpHandler.responseText;
                // If the user provided an HTML object, we'll update its value
                if(m_objHTMLResult)
                {
					if(m_objHTMLResult.innerHTML)
                    {
                        m_objHTMLResult.innerHTML = m_szAjaxResult;
                    }
					else
					{
						if(m_objHTMLResult.value)
						{
							m_objHTMLResult.value = m_szAjaxResult;
						}
					}
                }
                // If the user supplied custom javascript, we'll run that
                if(m_a_szCustomJavascript && m_a_szCustomJavascript.length)
                {
                    // Run the custom javascript
                    for(var cj = 0; cj < m_a_szCustomJavascript.length; cj++)
                    {
                        setTimeout(m_a_szCustomJavascript[cj], 10*cj);
                    }
                }
            }
            
            return nStatusCode == 200;
        }
        
        return false;
    }
    
    this.AjaxRequestTimeout = function ( requestId )
    {
        // This will handle what happens if the Ajax request associated with requestId
        //      where requestId = BellwetherAjax.m_nGUID
        
        m_szAjaxResult = "";
        m_bHasResponse = true;
        
        // First, we make sure the request that has timed out is this request
        if(requestId != m_nGUID) return;
        
        // The timeout period has elapsed, so we will abort the request
        if(m_objHttpHandler)
        {
            m_objHttpHandler.onreadystatechange = function () { return false }
            m_objHttpHandler.abort();
        }
        m_nGUID = null;
        m_dtRequestSent = null;
        
        // Reset the other member variables
        if(window.XMLHttpRequest)
        {
            // Mozilla, Safari
            m_objHttpHandler = new XMLHttpRequest();
            if(m_objHttpHandler.overrideMimeType)
            {
                m_objHttpHandler.overrideMimeType('text/xml');
            }
        }
        else if(window.ActiveXObject)
        {
            // Internet explorer
            try
            {
                m_objHttpHandler = new ActiveXObject("Msxml2.XMLHTTP");
            }
            catch(e)
            {
                try
                {
                    m_objHttpHandler = new ActiveXObject("Microsoft.XMLHTTP");
                }
                catch(e) { m_objHttpHandler = null; }
            }
        }
        
        m_nGUID = new Date().getTime();
    }
} // end BellwetherAjax singleton