/**
 * Handle XML / AJAX requests without reloading a page.
 * 
 * @file     XmlHttp.js
 * @purpose  Provides controlled access to an AJAX query/response.
 * @date     2008-10-23 10:43 HST
 * @author   Paul Reuter
 * @version  1.1
 * @copyright
 *              Regents of the University of California
 *                       All Rights Reserved
 */


/**
 * An object that handles synchronous and asynchronous data requests from
 *  a server, via a URL.  The protocol is always HTTP, and an optimal 
 *  XMLHttp object will be used per browser.
 *
 * @constructor
 * @return {Object} A new XmlHttp() object.
 */
function XmlHttp(mime) {
  this.http_request = null; // the client-specific XMLHttpRequest object.
  this.sentWarning = 0; // semiphore
  this.initialize(mime);
}


/**
 * Initialization of the http_request object via XHMLHttpRequest()
 *
 * @private
 * @return {boolean} success or failure.
 */
XmlHttp.prototype.initialize = function(mime) { 
  if (window.XMLHttpRequest) { // Mozilla, Safari,...
    this.http_request = new XMLHttpRequest();
    if( typeof(mime) != "undefined" ) { 
      if(this.http_request.overrideMimeType) {
        this.http_request.overrideMimeType(mime);
      }
    }

  } else if (window.ActiveXObject) { 
    try {
      this.http_request = new ActiveXObject("Msxml2.XMLHTTP");
    } catch (e) {
      try {
        this.http_request = new ActiveXObject("Microsoft.XMLHTTP");
      } catch (e) {}
    }
  }
  if (!this.http_request) {
    alert('Giving up :( Cannot create an XMLHTTP instance');
    return false;
  }
  return true;
}; // END: function initialize();


/**
 * Make an HTTP GET request.
 *
 * @public
 * @param {string} url The URL to download.
 * @param {boolean} async Flag indicating whether to process asyncroniously
 * @param {function} func A callback function taking (data,code).
 * @return {void}
 */
XmlHttp.prototype.request = function(url,async,func) {
  async = (typeof(async)=="undefined" || !async) ? false : true;
  var xmlHttp = this.http_request;
  xmlHttp.open('GET', url, async);
  xmlHttp.send(null);
  if( async ) { 
    xmlHttp.onreadystatechange = function() {
      if(xmlHttp.readyState==4) {
        if( typeof(func)!="undefined" ) { 
          func(xmlHttp.responseText,xmlHttp.status);
        }
        return xmlHttp.responseText;
      }
    }
  } else {
    this.xml = xmlHttp.responseXML;
    if( typeof(func)!="undefined" ) { 
      func(xmlHttp.responseText,xmlHttp.status);
    }
    return xmlHttp.responseText;
  }
}; // END: function request(url,async,func);


/**
 * Used to request documents in their incomplete form.  This can be used
 *   for true AJAX.
 * @public
 * @param {string} url The URL of the document to fetch
 * @param {function} func A callback function executed whenever the requested
 *   state is active.
 * @param {int} state The readyState to watch for (default: 3)
 * @return {void}
 */
XmlHttp.prototype.interact = function(url,func,state) { 
  state = (!state) ? 3 : state;
  
  if( typeof(func) != "function" ) { 
    return false;
  }
  var xmlHttp = this.http_request;
  xmlHttp.onreadystatechange = function() {
    if(xmlHttp.readyState==state) {
      if( navigator.appVersion.indexOf("MSIE") < 0 || state == 4 ) {
      // if IE or state == 4, normal behaviour
        func(xmlHttp.responseText,xmlHttp.status);
      } else { 
      // else browser is IE and state not complete
        // func(xmlHttp.responseStream,xmlHttp.status);
        if( !this.sentWarning ) { 
          alert("Unfortunately, IE is currently not supported, though we are trying.\r\nPlease try Firefox instead.");
          this.sentWarning = true;
        }
      }
    }
  }
  xmlHttp.open('GET', url, true);
  xmlHttp.send(null);
}; // END: function interact(url,func,state)


/**
 * Closes an interactive session.
 *
 * @public
 */
XmlHttp.prototype.close = function() { 
  this.http_request.abort();
  this.http_request = null;
  this.initialize();
}; // END: function close()


/**
 * Parses an xml document and returns a dom object.
 *
 * @public
 * @param {string} a An XML string.
 * @return {Object} A dom representation of the XML.
 */
XmlHttp.prototype.parse = function(a) { 
  a = (!a) ? this.http_request.responseText : a;
  if(typeof ActiveXObject!="undefined"&&typeof GetObject!="undefined") {
    var b=new ActiveXObject("Microsoft.XMLDOM");
    b.loadXML(a);
    return b;
  }
  if(typeof DOMParser!="undefined") {
    var b = (new DOMParser).parseFromString(a,"text/xml");
    return b;
  }
  var doc = document.createElement("div");
  doc.innerHTML = a;
  return doc;
}; // END: function parse(a);
