//*****************************************************************************
// HttpRequest	http://www.brainjar.com/dhtml/ajax/
//   Defines a object for making asynchronous HTTP GET and POST requests.
//
//   It is basically a wrapper for the XmlHttpRequest object that hides
//   differences between browsers and makes it easier to set up callback
//   functions.
//-----------------------------------------------------------------------------
// Constructor:
//
//   HttpRequest()
//     Creates a new instance of the HttpRequest object.
//
//     Notes: Be sure to set the url property before calling get() or post().
//     Likewise, if you want to process the response, set the successCallback
//     property. To process errors on an unsuccessful request, set the
//     failureCallback property (see below).
//-----------------------------------------------------------------------------
// Properties:
//
//   successCallback
//     A function to be called when a GET or POST request completes
//     successfully (i.e., the HTTP status is "200 OK"). The function should
//     accept one argument which will be the HttpRequest object that made the
//     request
//
//   failureCallback
//     A function to be called when a GET or POST request completes
//     unsuccessfully (i.e., the HTTP status is anything other than "200 OK").
//     The function should accept one argument which will be the HttpRequest
//     object that made the request
//
//   url
//     The URL to send the request to. It should not include a query string.
//
//   queryString
//     A query string to append to the URL.
//
//   username
//     Username for authentication, if required.
//
//   password
//     Password for authentication, if required.
//
//   status
//     The status of the response returned from a request. This will be an
//     HTTP status code. For example, a sucessful call returns 200.
//
//   statusText
//     The text associated with the status code. For example, the text for HTTP
//     status code 404 is "Object Not Found".
//
//   responseText
//     A string representing the data returned from a request.
//
//   responseXML
//     A DOM document object representing the XML returned from a request.
//-----------------------------------------------------------------------------
// Methods:
//
//   abort()
//     Aborts a request that is in currently progress.
//
//   setRequestHeader(name, value)
//     Sets the specified request header.
//
//   getRequestHeader(name)
//     Returns the value of the specified request header.
//
//   removeRequestHeader(name, value)
//     Removes the the specified request header.
//
//   clearRequestHeaders()
//     Removes all request headers.
//
//   get()
//     Performs an asynchronous GET request.
//
//   post(data)
//     Performs an asynchronous POST request, passing the given data. Be sure
//     to set the "Content-Type" request header appropriately prior to calling
//     post().
//
//   getResponseHeader(name)
//     Returns the value of the named response header returned from a request.
//
//   getAllResponseHeaders()
//     Returns a string containing all the response headers returned from a
//     request.
//*****************************************************************************

// Define a list of Microsoft XML HTTP ProgIDs.
HttpRequest.prototype.MS_PROGIDS = new Array(
									"Msxml2.XMLHTTP.7.0",
									"Msxml2.XMLHTTP.6.0",
									"Msxml2.XMLHTTP.5.0",
									"Msxml2.XMLHTTP.4.0",
									"MSXML2.XMLHTTP.3.0",
									"MSXML2.XMLHTTP",
									"Microsoft.XMLHTTP");

// Define constants.
HttpRequest.prototype.READY_STATE_UNINITIALIZED = 0;
HttpRequest.prototype.READY_STATE_LOADING       = 1;
HttpRequest.prototype.READY_STATE_LOADED        = 2;
HttpRequest.prototype.READY_STATE_INTERACTIVE   = 3;
HttpRequest.prototype.READY_STATE_COMPLETED     = 4;

// Define properties.
HttpRequest.prototype.successCallback = null;
HttpRequest.prototype.failureCallback = null;
HttpRequest.prototype.url             = null;
HttpRequest.prototype.username        = null;
HttpRequest.prototype.password        = null;
HttpRequest.prototype.requestHeaders  = new Array();
HttpRequest.prototype.status          = null;
HttpRequest.prototype.statusText      = null;
HttpRequest.prototype.responseXML     = null;
HttpRequest.prototype.responseText    = null;

