/**
 * Supply the full url with optional params. Default method is GET. On return
 * it will call the handlerFunction which will be custom to do what you want
 * with the returned XML.
 * SAMPLE USAGE
 * var req = ajaxQuery(url, handlerFunction, [method], [timeout], [timeoutHandler]);
 */

var nAjaxRequestNumber = 1;      // global request counter
var bAjaxDebug         = false;  // set to true to alert key areas for debugging

/**
 * Send a query via ajax
 * @param        string              url including variables
 * @param        function            call back function to handle the completed request
 * @param        optional string     form method, (get or post)
 * @param        optional int        length before timing out request in milliseconds
 * @param        optional function   function to call on timeout
 * @return       int                 request number (auto_incrementing)
 */
function ajaxQuery(url, handler, method, timeout, timeoutHandler) 
{
    var oReq            = Object();
    oReq.handled        = false;
    oReq.num            = nAjaxRequestNumber++;
    oReq.handler        = handler;
    oReq.method         = method || 'GET';
    oReq.timeoutHandler = timeoutHandler;

    // set up the request object
    if (window.XMLHttpRequest) // Mozilla
    {
        oReq.ht = new XMLHttpRequest();
    } 
    else if (window.ActiveXObject) // IE
    {
        try {
            oReq.ht = new ActiveXObject("Msxml2.XMLHTTP");
        } catch (e) {
            try {
                oReq.ht = new ActiveXObject("Microsoft.XMLHTTP");
            } catch (e) {}
        }
    }

    // alert and return if browser doens't support some form of XMLHttpRequest
    if (!oReq.ht)
    {
        alert('Sorry your browser doesn\'t seem to support XMLHttpRequest\'s');
        return;
    }
    else
    {
        // assign callback function
        oReq.ht.onreadystatechange = function () { processAjaxQuery(oReq) };
        if (oReq.method.toUpperCase() == 'POST')
        { 
            var urlPieces = url.split('?');
            oReq.ht.open('POST', urlPieces[0], true);
            // set content type so POST values get through
            oReq.ht.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
            // force text/xml mime type if supported
            if (oReq.ht.overrideMimeType) oReq.ht.overrideMimeType('text/xml');
            oReq.ht.send(urlPieces[1]);        
            
            if (bAjaxDebug) alert("POST URL:\nurlPieces[0]: " + urlPieces[0] + "\nurlPieces[1]: " + urlPieces[1]); // debug 
        }
        else
        {    
            oReq.ht.open('GET', url, true);
            // force text/xml mime type if supported
            if (oReq.ht.overrideMimeType) oReq.ht.overrideMimeType('text/xml');      
            oReq.ht.send(null);

            if (bAjaxDebug) alert("GET URL:\n" + url);  //debug
        }
    }
    
    // if timeout then set it up
    if ( timeout > 0 ) {
        setTimeout( function() { processAjaxTimeout(oReq) }, timeout );
    }

    return oReq.num;
}

/**
 * Check for a response from the server, it will go from readyState 0-4
 * Threw this in a try catch to elemineate Mozilla exceptions
 * @param      object        request object
 */
function processAjaxQuery(oReq) {
    try 
    {
        var hreq = oReq.ht;
        if ((hreq.readyState == 4) && (hreq.status == 200))
        {
            // if request has already been handled or timed out return
            if (oReq.handled) return;
            oReq.handled = true;                 
            if (bAjaxDebug) alert("XML Response\n" + hreq.responseText); // debug
            response = hreq.responseXML.documentElement;"XML Response\n" + hreq.responseText
            if (oReq.handler != null)
            {
                if (bAjaxDebug) alert(oReq.handler);
                oReq.handler(oReq.num, response);
            }        
        }
    }
    catch(e) {}
}

/**
 * run if a timeout is set and exceeded
 * @param         object         request object
 */
function processAjaxTimeout(oReq) 
{
    if (oReq.handled) return;  // no timeout b/c it was already handled.

    oReq.handled = true;  // mark handled.
    oReq.ht.abort();      // kill it off.

    if (oReq.timeoutHandler != null)
    {
        oReq.timeoutHandler(oReq.num);
    }
}

/**
 * submit a form through ajaxQuery, handles the setting up the of the ajax request
 * using the form elements, action and method
 * @param        string              url including variables
 * @param        function            call back function to handle the completed request
 * @param        optional int        length before timing out request in milliseconds
 * @param        optional function   function to call on timeout
 * @return       int                 request number
 */
function ajaxFormSubmit(formName, handler, timeout, toHandler)
{
    var form = document.forms[formName];
    var url  = form.action;
    var meth = form.method;
    var elts = form.elements;

    var argn = 0;
    var args = "";

    if (meth == undefined || meth == "") meth = "GET";

    /* loop over the form elements and handle them based on type
     * {Mozilla, IE} type = {text, hidden, checkbox, radio, select-one, select-multiple}
     */
    for (var i = 0; i < elts.length; i++)
    {
        var elt = elts.item(i);
        if (elt.name)
        {
            if (elt.type == 'select-multiple' || elt.type == 'select-one') {

                for(var j = 0; j < elt.options.length; j++) {

                    var opt = elt.options[j];
                    if (opt.selected)
                    {
                        var ovalue = opt.value;
                        if (ovalue == undefined || ovalue == null || ovalue == '')
                        {
                            ovalue = opt.text;
                        }

                        if (argn)
                        {
                            args += '&';
                        }
                        argn++;
                        args += elt.name + '=' + encodeURIComponent(ovalue);
                    }
                }

            }
            else if (elt.type == 'checkbox' || elt.type == 'radio')
            {
                if (elt.checked)
                {
                    if (argn)
                    {
                        args += '&';
                    }
                    argn++;
                    args += elt.name + '=' + encodeURIComponent(elt.value);
                }

            }
            else
            {  // text, hidden, ???
                var ovalue = elt.value;
                if (ovalue != undefined && ovalue != null && ovalue != '')
                {
                    if (argn)
                    {
                        args += '&';
                    }
                    argn++;
                    args += elt.name + '=' + encodeURIComponent(elt.value);
                }
            }
        }
    }
    var req = ajaxQuery(url + '?' + args, handler, meth.toUpperCase(), timeout, toHandler);
    return req;
}