/* rpc-combined: sets up object for XMLHttprequest method of rpc
 * or iframe method
 *
 * functions
 *    addEvent (optional): to assign handler to window.onload event
 *    createHTTPObj: controls creating an XMLHttprequest object or hidden iframe
 *    createXMLHttp: creates the XMLHttprequest object
 *    createExtIframe: calls routine to create the hidden iframe and extends the iframe
 *    createIframe: creates the hidden iframe
 *    callb: method used by iframe page to callback when loaded
 *    openMethod: compatibility method, writes url to iframe
 *    sendMethod: compatibility method, writes url to custom property of iframe
 *
 *    do_rpc: the event handler for user activity that starts rpc
 *    formatURL: formats url adding search string and a flag
 *    form2query: creates search string from a form
 */
var HTTPObj = null;
var HTTPtarget = null; // because IE's activeX can't be extended

if (!HTTPObj)
  addEvent(window, "load", createHTTPObj);

/*
 * The demonstration uses an add/remove event library available at
 * http://lawrence.ecorp.net/inet/samples/js-addevent1.shtml or you can
 * uncomment and use the following function
 */
function addEvent(obj, event_name, fnc, assigment_only) {
  var rtrn = true;
  if (typeof obj == "undefined") {
    return false;
  }

  if (obj.attachEvent) {
    obj.attachEvent("on" + event_name, fnc);
  } else if (obj.addEventListener) {
    try {
      obj.addEventListener(event_name, fnc, false);
    } catch (e) {
      obj["on" + event_name] = fnc;
    }
  } else {
    obj["on" + event_name] = fnc;
  }
  return rtrn;
}// eof addEvent

function createHTTPObj() {

  if (!HTTPObj && !(window.console && window.console.firebug)) {
    createXMLHttp();
  }

  if (!HTTPObj) {
    createExtIframe();
  }
}

function createXMLHttp() {
  /* Creates an XMLHttp object */
  var httpReq = HTTPObj;
  if (!httpReq) {
    if (typeof window.XMLHttpRequest != 'undefined') {
      // branch for native XMLHttpRequest object - Mozilla
      try {
        httpReq = new XMLHttpRequest();
      } catch (e) {
        httpReq = null;
      }
    } else if (typeof window.ActiveXObject != 'undefined') {
      // branch for IE/Windows ActiveX version
      try {
        httpReq = new ActiveXObject("Msxml2.XMLHTTP");
      } catch (e) {
        try {
          httpReq = new ActiveXObject("Microsoft.XMLHTTP");
        } catch (e) {
          httpReq = null;
        }
      }// catch
    } else if (typeof window.createRequest) {
      /*
       * For ICEbrowser -- untested. per their site
       * http://support.icesoft.com/jive/entry.jspa?entryID=471&categoryID=21
       * There are a number of restrictions on the implementation and it only
       * does get
       */
      try {
        httpReq = window.createRequest();
      } catch (e) {
        httpReq = null;
      }
    }// end if-else
  }// end if

  if (httpReq && typeof httpReq.readyState == "number") {
    try {
      httpReq.backbutton = false;
      httpReq.RPCType = "ajaxg";
      httpReq.targetId = "";
      httpReq.nexturl = "";
    } catch (e) {
      /* We can't extend active X objects */
    }
  } else {
    httpReq = null;
  }
  HTTPObj = httpReq;
}// eof createHTTPObj

function createExtIframe() {

  /* Test if Iframe needs to be created */
  var iframeObj = document.getElementById("rs-iframe");
  if (!iframeObj) {
    iframeObj = createIframe();
  }

  /* Extend the iframe */
  if (iframeObj) {
    iframeObj.backbutton = false;
    iframeObj.RPCType = "iframe2";
    iframeObj.targetId = "";
    iframeObj.onreadystatechange = "";
    try {
      iframeObj.readyState = 0;
    } catch (e) {
      /*
       * IE already has this property as a read only text with the values of
       * uninitialized, loading, loaded, interactive, and complete so we just
       * catch the error and go on.
       */
    }

    iframeObj.status = 0;
    iframeObj.nexturl = "";
    iframeObj.responseText = "";
    iframeObj.callBack = callb;
    iframeObj.open = openMethod;
    iframeObj.send = sendMethod;
    // iframeObj.window = getWindowHandle(iframeObj);
  }

  HTTPObj = iframeObj;

}// eof createHTTPObj

