    /**
     * getXMLHttpRequest()
     * Function for establishing the cross-browser XMLHttpRequest object.
     * @access public
     * @return mixed    false = browser does not suport AJAX | object if it does
     * @author Steven Mapes
     **/
    function getXMLHttpRequest() {
        var request = false;

        try {
            request = new XMLHttpRequest();
        } catch (e) {
            try {
                request = new ActiveXObject("Msxml2.XMLHTTP");
            } catch(e) {
                try {
                    request = new ActiveXObject("Microsoft.XMLHTTP");
               } catch(e) {
                    // Browser really doesn't support AJAX
               }
            }
        }
        return request;
    }

    /**
     * ajaxRequest()
     * Common function to set and make the AJAX request.  Can be called from another
     * function of directly is enough information is given.
     * @param string url                The URL to connect to
     * @param string callbackHandler    The name of the function that will handle the response
     * @param string method             The method to use.  GET or POST
     * @param string getXML             FALSE = responseText | TRUE = responseXML
     * @param string postData           If the METHOD is POST then this is the data to send
     * @param string contentType        If the METHOD is POST then set the RequestHeader to this
     * @param boolean async             If true then asynchronous request
     * @access public
     * @return void
     * @author Steven Mapes
     * <example>
     *   // Make a call to update the Version Select list for SiteID 1
     *   ajaxRequest("ajax/nav.php?method=getVersions&siteId=1","displayVersionList");
     * </example>
     **/
    function ajaxRequest(url,callbackHandler,method,getXML,postData,contentType,async){
        // Handle parameter defaults
        method = method || "GET";
        getXML = getXML || false;
        postData = postData || false;
        contentType = contentType || 'application/x-www-form-urlencoded';
        async = async || true;

        requestObj = getXMLHttpRequest();    // Need to put this here as IE7 breaks otherwise

        try {
            // Create the Callback Function to handle the various status
            requestObj.onreadystatechange = function() {
                // readyStates: 0 = Uninitialised | 1 = Loading | 2 = Loaded | 3 = Interactive | 4 = Completed

                if (requestObj.readyState == 4) {
                    // The request has been completed
                    hideSpinner();  // Hide the spinner

                    if (requestObj.status == 200) {
                        // Good response sent. Gather the response based on value of getXML
                        var output = requestObj.responseText;   // Using Plain-Text
                        if (getXML == true) {
                            output = requestObj.responseXML;    // Using XML
                        }

                        // Pass the response into the specified callbackHandler
                        performCallback(callbackHandler,output);
                    } else {
                        // Bad response sent from the server
                        alert("The server returned a status of "+requestObj.status+", aborting the request");
                    }
                } else {
                    // Display the in progress icon
                    document.onmousemove = displaySpinner;
                }
            }

            // If we're using GET generate a random int to help expire the browser cache
            if (method == 'GET') {
                var rand = parseInt(Math.random()*99999999);
                url += "&random="+rand;
            }

            // Specify the METHOD, URL, asynch mode
            requestObj.open(method,url,async);

            if (method == 'POST') {
                // If we're using POST data then you may need to set the request header
                if (contentType) {
                    requestObj.setRequestHeader('Content-Type',contentType);
                }
            } else {
                postData = null;
            }

            // Send the request with the POST data if required
            requestObj.send(postData);

        } catch (e) {
            handleException(e);
        }
    }

    /**
     * performCallback()
     * Common middle function that calls the ACTUAL callback handler.
     * Separate from ajaxRequest() incase we wish to do apply extra logic
     * @param string callbackHandler    The name of the callback function to handle the response
     * @param string output             The AJAX reponse
     * @access public
     * @return void
     * @author Steven Mapes
     **/
    function performCallback(callbackHandler,output) {
        eval(callbackHandler+'(output)');
    }

    /**
     * displaySpinner()
     * Displays a spinner icon near to the mousepointer.
     * Used during the AJAX requests to show something is happening
     * @param object anEvent    The event in action, in this case mousemove
     * @access public
     * @author Steven Mapes
     **/
    function displaySpinner(anEvent) {

        // Get the current mouse position on the page
        var xPos = 0;
        var yPos = 0;

        // Check for and handle non-DOM browser
        if (!anEvent) {
            var anEvent = window.event;
        }

        // Two ways of getting the mouse position depending on the browser
        if (anEvent.pageX || anEvent.pageY) {
            xPos = anEvent.pageX;
            yPos = anEvent.pageY;
        }
        else if (anEvent.clientX || eanEvent.clientY)   {
            xPos = anEvent.clientX + document.body.scrollLeft + document.documentElement.scrollLeft;
            yPos = anEvent.clientY + document.body.scrollTop + document.documentElement.scrollTop;
        }

        // Move the loading spinnger underneath the mouse
        icon = document.getElementById('loadingSpinner');
        if (icon) {
            icon.style.left = xPos+10+"px";
            icon.style.top = yPos+10+"px";
            icon.style.visibility = "visible";  // Ensure its now visible
        }
    }

    /**
     * hideSpinner()
     * Hides the spinner icon by turning its visiblity state off and moving the position off screen
     * @access public
     * @return void
     * @author Steven Mapes
     **/
    function hideSpinner() {
        document.onmousemove = null;    // Turn off the mousemove event listener

        icon = document.getElementById('loadingSpinner');
        if (icon) {
            icon.style.left = 0+"px";
            icon.style.top = 0+"px";
            icon.style.visibility = "hidden";
        }
    }


    /** INLINE JAVASCRIPT TO PREPARE CERTAIN THINGS **/
    // Initialise the XMLHttpRequest object as the page loads so its available to everything
    var requestObj = getXMLHttpRequest();
    if (requestObj == false) {
        // Prompt if the users browser does not support AJAX
        alert("Your browser does not appear to support AJAX.  Therefore this page will not work");
    }

    // Handle placing the spinner DIV somewhere onto the page
    var spinner=["/spinner.gif", 16, 16];        // An array of details about the spinner icon
    if (! document.getElementById('loadingSpinner')) {
        // Doesn't exist.  Add it now
        document.write('<span id="loadingSpinner" style="position:absolute;visibility:hidden;left:0;top:0;">'
            +'<img src="'+spinner[0]+'" width="'+spinner[1]+'" height="'+spinner[2]+'" alt="Loading"></span>');
    }
    /** INLINE JAVASCRIPT TO PREPARE CERTAIN THINGS **/
