////////////////////////////////////////////////////////////////////////
// Simple Ajax Call Object
////////////////////////////////////////////////////////////////////////
//
// Version: 1.8
// Author: SiC
// Last Modified: 2005-12-13 18:04:07
////////////////////////////////////////////////////////////////////////

var simpleAjax={

  // Member Variables
  error: null,
  arrXMLHTTP: {},
  result: {},

  // *** Get a XMLHTTP object ***
  getXMLHTTP: function(){
    var objXMLHTTP;
    try{
      objXMLHTTP = new ActiveXObject("Microsoft.XMLHTTP");
    }catch(e){
      this.error = e;
      return null;
    }
    return objXMLHTTP;
  },

  // *** Get a XMLDOM object ***
  getXMLDOM: function(){
    var objXMLDOM;
    try{
      objXMLDOM = new ActiveXObject("Microsoft.XMLDOM");
      objXMLDOM.async = false;
    }catch(e){
      this.error = e;
      return null;
    }
    return objXMLDOM;
  },

  // *** A Daemon function to pass paramters for event handler ***
  callDaemon: function(func,context, id, callBackFunc, responseType){
    return function(){ func(context, id, callBackFunc, responseType); }
  },

  // *** Load content from remote url via XMLDOM ***
  // id: can be string or number, to indentify this call when callback
  // url: target url of this call
  // callBackFunc: the callback function handle
  //               callBackFunc(id, result, errorCode, errorText)
  //               id: the id of this call
  //               result: response text or xml of remote server
  //               errorCode: parse error code of XMLDOM
  //               errorText: description of error
  // responseType: response content mode (optional, default is 0)
  //       0 - xml (raw xml text, must be valid)
  //       1 - text (if the remote xml file contains xsl link, the text will be the transformed result)
  load: function(id, url, callBackFunc, responseType){
    if(responseType==undefined) responseType=0;

    if(!this.arrXMLHTTP[id]){
      this.arrXMLHTTP[id]=this.getXMLDOM();
      if(!this.arrXMLHTTP[id]) return false;
    }

    this.arrXMLHTTP[id].async=true;
    this.arrXMLHTTP[id].onreadystatechange = this.callDaemon(this.readyStateCheckXMLDOM, this, id, callBackFunc, responseType);

    try{
      this.arrXMLHTTP[id].load(url);
    }catch(e){
      this.error = e;
      return false;
    }

    return true;
  },

  // *** Check ready state for XMLDOM***
  readyStateCheckXMLDOM: function(context, id, callBackFunc, responseType){
    if(context.arrXMLHTTP[id].readyState!=4) return;

    if(responseType==0){
      context.result[id]=context.arrXMLHTTP[id].xml;
    }else if(responseType==1){
      context.result[id]=context.arrXMLHTTP[id].text;
    }

    callBackFunc(id,
      (context.arrXMLHTTP[id].parseError.errorCode==0 ? true : false),
      context.arrXMLHTTP[id].parseError.errorCode,
      context.arrXMLHTTP[id].parseError.reason);

    context.arrXMLHTTP[id].onreadystatechange = function(){};
    context.arrXMLHTTP[id]=null;
  },

  // *** Make a GET request via XMLHTTP and get the response ***
  get: function(id, url, callBackFunc, arrParams){
    return this.call(id, url, "GET", "", callBackFunc, arrParams);
  },

  // *** Make a POST request via XMLHTTP and get the response ***
  post: function(id, url, strRequest, callBackFunc, responseType){
    return this.call(id, url, "POST", strRequest, callBackFunc, arrParams);
  }, 

  // *** Make a call with XMLHTTP ***
  // {id} can be string or number, to indentify this call when callback
  // {url} target url of this call
  // {callMethod} can be "GET" or "POST"
  // {strRequest} the request content sent to remote server, only for "POST" method
  // {callBackFunc} the callback function handle
  //               callBackFunc(id, result, status, statusText)
  //               id: the id of this call
  //               result: response text or xml of remote server
  //               status: final status code of XMLHTTP
  //               statusText: description of status
  // {arrParams} a struct contains extra parameters
  // ->responseType: response content mode (optional, default is 0)
  //       0 - plain text
  //       1 - xml (XMLHTTP will automatically convert the content into Unicode)
  //       2 - stream (if you want to get the raw data for XMLDOM etc.)
  // ->requestHeaders: an Array of custom headers for this call
  call: function(id, url, callMethod, strRequest, callBackFunc, arrParams){

    if(!arrParams['responseType']) arrParams['responseType']=0;
    if(callMethod!="POST"){
      callMethod="GET";
      strRequest="";
    }

    if(!this.arrXMLHTTP[id]){
      this.arrXMLHTTP[id]=this.getXMLHTTP();
      if(!this.arrXMLHTTP[id]) return false;
    }

    this.arrXMLHTTP[id].onreadystatechange = this.callDaemon(this.readyStateCheckXMLHTTP, this, id, callBackFunc, arrParams['responseType']);

    if(arrParams['requestHeaders']){
      for(var i=0;i<arrParams['requestHeaders'].length;i++){
        this.arrXMLHTTP[id].setRequestHeader(arrParams['requestHeaders'][i][0],arrParams['requestHeaders'][i][1]);
      }
    }

    try{
      this.arrXMLHTTP[id].open(callMethod, url, true);
      this.arrXMLHTTP[id].send(strRequest);
    }catch(e){
      this.error = e;
      return false;
    }

    return true;
  },

  // *** Check ready state for XMLHTTP***
  readyStateCheckXMLHTTP: function(context, id, callBackFunc, responseType){
    if(context.arrXMLHTTP[id].readyState!=4) return;

    if(responseType==0){
      context.result[id]=context.arrXMLHTTP[id].responseText;
    }else if(responseType==1){
      context.result[id]=context.arrXMLHTTP[id].responseXML.xml;
    }else{
      context.result[id]=context.arrXMLHTTP[id].responseStream;
    }
    
    callBackFunc(id,
      (context.arrXMLHTTP[id].status==200 ? true : false),
      context.arrXMLHTTP[id].status,
      context.arrXMLHTTP[id].statusText);

    context.arrXMLHTTP[id].onreadystatechange=function(){};
    context.arrXMLHTTP[id]=null;
  },

  // *** Clean up to avoid memory leak ***
  cleanUp: function(){
    for(var id in this.arrXMLHTTP){
      this.arrXMLHTTP[id].abort();
      this.arrXMLHTTP[id].onreadystatechange=function(){};
      this.arrXMLHTTP[id]=null;
    }
    for(var id in this.result){
      this.result[id]=null;
    }
  }
}

// Avoid IE memory leak
window.attachEvent("onunload",simpleAjax.cleanUp);