function getWindowHandle(iframeObj) {
  var iframeWin = null;

  /* Get handle to iframe window */
  if (iframeObj.contentWindow) { // IE5.5+, Mozilla, NN7
    iframeWin = iframeObj.contentWindow;
  } else if (iframeObj.contentDocument) { // NN6, Konqueror
    iframeWin = iframeObj.contentDocument.defaultView;
  } else if (iframeObj.Document) { // IE5
    iframeWin = iframeObj.Document.parentWindow;
  }

  return iframeWin;
}

function createIframe(i_FrameName) {

  if (!i_FrameName)
    i_FrameName = 'rs-iframe';

  /*
   * Routine to create hidden iframe Discovered that wrapping the iframe in a
   * div with display none works well in most, if not all, common browsers.
   * 
   * Note this test iframeObj.nodeType == "undefined" is to trap some browsers
   * that create a useless iframe. For example Konqueror 3.2 and earlier.
   */
  var iframeObj = null;
  try {
    // Create Iframe and put it at bottom of page
    var tmpFrame;
    // IE 6.0 fix using wrapper div with display none
    var tmpDiv = document.createElement("div");
    tmpDiv.setAttribute("id", "iframe-div");
    tmpFrame = document.createElement("iframe");
    tmpFrame.setAttribute("id", i_FrameName);
    tmpFrame.setAttribute("name", i_FrameName);

    if (typeof document.body.getAttribute("className") == 'string')
      tmpFrame.setAttribute("className", "hidden-frame");
    else
      tmpFrame.setAttribute("class", "hidden-frame");

    tmpDiv.appendChild(tmpFrame);
    document.body.appendChild(tmpDiv);

    if (typeof document.frames != "undefined") {
      /*
       * Required for IE 5 on Mac and throws error on IE 5.0 PC which we need to
       * branch to a different process.
       */
      iframeObj = document.frames[i_FrameName];
    }

    if (!iframeObj || typeof iframeObj.nodeType == "undefined") {
      /*
       * Most browsers yield null or good iframe reference above, but some
       * return an object with no properties so nodeType test.
       */
      iframeObj = document.getElementById(i_FrameName);
    }
  } catch (e) {
    /*
     * Hack to handle IE 5.0 on PC, which doesn't want to 'automate' adding an
     * iframe.
     * 
     * Reguired: 1. HTML string for iframe and NOT an element object. 2. use
     * iframe src attribute to load first RPC; otherwise only subsequent calls
     * work 3. A block container to hold iframe 4. Attach container and iframe
     * to any block inside body but NOT the body.
     */

    /*
     * Put iframe in container (innerHTML must be used) and append to any div in
     * page (this may exist from above)
     */
    var iframeHTML = '<iframe id="' + i_FrameName + '" name="' + i_FrameName
        + '" class="hidden-frame"><\/iframe>';
    if (!document.getElementById("iframe-div")) {
      tmpDiv = document.createElement("div");
      tmpDiv.setAttribute("id", "iframe-div");
      tmpDiv.innerHTML = iframeHTML;
      document.getElementsByTagName('DIV')[0].appendChild(tmpDiv);
    } else {
      document.getElementById("iframe-div").innerHTML = iframeHTML;
    }
    iframeObj = document.getElementById(i_FrameName);
  }
  /* How did we do? Return if alternate page should load */
  if (iframeObj && typeof iframeObj.nodeType == "undefined") {
    iframeObj = null;
  }
  return iframeObj;
}// eof createIframe

