function ContentLoader(url,onload,onerror) {
  this.READY_STATE_UNINITIALIZED=0;
  this.READY_STATE_LOADING=1;
  this.READY_STATE_LOADED=2;
  this.READY_STATE_INTERACTIVE=3;
  this.READY_STATE_COMPLETE=4;

  this.url = url;
  this.calling_obj = null;
  this.req = null;
  this.req_type = "get";
  this.onload = (onload) ? onload : null;
  this.onerror = (onerror) ? onerror : this.defaultError;
  this.results = null;
  this.serialized = false;

  if (typeof ContentLoader._initialized == "undefined") {

    ContentLoader.prototype.setUrl = function (url) {
      this.url = url;
    };

    ContentLoader.prototype.setCallObj = function (calling_obj) {
      this.calling_obj = calling_obj;
    };

    ContentLoader.prototype.setReqType = function (req_type) {
      this.req_type = req_type;
    };

    ContentLoader.prototype.setReq = function () {
      if (window.XMLHttpRequest) {
        this.req = new XMLHttpRequest();
      } else if (window.ActiveXObject) {
        this.req = new ActiveXObject("Microsoft.XMLHTTP");
      }
    };

    ContentLoader.prototype.setSerialized = function (myBool) {
      this.serialized = myBool;
    };

    ContentLoader.prototype.loadXMLDoc = function (url,values) {
      this.setReq();
      url = (url) ? url : this.url;
      if (this.req) {
        try {
          var loader = this;
          this.req.open(this.req_type,url,true);
          this.req.onreadystatechange = function() {
            loader.onReadyState.call(loader);
          }
          if (this.req_type=="post" || this.serialized) {
            this.req.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
          }
          if (this.req_type=="post" && values) {
            this.req.send(this.encodeFormData(values));
          } else {
            this.req.send(null);
          }
        } catch (err) {
          this.onerror.call(this);
        }
      }
    };

    ContentLoader.prototype.onReadyState = function () {
      var req = this.req;
      var ready = req.readyState;
      if (ready == this.READY_STATE_COMPLETE) {
        try {
          var httpStatus = req.status;
          if (httpStatus == 200 || httpStatus == 0) {
            if (this.onload) {
              this.onload.call(this);
            } else {
              if (this.req.responseXML.documentElement) {
                this.results = this.req.responseXML.documentElement;
              } else {
                this.results = this.req.responseText;
              }
            }
          } else {
            this.onerror.call(this);
          }
        } catch (e) {
          // not worrying about it
          // error was being generated when ajax call still in progress, but link was clicked
          // to some other page.
        }
      }
    };

    ContentLoader.prototype.defaultError = function () {
      alert("error fetching data!"
        +"\n\nreadyState:"+this.req.readyState
        +"\nstatus: "+this.req.status
        +"\nheaders: "+this.req.getAllResponseHeaders());
    };

    ContentLoader.prototype.encodeFormData = function (data) {
      var pairs = [];
      var regexp = /%20/g; // to match encoded space

      for (var name in data) {
        var value = data[name].toString();
        var pair = encodeURIComponent(name).replace(regexp,"+") + '=' +
                   encodeURIComponent(value).replace(regexp,"+");
        pairs.push(pair);
      }

      return pairs.join('&');
    }

    ContentLoader._initialized = true;
  }
}

