﻿// JScript File

// All common convenience function for GENII AJAX-related functionalities should be put here.

// You should use the following "constants" in your script, do not use the numbers directly.
// Using magic numbers directly is BAD programming practice.

// Common values for the ReadyState for the XMLHttpRequest object
var READYSTATE_UNINITIALIZED = 0;
var READYSTATE_LOADING = 1;
var READYSTATE_LOADED = 2;
var READYSTATE_INTERACTIVE = 3;
var READYSTATE_COMPLETE = 4;

// Common HTTP response states.

// status is 0 when request is aborted.
var HTTPSTATUS_ABORT = 0;

// 2xx success.
var HTTPSTATUS_OK = 200;

// 4xx client errors.
var HTTPSTATUS_BAD_REQUEST = 400;
var HTTPSTATUS_UNAUTHORIZED = 401;
var HTTPSTATUS_FORBIDDEN = 403;
var HTTPSTATUS_NOTFOUND = 404;
var HTTPSTATUS_METHOD_NOT_ALLOWED = 405;
var HTTPSTATUS_REQUEST_URI_TOO_LONG = 414;

// 5xx server errors.
var HTTPSTATUS_INTERNAL_SERVER_ERROR = 500;
var HTTPSTATUS_NOT_IMPLEMENTED = 501;
var HTTPSTATUS_BAD_GATEWAY = 502;
var HTTPSTATUS_SERVICE_TEMPORARILY_UNAVAILABLE = 503;

/* Global variable to be used by CreateXmlHttpRequestObject() only. Not intended
 * to be accessed directly by functions other than the ones explicitly listed below.
 * The global variables enable reuse of XMLHttpRequest object and prevents potential memory leak.
 *
 * Accessible to:
 * CreateOrGetXmlHttpRequestObject()
 * GetXmlHttpRequestObject()
 */
var __xmlHttpObj = null;

/* Global variable of MSXML DOM object to prevent recreating the object many times over
 * and to prevent potential memory leak. Not intended to be accessed directly by functions
 * other than the ones explicitly listed below.
 *
 * Accessible to:
 * CreateMsXmlDom()
 * GetMsXmlDom()
 */
var __msXmlDom = null;

// Creates an MSXML DOM object.
function CreateMsXmlDom()
{
    if (__msXmlDom == null) {
        __msXmlDom = new ActiveXObject("msxml2.DOMDocument.3.0");
        __msXmlDom.async = false;
        __msXmlDom.resolveExternals = false;
    }
    
    return __msXmlDom;
}

// A clearer function name.
function CreateOrGetMsXmlDom()
{
    return CreateMsXmlDom();
}

// Accessor for the globally stored MSXML DOM object.
function GetMsXmlDom()
{
    if (__msXmlDom == null) {
        throw new Error("The MSXML DOM object is null.");
    }
    
    return __msXmlDom;
}

// Accessor for the globally stored XMLHttpRequest object.
function GetXmlHttpRequestObject()
{
    if (__xmlHttpObj == null) {
        throw new Error("The XML HTTP Object is null.");
    }
    
    return __xmlHttpObj;
}

/* Creates an XMLHttpRequest object (hopefully) independently from the current browser.
 * Use this if you want a fresh XMLHttpRequest object. Useful when making multiple
 * XmlHttp requests in a page.
 */
function CreateXmlHttpRequestObject()
{
    // Create a new XMLHTTP object..
    if (window.ActiveXObject) {
        try {
            return new ActiveXObject("Microsoft.XMLHTTP");
        } catch (e) {
            return new ActiveXObject("Msxml2.XMLHTTP");
        }
    }
    else {
        return new XMLHttpRequest();
    }
}

/* Creates an XMLHttpRequest object (hopefully) independently from the current browser.
 * If the global object __xmlHttpObj exists already, the existing reference is returned,
 * otherwise, a new one is created. Use this if you are not sure whether to get or to
 * create.
 */
function CreateOrGetXmlHttpRequestObject()
{
    if (__xmlHttpObj == null) {
        // First time the function is called.
        if (window.ActiveXObject) {
            try {
                __xmlHttpObj = new ActiveXObject("Microsoft.XMLHTTP");
            } catch (e) {
                __xmlHttpObj = new ActiveXObject("Msxml2.XMLHTTP");
            }
        }
        else {
            __xmlHttpObj = new XMLHttpRequest();
        }
    }
    
    return __xmlHttpObj;
}

/* Makes an XMLHttpRequest call asynchronously using HTTP GET.
 *
 * Parameters:
 * callbackFun - The call back function to invoke after the call is completed.
 * url - the url of an HTTP handler to handle the call.
 * reuseObject - Optional boolean parameter specifies whether the XmlHttp object can be reused. 
 *                  Default value is true (object is resused).
 *
 * Usage:
 * Regarding how to write callbackFun. A minimal callbackFun should look like this:
 * function aCallBackFun()
 * {
 *     var xmlHttpObj = GetXmlHttpRequestObject();
 *     if (xmlHttpObj.readyState == READYSTATE_COMPLETE) {
 *         if (xmlHttpObj.status != HTTPSTATUS_OK) {
 *             alert("Error in XML HTTP call.");
 *             return;
 *         }
 *         // Access various properties exposed by xmlHttpObj here and do 
 *         // other things with the result.
 *         alert(xmlHttpObj.responseText);
 *     }
 * }
 * aCallBackFun should not need to take any parameters as the parameters should be passed
 * to the HTTP handler that services the request and specified as part of url parameter
 * to MakeAsyncXmlHttpCall.
 */
