// File: utd.js
//
// Description: The global UTD object and UTD.util, which contains general utility methods.
// Since this contains the global UTD object it should be included before all other .js files.

/**
 * Creates the global UTD object if it is not already defined.
 */
if (typeof UTD == "undefined") {
  var UTD = {};
}

/**
 * Creates one or more namespaces if they do not exist, returning the last one 
 * created.  A namespace is specified as a string with "." separating the 
 * components of the namespace, similar to a Java package.  Unlike Java, UTD 
 * namespaces are hierarchical.  The leading "UTD" can be included or omitted.
 * Some examples:
 * <pre>
 * UTD.namespace("patient");
 * UTD.namespace("UTD.patient.storefront");
 * </pre>
 * The first example creates and returns the "patient" namespace.  The second creates
 * the "storefront" namespace in the "patient" namespace, creating the "patient" namespace if
 * it does not exist.
 */
UTD.namespace = function() {
  var a = arguments;
  var ns = null;
  var nss = null;
  var i, j;
  
  // Loop through all arguments.  Split each across periods to get all of the
  // namespaces in the namespace hierarchy.
  for (i = 0; i < a.length; i = i + 1) {
    nss = a[i].split(".");
    ns = UTD;

    // Loop through all of the namespaces in the hierarchy, creating namespaces
    // that do not exist.  Ignore UTD if it is included as the first 
    // namespace since it is implied.
    for (j = (nss[0] == "UTD") ? 1 : 0; j < nss.length; j = j + 1) {
      ns[nss[j]] = ns[nss[j]] || {};
      ns = ns[nss[j]];
    }
  }
  return ns;
};

/**
 * The util singleton, which contains general utility methods.
 */
UTD.namespace("util");
UTD.util = function() {
  var object = {};

  /**
   * Returns true if the browser is Opera, false otherwise.
   */
  object.isOPERA = function() {
    var ua = window.navigator.userAgent.toUpperCase();
    return (ua.indexOf("OPERA") == 0);
  };
  
  /**
   * Returns the top and left position of the specified element as an object with 'top' and 'left'
   * properties.  This function takes the scroll position into account, and thus will return the
   * top and left as the user currently sees the element.
   */
  object.getTopLeft = function(element) {
  	var top = 0, left = 0, e = element;
  	
  	// First determine the absolute top and left of the specified element taking into account 
  	// all of its parents.
  	do {
  		top += e.offsetTop || 0;
  		left += e.offsetLeft || 0;
  	} while (e = e.offsetParent);

  	// Next, take into account the scrolling of each parent to get the actual top and left
  	// within the current scroll position of the browser.
  	e = element;
  	do {
  		if (!UTD.util.isOPERA() || (e.tagName && (e.tagName.toUpperCase() == 'BODY'))) {
  			top -= e.scrollTop || 0;
  			left -= e.scrollLeft || 0;
  		}
  	} while (e = e.parentNode);
  		
  	return {top: top, left: left};
  };

  /**
   * Repositions the specified element an offset from the fromElement.
   */
  object.repositionElement = function(element, fromElement, offsetLeft, offsetTop) {
    // Get the position of the from element.
    var topLeft = UTD.util.getTopLeft(fromElement);

    // Determine the left position of the element.  If the desired offset would position it 
    // such that it would be cut off the right of the page, then move it so it can be seen entirely.
    var left = topLeft.left + offsetLeft;
    var pageWidth = Math.floor(document.body.clientWidth);
    if (pageWidth < left + element.style.width) {
      left = pageWidth - element.style.width;
      left = left < 0 ? 0 : left;
    }
  	
    // Determine the top position of the element.  If the desired offset would position it 
    // such that it would be cut off the bottom of the page, then move it so it can be seen entirely.
    var top = topLeft.top + offsetTop;
    var pageHeight = Math.floor(document.body.clientHeight);
    if (pageHeight < top + element.style.height) {
      top = pageHeight - element.style.height;
      top = top < 0 ? 0 : top;
    }
    
    element.style.left = left;
    element.style.top = top;
  };

  return object;
}(); // UTD.util
