/*
  Functions for working with XmlHttpRequests.
  Steaven Woyan
  
  In general, you only need to use initiateXmlHttpRequest, the others are internal helper functions for it.
  
*/
 
//create and initiate an xml http request with default parameters 
//notes:
//   See the full version for full parameter list and meanings
//   This is a helper version that uses some defaults for parameters.
//   This will POST or GET (based on method) to the url and send the data as text/xml
//   and it will then call your call back function.
//   If using other encodings or the need for results as text, you must use the full version
//parms:
//  method: the http method to use, "GET" or "POST" 
//  url: the url to invoke (i will escape this)
//  async: run asynchronously or not
//  data: the data to send along with the request, may be null or ""
//  handlerFunction: the call back function to invoke when done
//                   takes one parameter the responseXML
//                   will only be invoked upon completion (readystate 4)
//                   may be null in which case no handler is invoked

function initiateXmlHttpRequest(method, url, async, data, handlerFunction) {
  initiateXmlHttpRequestFull(method, encodeURI(url), async, data, "text/xml", handlerFunction, 1);
}

//create and initiate an xml http request with full range of parameters
//notes: some browsers do not call the callback function on synchronous changes, others do
//       so, here is what I do for consistency:
//       if async == true, then I hook up your call back to the request normally.
//       if async == false, then I do not hook up any call back what so ever to the request
//       instead, I call it manually after the send returns.
//parms:
//  method: the http method to use, "GET" or "POST" 
//  url: the url to invoke 
//  async: run the request asynchronously or not, true or false (true 99% of the time)
//  data: the data to send along with the request, may be null or ""
//  contentType: the content type of the data to be sent as a header
//               eg "application/x-www-form-urlencoded" or "text/xml" etc
//  handlerFunction: the call back function to invoke when done
//                   takes one parameter, either the responseXML or the responseText based on handlerDataType
//                   will only be invoked upon completion (readystate 4)
//                   may be null in which case no handler is invoked
//  handlerDataType: the type of data the handler wants, the responseXML (1) or the responseText (2)
function initiateXmlHttpRequestFull(method, url, async, data, contentType, handlerFunction, handlerDataType) {
  var xml_http_request = createXmlHttpRequest();  
  if(async) {
    xml_http_request.onreadystatechange = createReadyStateChangeHandler(xml_http_request, handlerFunction, handlerDataType);
  }  
  xml_http_request.open(method, url, async);  
  xml_http_request.setRequestHeader("Content-Type", contentType);
  xml_http_request.send(data);  
  if(!async) {
    if(xml_http_request.readyState == 4) {
      if(xml_http_request.status) {
        if(xml_http_request.status != 200) {
          alert("Error on response: " + xml_http_request.status);
          xml_http_request = null;
          return;
        }
      }  
      if(handlerFunction) {
        if(handlerDataType == 1) {
          handlerFunction(xml_http_request.responseXML);
        }
        else {
          handlerFunction(xml_http_request.responseText);
        }
      }
      xml_http_request = null;
    }
  }
}

//create an XML HTTP Request object
function createXmlHttpRequest() {
  var xml_http_request = null;
  try {
    //native
    if(typeof XMLHttpRequest != 'undefined') {
      xml_http_request = new XMLHttpRequest();
    }
    else {
      try { 
        //IE - new  
        xml_http_request = new ActiveXObject("Msxml2.XMLHTTP.6.0");        
      }        
      catch(e1){
        //IE - old
        xml_http_request = new ActiveXObject("Msxml2.XMLHTTP");        
      }
    }
  }  
  catch(e) {
    alert(e);
    xml_http_request = null;
  }
  return xml_http_request;
}

//create a readystatechange handler function
function createReadyStateChangeHandler(xml_http_request, handlerFunction, handlerDataType) {

  return function() {
    if(!xml_http_request) {
      return;
    }
    if(xml_http_request.readyState == 4) {
      if(xml_http_request.status) {
        if(xml_http_request.status != 200) {
          alert("Error on response: " + xml_http_request.status);
          xml_http_request = null;
          return;
        }
      }
      if(handlerFunction) {        
        if(handlerDataType == 1) {
          handlerFunction(xml_http_request.responseXML);
        }
        else {
          handlerFunction(xml_http_request.responseText);
        }
      }
      xml_http_request = null;
    }
  };
}
