function XHReq(handler)
{
  if (handler != null)
  {
    this.handler = handler;
    this.method = "get";
    this.data = "";
    this.url = "";
    this.contentTypePost = null;
    this.asyncFlag = null;
    this.userName = null;
    this.password = null;
    this.serial = XHReq.reqSerial++;
    this.req = null;
    this.nextReq = null;
    this.handled = false;
    this.onTimeout = null;
  }
}
new XHReq(null);

XHReq.reqSerial = 1;
XHReq.reqs = null;
XHReq.timeout = 15000; // 15 seconds
XHReq.reqAsynch = true;

XHReq.errMsgNoReq = "This browser is incompatible.  You will need to upgrade to view this content.";

XHReq.contentTypePost = 'application/x-www-form-urlencoded';


//
// Request list funcs
  XHReq.addReq = function(req)
  {
    if (XHReq.reqs == null)
    {
      XHReq.reqs = req;
    }
    else
    {
      XHReq.reqs.addReq(req);
    }
  }
  
  XHReq.getReq = function(serial)
  {
    if (XHReq.reqs == null)
    {
      return null;
    }
    else
    {
      return XHReq.reqs.getReq(serial);
    }
  }
  
  XHReq.delReq = function(serial)
  {
    if (XHReq.reqs != null)
    {
      if (XHReq.reqs.serial == serial)
      {
        XHReq.reqs = XHReq.reqs.nextReq;
      }
      else
      {
        XHReq.reqs.delReq(serial);
      }
    }
  }
  

  XHReq.prototype.addReq = function(req)
  {
    if (this.nextReq == null)
    {
      this.nextReq = req;
    }
    else
    {
      this.nextReq.addReq(req);
    }
  }
  
  XHReq.prototype.getReq = function(serial)
  {
    if (this.serial == serial)
    {
      return this;
    }
    else if (this.nextReq != null)
    {
      return this.nextReq.getReq(serial);
    }
    else
    {
      return null;
    }
  }
  
  XHReq.prototype.delReq = function(serial)
  {
    var req = this.nextReq;
    if (req == null)
    {
      return;
    }
    else if (req.serial == serial)
    {
      this.nextReq = req.nextReq;
      req.nextReq = null;
    }
    else
    {
      req.delReq(serial);
    }
  }
  


//
// Request constructor wrapper
  XHReq.newReq = function()
  {
    var req;
    if(window.XMLHttpRequest)
    {
      try
      {
  	    req = new XMLHttpRequest();
      }
      catch(e)
      {
  	    req = null;
      }
    }
    else if(window.ActiveXObject)
    // branch for IE/Windows ActiveX version
    {
      try
      {
        req = new ActiveXObject("Msxml2.XMLHTTP");
      }
      catch(e)
      {
        try
        {
          req = new ActiveXObject("Microsoft.XMLHTTP");
        }
        catch(e)
        {
          req = null;
        }
  	  }
    }
    
    if (req == null)
    {
      alert(XHReq.errMsgNoReq);
    }
    return req;
  }
  
  
  
  if (XHReq.newReq() != null)
  /* Define methods */
  {
    XHReq.prototype.request = function()
    {
      this.handled = false;
      if ((!XHReq.reqAsynch) && (XHReq.reqs != null))
      {
        if (this.nonAsynchHandler != null)
        {
          this.nonAsynchHandler();
        }
        return;
      }
      this.req = XHReq.newReq();
      this.req.onreadystatechange = XHReq.onreadystatechange;
  
      if ((this.asyncFlag == null) &&
          (this.userName == null) &&
          (this.password == null))
      {
        try
        {
          this.req.open(this.method, this.url);
        }
        catch (e)
        {
          document.write(e);
          return;
        }
      }
      else if ((this.userName == null) &&
               (this.password == null))
      {
        this.req.open(this.method, this.url, this.asyncFlag);
      }
      else if (this.password == null)
      {
        this.req.open(this.method, this.url, this.asyncFlag, this.userName);
      }
      else
      {
        this.req.open(this.method, this.url, this.asyncFlag, this.userName, this.password);
      }
  
      if (this.method == 'post')
      {
        this.req.setRequestHeader('Content-Type', (this.contentTypePost != null) ? this.contentTypePost : XHReq.contentTypePost);
      }

      XHReq.addReq(this);
      setTimeout("XHReq.reqTimeout("+this.serial+");", XHReq.timeout);

      try
      {
        this.req.send(this.data);
      }
      catch (e)
      {
        document.write(e);
        return;
      }
  
      return false;
    }
    
    XHReq.onreadystatechange = function()
    {
      var req, i, serials = new Array();
      for (req = XHReq.reqs; req != null; req = req.nextReq)
      {
        if (req.onreadystatechange())
        {
          serials.push(req.serial);
        }
      }
      
      for (i = 0; i < serials.length; i++)
      {
        XHReq.delReq(serials[i]);
      }
    }
  
    XHReq.prototype.onreadystatechange = function()
    {
      if (this.handled)
      {
        return;
      }

      if (this.req.readyState == 4)
      {
        this.handled = true;
        this.handler.onreadystatechange(this.req);
        return true;
      }
      else
      {
        this.handler.onreadystatechange(this.req);
      }
      return false;
    }
    
    XHReq.reqTimeout = function(serial)
    {
      var req;
      if (req = XHReq.getReq(serial))
      {
        if (req.handler.ontimeout != null)
        {
          req.handler.ontimeout();
        }
        else
        {
          if (req.onTimeout)
          {
            req.onTimeout();
          }
        }
        XHReq.delReq(serial);
      }
    }
    
  }
  else
  /* Define empty methods */
  {
    XHReq.prototype.request = function(tgtState)
    {
      alert(XHReq.errMsgNoReq);
      return false;
    }
  }