/*
Summary:  BjaxXlstEngine is a library of Bjax functions.
          For use when needing initiating cross browser XSLT transformations.
Remarks:  Bjax is Ajax plus XSLT, including XPATH, functions
          initiated from browser script.
*/


function Ajaxer() {
  /*************
    Private
   *************/
  var HttpRequestOrDom = null;
  var ReadyStateCode = new Object();
  var RequestIndex = Ajaxer.NumberOfRequests++;

  // The object has been created, but not initialized
  // (the open method has not been called).
  ReadyStateCode.Unitialized = 0;

  // The object has been created, but the send method has not been called.
  ReadyStateCode.Loading = 1;

  // The send method has been called, but the status and headers
  // are not yet available.
  ReadyStateCode.Loaded = 2;

  // Some data has been received. Calling the responseBody and responseText
  // properties at this state to obtain partial results will return an error,
  // because status and response headers are not fully available.
  ReadyStateCode.Interactive = 3;

  // All the data has been received, and the complete data is available in
  // the responseBody and responseText properties.
  ReadyStateCode.Completed = 4;

  // http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html
  var HttpStatusCode = new Object();

  HttpStatusCode.Ok = 200;  // The request has succeeded

  var OnSuccessFunction = null;

  // Within private functions you can refer to public members.
  var Self = this;

  // Loads the XMLDocument object (Msxml2.DOMDocument or Gecko XMLDocument)
  // into this object, Ajaxer.
  function loadXmlDomIntoThis() {
      Self.responseXML = HttpRequestOrDom;
      //Self.responseText = HttpRequestOrDom.text;
      Self.loadBasis += "loadXmlDomIntoThis; ";
      OnSuccessFunction();
  }

  function onReadyStateChange() {
    var out = "";
     if (HttpRequestOrDom.readyState == ReadyStateCode.Completed) {
      if (HttpRequestOrDom.status == HttpStatusCode.Ok) {
        // via xmlHTTPRequest
        Self.responseXML = HttpRequestOrDom.responseXML;
        //Self.responseText = HttpRequestOrDom.responseText;
        this.loadBasis += "responseXML; ";
        OnSuccessFunction();
      } else if (HttpRequestOrDom.parseError.errorCode === 0) {

        loadXmlDomIntoThis();
      } else if (HttpRequestOrDom.parseError.errorCode !== 0) {
        out = "There was a problem parsing the DOM doc. \n";
        out += "Url: " + this.url + "\n";
        out += "Reason: " + HttpRequestOrDom.parseError.reason;
        alert(out);
      } else {
        out = "HTTP Request Status Code: " + HttpRequestOrDom.status + "\n";
        out += "HTTP Request Status Text: " + HttpRequestOrDom.statusText;
        alert(out);
      } // if (HttpRequestOrDom.status
    } // if ((HttpRequestOrDom.readyState
  }

  /*************
    Public
   *************/
  //this.readyStateCode = ReadyStateCode;
  //this.httpStatusCode = HttpStatusCode;

  this.responseXML = null;
  //this.responseText = null;
  this.loadBasis = "Start. ";
  this.url = null;

  /*
  Params:
        urlOrXmlDomDoc: a string url that points to the xml file
                      eg "http://www.example.org/fun.xml"
                      "data/fun.xml";
                      OR the document node of a previously loaded XML file.
        onSuccessFunction. A pointer to a callback function.
            Must be of a specific format:
            eg onSuccess(xmlDoc) { ... } where xmlDoc is the
            the XML document returned by XMLHTTPrequest.repsonseXML
        isStylesheet (optional) Default false
            if the document is going to be used as a stylesheet then
            in IE 6.0 (MSXML 4.0) async must be false. See
            Microsoft XML Core Services (MSXML) 4.0 - XSLT Developer's Guide
            > Increasing Performance by Using the XSLTemplate Object  */
  this.load = function(urlOrXmlDomDoc, onSuccessFunction, isStylesheet) {
    //if (urlOrXmlDomDoc == "booksTable.xslt") stop;
    if (isStylesheet === null) {isStylesheet = false;}

    if (!isBeingServed()) { return false; }
    OnSuccessFunction = onSuccessFunction;    
    if (typeof urlOrXmlDomDoc == "string") {
      this.url = urlOrXmlDomDoc;
      if (window.XMLHttpRequest) { // Mozilla, Safari,...
        HttpRequestOrDom = new XMLHttpRequest();
        /* Some versions of some Mozilla browsers won't work properly
        if the response from the server doesn't have an
        XML mime-type header */
        if (HttpRequestOrDom.overrideMimeType) {
          HttpRequestOrDom.overrideMimeType('text/xml');
        }
        this.loadBasis += "Gecko XMlHttpRequest; ";
      } else if (window.ActiveXObject) { // IE
        HttpRequestOrDom = new ActiveXObject(MSProgId);
        this.loadBasis += "MS ActiveXObject('" + MSProgId + ");";
      } else {
          alert('Your browser does not support the creation of an XMLHTTP instance nor Msxml2.DOMDocument.');
          return false;
      }
      try {
    	  // if req.method=="GET"
    	  // Prevent cacheing of url when using the GET method
    	  //var searchString = writeToSearchString("ajaxRequestUniqueId", new Date().getTime() + RequestIndex , searchString);
    	  //urlOrXmlDomDoc += searchString;
        // open( method, urlOrXmlDomDoc, async )
        if (typeof HttpRequestOrDom.open != "undefined") {
          HttpRequestOrDom.onreadystatechange = onReadyStateChange;
          HttpRequestOrDom.open('GET', urlOrXmlDomDoc, true);
          HttpRequestOrDom.send(null);
          this.loadBasis += "send; ";
        } else if (typeof HttpRequestOrDom.load != "undefined") {
          this.loadBasis += "load (not XHR); ";
          // Using IE MSXML
          if (isStylesheet) {
            HttpRequestOrDom.async = false;
            this.loadBasis += "async false; ";
          } else {
            HttpRequestOrDom.async = true;
            this.loadBasis += "async true; ";
            HttpRequestOrDom.onreadystatechange = onReadyStateChange;
          }
          HttpRequestOrDom.resolveExternals = false;
          HttpRequestOrDom.load(urlOrXmlDomDoc);
          // If we are loading a stylesheet synchronously then call loadXmlDomIntoThis
          // Straight away, there is no onReadyStateChange.
          if (isStylesheet) {
            loadXmlDomIntoThis();
          }
        } else {
          throw new Error("Your browser doesn't support HTTPRequest.open nor MS Dom.load ");
        }
      } catch (error) {
        var errorMessage = "There was a problem retrieving the XML data. ";
            errorMessage += "\nFirst, Try running from a web server, eg http://localhost, rather than file system.\n";
            errorMessage += "XMLHttpRequest Error Message: \n";
            errorMessage += "Url: " + urlOrXmlDomDoc + "\n";
            errorMessage += ((HttpRequestOrDom.statusText === "") ? "" : "statusText: " + HttpRequestOrDom.statusText) + "\n";
            errorMessage += "Error Message: " + error.message;
          // Allow calling procedure to deal.
          throw new Error(errorMessage);
      }
    } else if (typeof urlOrXmlDomDoc == "object") {
      this.url = urlOrXmlDomDoc.url;  // for IE only.
      HttpRequestOrDom = urlOrXmlDomDoc;
      this.loadBasis += "Assign Existing DOM object; ";
      loadXmlDomIntoThis();
    } else {
      throw new Error("urlOrXmlDomDoc can only be a string or an XmlDomDoc object but was " + typeof urlOrXmlDomDoc);
    }
    return true;
  }; // load
} // Ajaxer

// Static Members
Ajaxer.NumberOfRequests = 0;