function MakeAsyncXmlHttpCall(callbackFun, url, reuseObject)
{
    var xmlHttpObj;
    var asyncCall = true;
    
    // Set optional parameter value to true
    if (typeof reuseObject == "undefined") {
        reuseObject = true;
    }
    
    if (reuseObject) {
        xmlHttpObj = CreateOrGetXmlHttpRequestObject();
    } else {
        xmlHttpObj = CreateXmlHttpRequestObject();
    }
    
    if (xmlHttpObj) {
    
        // For MSIE:
        // Open the request first, and then attach the event handler. The approach somehow facilitates
        // correct re-use of XMLHttpObject in CreateXmlHttpRequestObject().
        // For full discussion of the issue, refer to:
        // http://keelypavan.blogspot.com/2006/03/reusing-xmlhttprequest-object-in-ie.html
        xmlHttpObj.open("GET", url, asyncCall);
        xmlHttpObj.onreadystatechange = callbackFun;
        
        // Actually sends the request.
        
        // This should prevent MSIE from reading stale cached response.
        // Refer to http://en.wikipedia.org/wiki/XMLHttpRequest for discussion.
        xmlHttpObj.setRequestHeader("If-Modified-Since", new Date(0));
        xmlHttpObj.send(null);
    }
    
    return xmlHttpObj;
}

/* Makes an XMLHttpRequest call asynchronously using HTTP POST.
 *
 * Parameters:
 * callbackFun - The call back function to invoke after the call is completed.
 * url - the url of an HTTP handler to handle the call.
 * postParams - HTTP POST parameters in URL encoded format that is a single string, such as,
 *      "foo1=bar1&foo2=bar2".
 * reuseObject - Optional boolean parameter specifies whether the XmlHttp object can be reused. 
 *                  Default value is true (object is resused).
 *
 * Usage:
 * Regarding how to write callbackFun. A minimal callbackFun should look like this:
 * function aCallBackFun()
 * {
 *     var xmlHttpObj = GetXmlHttpRequestObject();
 *     if (xmlHttpObj.readyState == READYSTATE_COMPLETE) {
 *         if (xmlHttpObj.status != HTTPSTATUS_OK) {
 *             alert("Error in XML HTTP call.");
 *             return;
 *         }
 *         // Access various properties exposed by xmlHttpObj here and do 
 *         // other things with the result.
 *         alert(xmlHttpObj.responseText);
 *     }
 * }
 * aCallBackFun should not need to take any parameters as the parameters should be passed
 * to the HTTP handler that services the request and specified as part of the postParams 
 * passed to MakeAsyncXmlHttpCallPost.
 * !!!WARNING!!!
 * DOES NOT WORK YET WITH IE DUE TO ERROR NUMBER 12030.
 * 12030 is one of the WinInet error codes: http://support.microsoft.com/default.aspx?scid=kb;EN-US;193625.
 */
//function MakeAsyncXmlHttpCallPost(callbackFun, url, postParams, reuseObject)
//{
//    var xmlHttpObj;
//    var asyncCall = true;
//    
//    // Set optional parameter value to true
//    if (typeof reuseObject == "undefined") {
//        reuseObject = true;
//    }
//    
//    if (reuseObject) {
//        xmlHttpObj = CreateOrGetXmlHttpRequestObject();
//    } else {
//        xmlHttpObj = CreateXmlHttpRequestObject();
//    }
//    
//    if (xmlHttpObj) {
//    
//        // For MSIE:
//        // Open the request first, and then attach the event handler. The approach somehow facilitates
//        // correct re-use of XMLHttpObject in CreateXmlHttpRequestObject().
//        // For full discussion of the issue, refer to:
//        // http://keelypavan.blogspot.com/2006/03/reusing-xmlhttprequest-object-in-ie.html
//        xmlHttpObj.open("POST", url, asyncCall);
//        xmlHttpObj.onreadystatechange = callbackFun;        
//        xmlHttpObj.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
//        xmlHttpObj.setRequestHeader("Content-Length", postParams.length.toString());
//        xmlHttpObj.setRequestHeader("Content-Disposition", 'form-data; name="GENIIAJAX"');
//        xmlHttpObj.setRequestHeader("Connection", "close");
//        
//        // Actually sends the request.
//        
//        // This should prevent MSIE from reading stale cached response.
//        // Refer to http://en.wikipedia.org/wiki/XMLHttpRequest for discussion.
//        //xmlHttpObj.setRequestHeader("If-Modified-Since", new Date(0));
//        xmlHttpObj.send(postParams);
//    }
//    
//    return xmlHttpObj;    
//}


