// Very general useful things that help you manipulate the HTML DOM.
// Includes some overlap of prototype.js functionality.
// Parts of this script now assume prototype.js has been run already.
if ( ! window.$) {
    $ = function(id) { return document.getElementById(id); }
}
function addClassName(element, className) {
    if (window.Element && Element.addClassName) {
        Element.addClassName(element, className);
    } else {
        element.className = className;
    }
}
// wrapped because prototype chokes if element has no class
function hasClassName(element, className) {
  return element.className != null && Element.hasClassName(element, className);
}

// This is the preferred method for scheduling initialization and
// cleanup functions to run.
//
// The first argument should be a function to be run after the onload
// event fires. Components that use window elements should do setup
// in this function. Functions will be executed in the order that they
// were scheduled.
//
// The second argument should be a function that cleans up the effects
// of the component. (Free memory by nulling variable references, close
// server connections, etc.) These functions will be executed in the
// reverse of the order that they were pushed, so that the last component
// initialized is the first component cleaned. If no cleanup is required,
// the second argument can be left off.
window.schedule = function(onloadFunction, onunloadFunction) {
  if (onloadFunction != null) {
    this.onload_queue.push(onloadFunction);
  }
  if (onunloadFunction != null) {
    this.onunload_stack.push(onunloadFunction);
  }
}

// Provide onload queue for the window.
// Use window.onload_queue.push(foo) instead of window.onload = foo
// Queue is FIFO: functions will be executed in the order that they
// were pushed.
window.onload_queue = new Array();
window.originalOnload = window.onload;
window.onload = function(e) {
    for (var i = 0; i < this.onload_queue.length; i++) {
        this.onload_queue[i](e);
        this.onload_queue[i] = null;
    }
}
if (window.originalOnload) {
    window.onload_queue.push(window.originalOnload);
}

// Provide onunload queue for the window. Put all object cleanup here
// (most importantly, detach all circular references you created,
// or primitive browsers (including IE) will leak memory).
// Use window.onunload_stack.push(foo) instead of window.onunload = foo
// The stack is LIFO: functions will be executed in the reverse of the
// order that they were pushed, so that effects from onload are
// unraveled correctly.
window.onunload_stack = new Array();
window.originalOnunload = window.onunload;
window.onunload = function(e) {
  if (this.onunload_stack) {
    for (var i = this.onunload_stack.length - 1; i >= 0; i--) {
      this.onunload_stack[i](e);
      this.onunload_stack[i] = null;
    }
  }
}
if (window.originalOnunload) {
  window.onunload_stack.push(window.originalOnunload);
}

/**
 * Get the closest ancestor node of htmlElement which expresses the
 * class className. Returns null if there is no such ancestor.
 * Example:
 * <div class="example">
 *  <div class="container">
 *   <div class="wrapper">
 *    <div class="d" onclick="flash(classedElementContaining(this, "container"));">click</div>
 *   </div>
 *  </div>
 * </div>
 * ... this would flash the "container"-classed div.
 */
function classedElementContaining(htmlElement, className) {
  if (hasClassName(htmlElement, className)) { return htmlElement; }
  if (htmlElement.parentNode == null) { return null; }
  return classedElementContaining(htmlElement.parentNode, className);
}

/**
 * Sloppily set the contents of parentElement to childElement; this is
 * smart enough to replace only one pre-existing element within parentElement.
 * If parentElement has multiple children, only the first one will be
 * replaced by childElement. This is why we usually use this call with
 * parents that start out empty and are populated only by javascript.
 */
function setElementFirstChild(parentElement, childElement) {
  if (parentElement.hasChildNodes()) {
    parentElement.replaceChild(childElement, parentElement.firstChild);
  } else {
    parentElement.insertBefore(childElement, null);
  }
}

// I don't know what this function used to do, but it seems
// to have vanished, so I'm quickly rewriting it here:
function getXMLHttpRequest() {
  var req = null;
  try {
      req = new ActiveXObject("Msxml2.XMLHTTP");
  } catch (exc) {
      try {
          req = new ActiveXObject("Microsoft.XMLHTTP");
      } catch (exc2) {
          req = null;
      }
  }
  if (req == null && typeof XMLHttpRequest != "undefined") {
      req = new XMLHttpRequest();
  }
  return req;
}

//this code comes from http://xkr.us/articles/dom/iframe-document/
function getDocumentInIframe(iframeElement) {
  var oDoc = (iframeElement.contentWindow || iframeElement.contentDocument);
  if (oDoc.document) {
    oDoc = oDoc.document;
  }
  return oDoc;
}

// document fields tend to be read-only, so we use this low-tech method
// to copy an entire document into another window. It's similar to this:
// destinationFrame.location = sourceDocument.location
// with the important distinction that the document is completely rendered
// before the function returns.
//
// I'm not sure if this is to browser DOM spec, but when we document.write
// below, it clears the contents of the document before writing the new
// strings to it. Both IE6 and FF1.5 do this, even if an empty string is
// written. I previously had a call to set document.location = "about:blank" ,
// but it isn't necessary as long as the document.write call clears the
// document. Untested in FF1.0.
function copyDocumentElementToFrame(sourceDocument, destinationFrame) {
  var destinationDocument = getDocumentInIframe(destinationFrame);
  destinationDocument.open();
  destinationDocument.write("<HTML>");
  destinationDocument.write(sourceDocument.documentElement.innerHTML);
  destinationDocument.write("</HTML>");
  destinationDocument.close();
}