// Define methods.
HttpRequest.prototype.abort                 = HttpRequestAbort;
HttpRequest.prototype.setRequestHeader      = HttpRequestSetRequestHeader;
HttpRequest.prototype.clearRequestHeaders   = HttpRequestClearRequestHeaders;
HttpRequest.prototype.get                   = HttpRequestGet;
HttpRequest.prototype.post                  = HttpRequestPost;
HttpRequest.prototype.initiateRequest       = HttpRequestInitiateRequest;
HttpRequest.prototype.getResponseHeader     = HttpRequestGetResponseHeader;
HttpRequest.prototype.getAllResponseHeaders = HttpRequestGetAllResponseHeaders;

//=============================================================================
// Contructor function.
//=============================================================================
function HttpRequest()
{
  // Create the appropriate HttpRequest object for the browser.
  this.xmlHttpRequest = null;

  if (window.XMLHttpRequest != null) {
    this.xmlHttpRequest = new window.XMLHttpRequest();
  } else if(window.ActiveXObject != null) {
    // Must be IE, find the right ActiveXObject.
    var success = false;
    for (var i = 0; i < HttpRequest.prototype.MS_PROGIDS.length && !success; i++) {
      try {
        this.xmlHttpRequest = new ActiveXObject(HttpRequest.prototype.MS_PROGIDS[i]);
        success = true;
      }
      catch (ex){}
    }
  }

  // If we couldn't create one, display an error and exit
  if (this.xmlHttpRequest == null) {
    alert("Error in HttpRequest():\n\nCannot create an XMLHttpRequest object.");
    return;
  }
}

//=============================================================================
// Methods.
//=============================================================================

function HttpRequestAbort() {
  this.xmlHttpRequest.abort();
}

function HttpRequestSetRequestHeader(name, value) {
  // If the header name already exists, replace the value.
  for (var i = 0; i < this.requestHeaders.length; i++) {
    var pair = this.requestHeaders[i].split("\n");
    if (pair[0].toLowerCase() == name.toLowerCase()) {
  	  this.requestHeaders[i] = name + "\n" + value;
  	  return;
  	}
  }

  // Otherwise, add it as a new item.
  var n = this.requestHeaders.length;
  this.requestHeaders.push(name + "\n" + value);
}

function HttpRequestClearRequestHeaders() {
  this.requestHeaders = new Array();
}

function HttpRequestGet() {
  this.initiateRequest("GET", null);
}

function HttpRequestPost(data) {
  this.initiateRequest("POST", data);
}

function HttpRequestGetResponseHeader(name) {
  return this.xmlHttpRequest.getResponseHeader(name);
}

function HttpRequestGetAllResponseHeaders() {
  return this.xmlHttpRequest.getAllResponseHeaders();
}

//=============================================================================
// Internal method to make the actual request.
//=============================================================================
function HttpRequestInitiateRequest(method, data) {
  // Clear all response fields.
  this.status       = null;
  this.statusText   = null;
  this.responseText = null;
  this.responseXML  = null;

  // Set up the callback functions.
  var refObj = this;
  this.xmlHttpRequest.onreadystatechange = function() {
		refObj.readyState = refObj.xmlHttpRequest.readyState
		if (refObj.readyState == HttpRequest.prototype.READY_STATE_COMPLETED) {
		  refObj.status       = refObj.xmlHttpRequest.status;
		  refObj.statusText   = refObj.xmlHttpRequest.statusText;
		  refObj.responseText = refObj.xmlHttpRequest.responseText;
		  refObj.responseXML  = refObj.xmlHttpRequest.responseXML;
		  if (refObj.status == 200) {
			  if (refObj.successCallback != null)
			    refObj.successCallback(refObj);
  		  } else {
	  		  if (refObj.failureCallback != null)
			    refObj.failureCallback(refObj);
		  }
       }
  }

  // Initialize the request.
  var url = this.url;
  if (this.queryString != null)
    url = url + "?" + this.queryString;
  this.xmlHttpRequest.open(method, url, true, this.username, this.password);

  // Set request headers (this must be done after the request is opened).
  for (var i = 0; i < this.requestHeaders.length; i++) {
    var pair = this.requestHeaders[i].split("\n");
    this.xmlHttpRequest.setRequestHeader(pair[0], pair[1]);
  }

  // Start the request, passing any POST data.
  this.xmlHttpRequest.send(data);
}