/**
 * Wrapper class for the XMLHttpRequest object
 */
function Ajax() 
{  
  this.req            = null;
  this.url            = null;
  this.method         = 'GET';
  this.async          = true;
  this.status         = null;
  this.statusText     = '';
  this.postData       = null;
  this.readyState     = null;
  this.responseText   = null;
  this.responseXML    = null;
  this.handleResp     = null;
  this.responseFormat = 'text';
  this.mimeType       = null;
  
  /**
   * Creates the browser specific request object.  
   */
  this.init = function() 
  {
    if (!this.req)
    {
      try
      {
        // Try to create the request object for Firefox, Safari, IE7, etc.
        this.req = new XMLHttpRequest();
      }
      catch (e)
      {
        try
        {
          // Try to create the request object for more recent versions of IE
          this.req = new ActiveXObject('MSXML2.XMLHTTP');          
        }
        catch (e)
        {
          try
          {
            // Try to create the request object for older versions of IE
            this.req = new ActiveXObject('Microsoft.XMLHTTP');            
          }
          catch (e)
          {
            // Could not create request object - not supported by browser            
          }
        }
      }
    }    
    return this.req;
  };
  
  /**
   * Sets the response's MIME type (used to override server Content-Type)
   */
  this.setMimeType = function(mimeType)
  {
    this.mimeType = mimeType;
  };
  
  /**
   * Sets a custom error handler
   */
  this.setErrHandler = function(funcRef)
  {
    this.handleErr = funcRef;
  };
  
  /**
   * Sets both successful and error requests to the same function
   */
  this.setHandlerBoth = function(funcRef)
  {
    this.handleResp = funcRef;
    this.handleErr  = funcRef;
  };  
  
  /**
   * Sets up a GET request
   * @param string url of request
   * @param string response handler
   * @param string format of response (optional; default = text)
   */
  this.doGet = function(url, handler, format)
  {
    this.url            = url;
    this.handleResp     = handler;
    this.responseFormat = format || 'text';
    this.doReq();
  };   
  
  /**
   * Sets up a POST request
   * @param string url of request
   * @param string POST data
   * @param string response handler
   * @param string format of response (optional; default = text)
   */
  this.doPost = function(url, postData, handler, format)
  {
    this.method         = 'POST'; 
    this.url            = url;
    this.postData       = postData;
    this.handleResp     = handler;
    this.responseFormat = format || 'text';       
    this.doReq();
  };    
  
  /**
   * Initializes the request object and prepares it to make an HTTP request.
   */
  this.doReq = function()
  {
    if (!this.init())
    {
      alert('It appears that your web browser does not support some of the functionality\n'
        + 'required to use this site. Please contact the Help Desk for assistance.\n\n'
        + 'Error: "Unable to initialize XMLHttpRequest object"');
        
      return;
    } 
    
    this.req.open(this.method, this.url, this.async);
    this.req.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
    
    // If this is a POST request - set proper header
    if (this.method == 'POST')
    {
      this.req.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
    }
    
    // Check if server Content-Type should be overridden
    if (this.mimeType)
    {
      try
      {
        this.req.overrideMimeType(this.mimeType);
      }
      catch (e)
      {
        // Could not override MIME type - IE6 or Opera in use
      }
    }
    
    // Fix loss-of-scope in inner function assigned to event handeler
    var self = this;
    this.req.onreadystatechange = function()
    {
      var resp = null;      
      if (self.req.readyState == 4)
      {
        switch (self.responseFormat)
        {
          case 'text':
          {
            resp = self.req.responseText;
            break;
          }
          case 'xml':
          {
            resp = self.req.responseXML;
            break;
          }
          case 'object':
          {
            resp = self.req;
            break;
          }
        }
        
        if (self.req.status >= 200 && self.req.status <= 299)
        {
          self.handleResp(resp);
        }
        else
        {
          self.handleErr(resp);
        }        
      }
    };
    this.req.send(this.postData);
  };     
  
  /**
   * Default error handler
   */
  this.handleErr = function()
  {
    var errWin;
    
    try
    {
      errWin = window.open('', 'Request Error');
      errWin.document.body.innerHTML = this.responseText;
    }
    catch (e)
    {
      alert('An error occurred, but the error message cannot be '
        + 'displayed. This is probably because of your browser\'s '
        + 'pop-up blocker.\n'
        + 'Please allow pop-ups from this web site if you want to '
        + 'see the full error messages.\n'
        + '\n'
        + 'Status Code: ' + this.req.status + '\n'
        + 'Status Description: ' + this.req.statusText);
    }
  };
  
  /**
   * Aborts an active request
   */
  this.abort = function()
  {
    if (this.req)
    {
      this.req.onreadystatechange = function() {};
      this.req.abort();
      this.req = null;
    }
  }; 
}
  