function callb(txt) {
  this.status = 200;
  this.responseText = txt;

  try {
    this.readyState = 4;
  } catch (e) {
    /*
     * IE already has this property for iframes as a read only text with the
     * values of uninitialized, loading, loaded, interactive, and complete so we
     * just catch the error and go on.
     */
  }
  this.onreadystatechange();
}// eof callb

function openMethod(method, url) {
  this.nexturl = url;
}// eof openMethod

function sendMethod() {
  /* IE 5.0 requires this for each RPC */
  this.window = getWindowHandle(this);

  if (this.window) {
    if (this.backButton) {
      this.src = this.nexturl;
    } else {
      this.window.location.replace(this.nexturl);
    }
  }
}// eof sendMethod

function do_rpc(url, target_elem, data, handler) {
  /*
   * 1. test if the browser has the necessary features for the RPC and to handle
   * the response data. 2. Do any preprocessing for the URL e.g. assembling a
   * query string from form fields 3. Make call to server 4. return if
   * consolation/alternate page in form action or link's href should load
   */
  var doDefault = true;
  if (HTTPObj) {
    /* Assign reference to block receiving results. */
    try {
      HTTPObj.targetId = target_elem;
    } catch (e) {
      /* for IE active X */
      HTTPtarget = target_elem;
    }

    // update iframe state for IE6 / non-activeX
    if (HTTPObj.RPCType == 'iframe2') {
      if (HTTPObj.readyState == 4)
        HTTPObj.readyState == 0;
      else
        HTTPObj.readyState == "";

      HTTPObj.status = 0;
      HTTPObj.responseText = '';
    }

    var formatedURL = formatURL(url, data); // for IE's activeX
    HTTPObj.open("GET", formatedURL, true);
    HTTPObj.onreadystatechange = handler;
    HTTPObj.send(null);
    doDefault = false;
  } else {
    doDefault = true;
  }
  return doDefault;
}// eof do_rpc

function getRPCType() {
  var RPCType = null;
  if (HTTPObj.RPCType) {
    RPCType = HTTPObj.RPCType;
  } else {
    /* For IE Active X */
    RPCType = "ajaxg";
  }
  return RPCType;
}// eof getRPCType

function formatURL(url, data) {
  /* Assemble query string and append to url */
  var type = "type=" + getRPCType();

  if (data) {
    switch (typeof data) {
      case "object":
        // Get string from form like method get
        if (data.tagName.toLowerCase() == "form") {
          url += form2query(data);
        }
        url += "&" + type;
        break;
      case "string":
        // formated string supplied
        if (!/^[?]/.test(data)) {
          data = '?' + data;
        }
        url += data + "&" + type;
        break;
      default:
        url += "?" + type; // use what is passed with url
    }
  } else {
    if (url.indexOf("?") == -1)
      url += "?" + type;
    else
      url += "&" + type;
  }
  return url;
}// eof formatURL

function form2query(frm) {
  /*
   * To string together fieldname value pairs from form elements with name
   * property set.
   * 
   * Format ?name=value&name=value ...
   */
  var qry = ""; // final query string
  var pair = "?"; // format one name/value pair
  var field; // form field being processed

  for ( var i = 0; i < frm.elements.length; i++) {

    field = frm.elements[i];

    if (typeof field.name != "undefined" && field.name != "") {

      switch (field.type) {
        case "select-one":
          pair += field.name + "=" + field.options[field.selectedIndex].value;
          break;
        case "radio":
        case "checkbox":
          if (field.checked) {
            pair += field.name + "=" + field.value;
          }
          break;
        default:
          pair += field.name + "=" + field.value;
      }

      if (pair.length > 1) {
        /*
         * Test in case first element is unchecked radio or checkbox
         */
        qry += pair;
        pair = "&";
      }
    }
  }
  return qry;
}// eof form2query

