// AJAX


var Ajax = {

    _MSXML_PROGIDS:['Msxml2.XMLHTTP.6.0',
                    'Msxml2.XMLHTTP.4.0',
                    'Msxml2.XMLHTTP.3.0',
                    'Msxml2.XMLHTTP',
                    'Microsoft.XMLHTTP'],


    /** 
     * CreateXhrObject
     * cross-browser instantiation of XMLHttpRequest object 
     * @public 
     * @return connection object or null if not supported 
    /*______________________________________________________________________________*/    
    CreateXhrObject:function(){
        var oXHR = null;

        if (typeof XMLHttpRequest != "undefined"){
            oXHR = new XMLHttpRequest();
        }else{

/*@cc_on
  @if (@_jscript_version >= 5)


            for (var i=0; i < this._MSXML_PROGIDS.length; i++){
                try {
                    oXHR = new ActiveXObject(this._MSXML_PROGIDS[i]); 
                    this._MSXML_PROGIDS = [this._MSXML_PROGIDS[i]];
                    break;
                } catch (e) {
                    oXHR = null;
                }
            }


@end @*/

            if (!oXHR && window.createRequest) { // IceBrowser 
                try {
                    oXHR = window.createRequest();
                } catch (e) {
                    oXHR = null;
                }
            }

        }

        return oXHR;
    },


    /** 
     * isSupported
     * call this function to find out if current browser supports XMLHTTP requests 
     * @public 
     * @return boolean 
    /*______________________________________________________________________________*/
    isSupported:function(){
        return (this.CreateXhrObject())? true : false;
    }

};




/**
 * If several concurrent requests are needed, several instances of Request can be created.
 */ 
Ajax.Request = function (){

    this._req = null;
    this.method = 'GET'; // public
    this.async = true; // public
    this.status = null; // public
    this._requestHeaders = [];
    this._busy = false;
    this._sFormData = null;
    this._isFormSubmit = false;
}; 


Ajax.Request.prototype = {
   
    Abort:function(){
        if (this._req) {
            this._req.onreadystatechange = function(){ };
            this._req.abort();
            this._req = null;
            this._busy = false;
        }
    },

    isBusy:function(){
        return this._busy;
    },


  /**
   * Note: This is a modified method borrowed from Yahoo! UI Library.
   *       
   * This method assembles the form label and value pairs and
   * constructs an encoded string.
   * Call() will automatically initialize the
   * transaction with a HTTP header Content-Type of
   * application/x-www-form-urlencoded.
   * @public
   * @param {string || object} form id or form object.
   * @return void
   /*______________________________________________________________________________*/
	SetForm:function(formId){

		this._sFormData = '';
		var oForm = null;
		if (typeof formId == 'string'){
			oForm = document.getElementById(formId);
		} else if(typeof formId == 'object'){
			oForm = formId;
		} else{
			return;
		}


		var oElement, oName, oValue, oDisabled;
		var hasSubmit = false;

		// Iterate over the form elements collection to construct the
		// label-value pairs.
		for (var i=0; i<oForm.elements.length; i++){
			oDisabled = oForm.elements[i].disabled;

			// If the name attribute is not populated, the form field's
			// value will not be submitted.
			oElement = oForm.elements[i];
			oName = oElement.name;
			oValue = oElement.value;

			// Do not submit fields that are disabled or
			// do not have a name attribute value.
			if(!oDisabled && oName){
				switch (oElement.type){
					case 'select-one':
					case 'select-multiple':
						for(var j=0; j<oElement.options.length; j++){
							if (oElement.options[j].selected){
									this._sFormData += encodeURIComponent(oName) + '=' + encodeURIComponent(oElement.options[j].value || oElement.options[j].text) + '&';
							}
						}
						break;
					case 'radio':
					case 'checkbox':
						if(oElement.checked){
							this._sFormData += encodeURIComponent(oName) + '=' + encodeURIComponent(oValue) + '&';
						}
						break;
					case 'file': // file upload is not supported
					case undefined:
					case 'reset':
					case 'button':
						break;
					case 'submit':
						if(hasSubmit == false){
							this._sFormData += encodeURIComponent(oName) + '=' + encodeURIComponent(oValue) + '&';
							hasSubmit = true;
						}
						break;
					default:
						this._sFormData += encodeURIComponent(oName) + '=' + encodeURIComponent(oValue) + '&';
						break;
				}
			}
		}// end for

		this._isFormSubmit = true;
		this._sFormData = this._sFormData.substr(0, this._sFormData.length - 1);
	},


    /** 
     * Call
     * Method for initiating an asynchronous request via the XHR object.
     * @public 
     * @param {string} URL address
     * @param {object} optional user-defined callback object.
     * @param {string} optional post body
     * @return {object} XHR object
    /*______________________________________________________________________________*/
    Call:function(url,callBack,postData){

            this._req = Ajax.CreateXhrObject();
            if (!this._req){ // Could not create XMLHttpRequest object
                return null;
            }

            if (this.isBusy()){
                return null;
            }


            this.status = null;
            this._busy = true;
            this.method = this.method.toUpperCase();

            if (this._isFormSubmit){
                if (this.method == 'GET'){
                    if (url.indexOf("?") == -1){
					   url += "?"+  this._sFormData;
					}else{
					   url += "&"+  this._sFormData;
					}
				} else if(this.method == 'POST'){
					postData = this._sFormData;
				}
				this._sFormData = '';
            }

            this._req.open(this.method, url, this.async);

            var self = this;
            if (this.async){
                this._req.onreadystatechange = function(){
                    if (self._req.readyState == 4) {
                        self._req.onreadystatechange = function() {}; // Avoid memory leak in MSIE: clean up the event handler
                        self.status = self._req.status; 

                        self.HandleResponse.apply(self, [self._req.status,callBack]);
                        
                        self._req = null;
                        self._busy = false;
                    }
                }
            }

            this.setRequestHeaders();
            this._isFormSubmit = false;


            this._req.send(this.method == 'POST'? postData : null);         

            if (!this.async){
                this.HandleResponse(this._req.status,callBack); 
                this._req = null;
                this._busy = false;
            }
    },


    /** 
     * HandleResponse
     * interprets the server response by examining the HTTP status code and calls
     * the appropriate, user defined, callback function depending on the HTTP status code.
     * @private 
     * @param {int} HTTP status code
     * @param {object} user defined object with callback functions for success and failure 
     * @return {void}               
    /*______________________________________________________________________________*/
    HandleResponse : function(httpStatus, callBack){

        if ((httpStatus >= 200 && httpStatus < 300) || httpStatus==304){

            if (callBack && callBack.success){
                if (!callBack.scope){
                    callBack.success(this._req);
                } else {
                    // If a scope property is defined, the callback will be fired from
                    // the context of the object.
                    callBack.success.apply(callBack.scope, [this._req]);
                }
            }

        } else {

            if (callBack && callBack.failure){
                if (!callBack.scope){
                    callBack.failure(this._req);
                } else {
                    callBack.failure.apply(callBack.scope, [this._req]);
                }
            }

        }

    },


    /** 
     * setRequestHeaders
     * @private
     * @return {void}          
    /*______________________________________________________________________________*/
    setRequestHeaders: function(){
        var requestHeaders = ['X-Requested-With', 'XMLHttpRequest'];

        if (this.method.toUpperCase() == 'POST') {
            requestHeaders.push('Content-type','application/x-www-form-urlencoded');

            /* Force "Connection: close" for Mozilla browsers to work around
            * a bug where XMLHttpReqeuest sends an incorrect Content-length
            * header. See Mozilla Bugzilla #246651. 
            */
            if (this._req.overrideMimeType){
                requestHeaders.push('Connection', 'close');
            }
        }

        if (this._requestHeaders){
            requestHeaders.push.apply(requestHeaders, this._requestHeaders);
        }

        for (var i=0; i < requestHeaders.length; i += 2){
            this._req.setRequestHeader(requestHeaders[i], requestHeaders[i+1]);
        }
    }

};
