/**
 * @file
 * @author Shannon M. Rause <shannon.rause@creativeflavor.com>
 * @version $Revision: 1.41 $
 * @version $Name: HUTDOGS_2010-06-29_24 $
 * @version $Id: Utils.js,v 1.41 2010/03/31 20:19:45 smr Exp $
 *
 * These files are copyrighted to Creative Flavor Inc. and are
 * subject to the terms of the applicable Service Agreement.
 * If no service agreement is available you must contact us at
 * legal@creativeflavor.com or 303-379-9450.
 * 
 * These files may be watermarked to ensure traceability.
 */
/**
 * Utils class.
 */
function Utils()
{
} // Utils

Utils.H_POSITION_AUTO         = 'auto';
Utils.H_POSITION_CENTER       = 'center';
Utils.H_POSITION_CENTER_MOUSE = 'center_mouse';
Utils.H_POSITION_LEFT_MOUSE   = 'left_mouse';
Utils.H_POSITION_NONE         = 'none';
Utils.H_POSITION_RIGHT_MOUSE  = 'right_mouse';

Utils.V_POSITION_ABOVE_MOUSE  = 'above';
Utils.V_POSITION_AUTO         = 'auto';
Utils.V_POSITION_BELOW_MOUSE  = 'below';
Utils.V_POSITION_CENTER       = 'center';
Utils.V_POSITION_CENTER_MOUSE = 'center_mouse';
Utils.V_POSITION_NONE         = 'none';

Utils._browserInfoData = [
   {
      identity: 'omniweb',
      string: navigator.userAgent,
      subString: 'OmniWeb',
      versionSearch: 'OmniWeb/'
   },
   {
      identity: 'safari',
      string: navigator.vendor,
      subString: 'Apple',
      versionSearch: 'Safari'
   },
   {
      identity: 'opera',
      prop: window.opera,
      versionSearch: 'Opera'
   },
   {
      identity: 'icab',
      string: navigator.vendor,
      subString: 'iCab',
      versionSearch: 'iCab'
   },
   {
      identity: 'konqueror',
      string: navigator.vendor,
      subString: 'KDE',
      versionSearch: 'Konqueror'
   },
   {
      identity: 'firefox',
      string: navigator.userAgent,
      subString: 'Firefox',
      versionSearch: 'Firefox'
   },
   {
      identity: 'camino',
      string: navigator.vendor,
      subString: 'Camino',
      versionSearch: 'Camino'
   },
   {
      identity: 'netscape',
      string: navigator.userAgent,
      subString: 'Netscape',
      versionSearch: 'Netscape'
   },
   {
      identity: 'ie',
      string: navigator.userAgent,
      subString: 'MSIE',
      versionSearch: 'MSIE'
   },
   {
      identity: 'mozilla',
      string: navigator.userAgent,
      subString: 'Gecko',
      versionSearch: 'rv'
   },
   {
      identity: 'netscape',
      string: navigator.userAgent,
      subString: 'Mozilla',
      versionSearch: 'Mozilla'
   }
];

Utils._browserInfoOs = [
   {
      identity: 'win',
      string: navigator.platform,
      subString: 'Win'
   },
   {
      identity: 'mac',
      string: navigator.platform,
      subString: 'Mac'
   },
   {
      identity: 'lin',
      string: navigator.platform,
      subString: 'Linux'
   }
];

Utils._reloadTimeout = null;
Utils._rotateImageInfo = {};


/**
 * Automatically reload page after a given amount of time.
 * Needs to be called in the onload for the page.
 *
 * @param secs Number of seconds to wait before reloading.
 */
Utils.autoReload = function(secs)
{
   if (secs)
   {
      Utils._reloadTimeout = secs * 1000;
      window.setTimeout("Utils._reload()", Utils._reloadTimeout);
   } // if
} // autoReload


/**
 * Capitalize a string.
 *
 * @param s String to capitalize.
 */
Utils.capitalize = function(s)
{
   if (s)
   {
      s = s.substring(0, 1).toUpperCase() + s.substring(1);
   } // if

   return (s);
} // capitalize


/**
 * Centers an element.
 *
 * @param elem Element to position.
 */
Utils.centerElem = function(elem)
{
   Utils.positionElem(elem,
                      Utils.V_POSITION_CENTER,
                      Utils.H_POSITION_CENTER);
} // centerElem


/**
 * Used to change to a location if user confirms message.
 *
 * @param msg  Message to display in confirmation dialog.
 * @param url  URL to go to if user presses "Yes".
 */
Utils.changeOnConfirm = function(msg,
                                 url)
{
   if (confirm(msg))
   {
      document.location = url;
   } // if
} // changeOnConfirm


/** 
 * Used to change tabs.
 *
 * @param ids  Array of all tab content ids.
 * @param id   Id of tab content tab to display.
 */
Utils.changeTab = function(ids,
                           id)
{
   if (document.getElementById(id))
   {
      for (var i = 0; i < ids.length; i++)
      {
         if (document.getElementById(ids[i]))
         {
            document.getElementById(ids[i]).style.display = 'none';
            document.getElementById(ids[i] + 'Tab').className = '';
         } // if
      } // for

      document.getElementById(id).style.display = 'block';
      document.getElementById(id + 'Tab').className = 'active';
   } // if
} // changeTab


/**
 * Comparison routine.
 *
 * @param a Variable to compare.
 * @param b Variable to compare.
 *
 * @return 1 if a > b, -1 if b < a, and 0 if a == b.
 */
Utils.cmp = function(a,
                     b)
{
   if (a < b)
   {
      return (-1);
   } // if

   if (a > b)
   {
      return (1);
   } // if

   return (0);
} // cmp


/**
 * Copies the value of one field into another.
 * 
 * @param input   Input control whose value is to be copied.
 * @param dest    Id of input to copy to.
 * @param cb      If given, it id the id to a checkbox. Only if this checkbox
 *                   is checked will the value be copied.
 */
Utils.copyField = function(input,
                           dest,
                           cb)
{
   if ((cb != null) &&
       (cb != undefined))
   {
      if ((document.getElementById(cb)) &&
          (!document.getElementById(cb).checked))
      {
         return;
      } // if
   } // if

   if (document.getElementById(dest))
   {
      document.getElementById(dest).value = input.value;
   } // if
} // copyField


/**
 * This creates a flash object "externally".
 *
 * @param id      Id of html element to create flash object in.
 * @param classid Flash class id.
 * @param src     Flash source file.
 * @param name    Name/id of object and embed elements.
 * @param width   Width.
 * @param height  Height.
 * @param params  Array of parameters.
 * @param version Flash version (i.e. 7,0,0,0).
 * @param extra   Extra object/embed information.
 */
Utils.createFlashObject = function(id,
                                   classid,
                                   src,
                                   name,
                                   width,
                                   height,
                                   params,
                                   version,
                                   extra)
{
   var elem = document.getElementById(id);
   
   if (elem)
   {
      var s = '<object classid="' + classid + '" codebase="http://fpdownload.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=' + version + '" width="' + width + '" height="' + height + '" id="' + name + '" name="' + name + '" ' + extra + '>';
      s += '<param name="movie" value="' + src + '" />';

      for (var i in params)
      {
         // this is a hack to work with mootools. no idea how this gets added but it breaks
         // everything.
         if (i == '$family')
         {
            break;
         } // if

         s += '<param name="' + i + '" value="' + params[i] + '" />';
      } // for

      s += '<embed src="' + src + '" width="' + width + '" height="' + height + '" id="' + name + '" name="' + name + '" swliveconnect="true" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" ';

      for (var i in params)
      {
         // this is a hack to work with mootools. no idea how this gets added but it breaks
         // everything.
         if (i == '$family')
         {
            break;
         } // if

         s += i + '="' + params[i] + '" ';
      } // for

      s += extra + ' /></object>';
      elem.innerHTML = s;
   } // if
} // createFlashObject


/**
 * Used to execute a function if user confirms message.
 *
 * @param msg  Message to display in confirmation dialog.
 * @param fn   Function to execute (must take no parameters).
 */
Utils.execOnConfirm = function(msg,
                               fn)
{
   if (confirm(msg))
   {
      fn();
   } // if
} // execOnConfirm


/**
 * This formats a floating point value.
 *
 * @param value   Floating point value to format.
 * @param format  Format to convert to (in the form of '1.2', '1.3', etc...).
 *
 * @return Formatted float value as a string.
 */
Utils.formatFloat = function(value,
                             format)
{
   value = '' + parseFloat(value);
   var temp = format.split('.',
                           2);
   var intPlaces = parseInt(temp[0]);
   var decPlaces = parseInt(temp[1]);
   var pos = value.indexOf('.');

   // decimals.
   if (pos == -1)
   {
      if (decPlaces > 0)
      {
         value += '.';
      } // if

      pos = value.length - 1;
   } // if

   while ((value.length - pos) <= decPlaces)
   {
      value += '0';
   } // while


   // integers.
   var len = intPlaces - pos;

   for (var i = 0; i < len; i++)
   {
      value = '0' + value;
   } // for

   return (value);
} // formatFloat


/**
 * This formats a price value.
 *
 * @param value   Floating point value to format.
 * @param incSign Whether or not to include $ sign.
 *
 * @return Formatted float value as a price string.
 */
Utils.formatPrice = function(value,
                             incSign)
{
   if ((incSign == undefined) ||
       (incSign))
   {
      var s = '$';
   } // if
   else
   {
      var s = '';
   } // else

   return (s + Utils.formatFloat(value, '1.2'));
} // formatPrice


/**
 * Gets browser information: browser name, version, and os.
 * This was originally taken from: http://www.quirksmode.org/js/detect.html.
 *
 * @return Array of browser name (camino, firefox, icab, ie,
 *         konqueror, mozilla, netscape, omniweb, opera, or safari), 
 *         version as a float or os (lin, mac, or win). null will be 
 *         returned on error.
 */
Utils.getBrowserInfo = function()
{
   var temp = Utils._searchBrowserString(Utils._browserInfoData);

   if (temp)
   {
      var browser = temp[0];
      var version = Utils._searchBrowserVersion(navigator.userAgent, temp[1]) || Utils._searchBrowserVersion(navigator.appVersion, temp[1]);
      temp = Utils._searchBrowserString(Utils._browserInfoOs);

      if (temp)
      {
         var os = temp[0];
      } // if
      else
      {
         var os = null;
      } // else

      return (new Array(browser, version, os));
   } // if
   
   return (null);
} // getBrowserInfo


/**
 * Returns the number of days in the given month/year.
 * 
 * @param year    Year.
 * @param month   Month.
 *
 * @return Days in the given month/year.
 */
Utils.getDaysInMonth = function(year,
                                month)
{
   switch (month)
   {
      case 2:
         if (Utils.isLeapYear(year))
         {
            return (29);
         } // if

         return (28);

      case 4:
      case 6:
      case 9:
      case 11:
         return (30);
   } // switch

   return (31);
} // getDaysInMonth


/**
 * Find absolute position of an element.
 *
 * @param elem Element to get position of.
 *
 * @return Array of left, top position.
 */
Utils.getElementPosition = function(elem)
{
   var left = 0;
   var top = 0;

   if (elem.offsetParent)
   {
      left = elem.offsetLeft;
      top = elem.offsetTop;

      while (elem = elem.offsetParent)
      {
         left += elem.offsetLeft;
         top += elem.offsetTop;
      } // while
   } // if

   return (new Array(left, top));
} // getElementPosition


/**
 * Gets month name in string.
 *
 * @param month   Month as number (1-12).
 *
 * @return Month string.
 */
Utils.getMonthString = function(m)
{
   switch (m)
   {
      case 1:  return 'January';
      case 2:  return 'February';
      case 3:  return 'March';
      case 4:  return 'April';
      case 5:  return 'May';
      case 6:  return 'June';
      case 7:  return 'July';
      case 8:  return 'August';
      case 9:  return 'September';
      case 10: return 'October';
      case 11: return 'November';
      default: return 'December';
   } // switch
} // getMonthString


/** 
 * Gets the current window height.
 *
 * @return Window height.
 */
Utils.getWindowHeight = function()
{
   if (typeof(window.innerHeight) == 'number')
   {
      return (window.innerHeight);
   } // if

   if ((document.documentElement) &&
       (document.documentElement.clientHeight))
   {
      return (document.documentElement.clientHeight);
   } // if

   if ((document.body) &&
       (document.body.clientHeight))
   {
      return (document.body.clientHeight);
   } // if

   return (0);
} // getWindowHeight


/** 
 * Gets the current window width.
 *
 * @return Window width.
 */
Utils.getWindowWidth = function()
{
   if (typeof(window.innerWidth) == 'number')
   {
      return (window.innerWidth);
   } // if

   if ((document.documentElement) &&
       (document.documentElement.clientWidth))
   {
      return (document.documentElement.clientWidth);
   } // if

   if ((document.body) &&
       (document.body.clientWidth))
   {
      return (document.body.clientWidth);
   } // else if

   return (0);
} // getWindowWidth


/**
 * Gets the window's x offset.
 *
 * @return X offset.
 */
Utils.getWindowXOffset = function()
{
   if (typeof(window.pageXOffset) == 'number')
   {
      return (window.pageXOffset);
   } // if

   if ((document.documentElement) &&
       (document.documentElement.scrollLeft))
   {
      return (document.documentElement.scrollLeft);
   } // if
   
   if ((document.body) &&
       (document.body.scrollLeft))
   {
      return (document.body.scrollLeft);
   } // else if

   return (0);
} // getWindowXOffset


/**
 * Gets the window's y offset.
 *
 * @return Y offset.
 */
Utils.getWindowYOffset = function()
{
   if (typeof(window.pageYOffset) == 'number')
   {
      return (window.pageYOffset);
   } // if

   if ((document.documentElement) &&
       (document.documentElement.scrollTop))
   {
      return (document.documentElement.scrollTop);
   } // if
   
   if ((document.body) &&
       (document.body.scrollTop))
   {
      return (document.body.scrollTop);
   } // else if

   return (0);
} // getWindowYOffset


/**
 * This hides all children of a given element.
 *
 * @param elem Element to hide children of.
 */
Utils.hideChildren = function(elem)
{
   for (var i = 0; i < elem.childNodes.length; i++)
   {
      if (elem.childNodes[i].style)
      {
         elem.childNodes[i].style.display = 'none';
      } // if
   } // for
} // hideChildren


/**
 * Determines if a value is in an array.
 *
 * @param needle     Value to look for.
 * @param haystack   Array to check.
 * 
 * @return true if value exists, false if not.
 */
Utils.inArray = function(needle,
                         haystack)
{
   for (var i = 0; i < haystack.length; i++)
   {
      if (haystack[i] == needle)
      {
         return (true);
      } // if
   } // for

   return (false);
} // inArray


/**
 * This determines if the given year is a leap year.
 * A leap year is one that is divisible by 4 but not divisible by 100 unless
 * its also divisible by 400.
 *
 * @param year Year to check.
 *
 * @return true if it is a leap year, false if not.
 */
Utils.isLeapYear = function(year)
{
   if (!(year % 4))
   {
      return ((year % 100) || (!(year % 400)));
   } // if

   return (false);
} // isLeapYear


/**
 * Opens a new window.
 *
 * @param url     URL of new window.
 * @param title   Title of new window.
 */
Utils.openWindow = function(url,
                            title)
{
   window.open(url,
               title,
               'innerHeight=window.innerHeight,innerWidth=window.innerWidth,location=yes,menubar=yes,resizeable=yes,scrollbars=yes,titlebar=yes,toolbar=yes');
} // openWindow


/**
 * This parses a dttm string and returns an object.
 *
 * @param dttm Date/time string to parse in the format (YYYYMMDDHHMMSS).
 *
 * @return Object that represents the date/time with attributes: year, month,
 *         monthNameShort, monthNameLong, day, hours24, hours12, minutes, and
 *         seconds.
 */
Utils.parseDttm = function(dttm)
{
   if (!dttm)
   {
      return (null);
   } // if

   var obj = new Object();

   obj.year = dttm.substring(0, 4);
   obj.month = dttm.substring(4, 6);
   obj.day = dttm.substring(6, 8);
   obj.hours24 = dttm.substring(8, 10);

   var temp = parseInt(obj.hours24);

   if (temp > 12)
   {
      obj.hours12 = temp - 12;
      obj.amPm = 'pm';
   } // if
   else if (temp == 0)
   {
      obj.hours12 = 12;
      obj.amPm = 'am';
   } // else if
   else if (temp == 12)
   {
      obj.hours12 = 12;
      obj.amPm = 'pm';
   } // else if
   else
   {
      obj.hours12 = obj.hours24;
      obj.amPm = 'am';
   } // else

   obj.minutes = dttm.substring(10, 12);
   obj.seconds = dttm.substring(12, 14);
   
   switch (parseInt(obj.month))
   {
      case 1:  obj.monthNameShort = 'Jan'; obj.monthNameLong = 'January'; break;
      case 2:  obj.monthNameShort = 'Feb'; obj.monthNameLong = 'February'; break;
      case 3:  obj.monthNameShort = 'Mar'; obj.monthNameLong = 'March'; break;
      case 4:  obj.monthNameShort = 'Apr'; obj.monthNameLong = 'April'; break;
      case 5:  obj.monthNameShort = 'May'; obj.monthNameLong = 'May'; break;
      case 6:  obj.monthNameShort = 'Jun'; obj.monthNameLong = 'June'; break;
      case 7:  obj.monthNameShort = 'Jul'; obj.monthNameLong = 'July'; break;
      case 8:  obj.monthNameShort = 'Aug'; obj.monthNameLong = 'August'; break;
      case 9:  obj.monthNameShort = 'Sep'; obj.monthNameLong = 'September'; break;
      case 10: obj.monthNameShort = 'Oct'; obj.monthNameLong = 'October'; break;
      case 11: obj.monthNameShort = 'Nov'; obj.monthNameLong = 'November'; break;
      case 12: obj.monthNameShort = 'Dec'; obj.monthNameLong = 'December'; break;
      default: obj.monthNameShort = '???'; obj.monthNameLong = '???'; break;
   } // switch

   return (obj);
} // parseDttm


/**
 * Positions an element.
 *
 * @param elem Element to position.
 * @param vpos Vertical position.
 * @param hpos Horizontal position.
 */
Utils.positionElem = function(elem,
                              vpos,
                              hpos)
{
   if ((vpos == null) ||
       (vpos == undefined))
   {
      vpos = Utils.V_POSITION_CENTER;
   } // if

   if ((hpos == null) ||
       (hpos == undefined))
   {
      hpos = Utils.H_POSITION_CENTER;
   } // if

   // some nice to knows:
   //    elem.clientWidth - Element width.
   //    elem.clientHeight - Element height.
   //    window.o3_x - Pointer X position (obviously).
   //    window.o3_y - Pointer Y position (obviously).
   var top = Utils.getWindowYOffset();
   var left = Utils.getWindowXOffset();
   var w = Utils.getWindowWidth();
   var h = Utils.getWindowHeight();

   var x_changed = false;
   var y_changed = false;

   if (vpos != Utils.V_POSITION_NONE)
   {
      switch (vpos)
      {
         case Utils.V_POSITION_ABOVE_MOUSE:
            // above the pointer.
            var y = window.o3_y - elem.clientHeight - 20;
            break;

         case Utils.V_POSITION_AUTO:
         case Utils.V_POSITION_CENTER_MOUSE:
            // center around mouse.
            var y = Math.round(window.o3_y - (elem.clientHeight / 2));

            // make sure as visible as possible.
            if (hpos == Utils.V_POSITION_AUTO)
            {
               if (y < (top + 10))
               {
                  y = top + 10;
               } // if
               else if ((y + elem.clientWidth) > (h + top - 20))
               {
                  y = h + top - elem.clientWidth - 20;
               } // else if

               if (y < 0)
               {
                  y = 0;
               } // if
            } // if
            break;

         case Utils.V_POSITION_BELOW_MOUSE:
            // below the pointer.
            var y = window.o3_y + 10;
            break;

         case Utils.V_POSITION_CENTER:
            // center on screen.
            var y = Math.round((h - elem.clientHeight) / 2);

            if (y < 0)
            {
               y = 0;
            } // if

            y += top;
            break;

         default:
            if (isNaN(vpos))
            {
               var temp = vpos.substr(0,
                                      vpos.length - 2);
               
               if ((vpos.substr(vpos.length - 2) == 'ab') &&
                   (!isNaN(temp)))
               {
                  // absolute positioning.
                  var y = parseInt(temp);
               } // if
            } // if
            else
            {
               // relative positioning.
               var y = window.o3_y + parseInt(vpos);
            } // else
            break;
      } // switch

      elem.style.top = y + 'px';
      y_changed = true;
   } // if


   if (hpos != Utils.H_POSITION_NONE)
   {
      switch (hpos)
      {
         case Utils.H_POSITION_AUTO:
         case Utils.H_POSITION_CENTER_MOUSE:
            // center horizontally over current mouse position.
            var x = Math.round(window.o3_x - (elem.clientWidth / 2));

            // make sure as visible as possible.
            if (hpos == Utils.H_POSITION_AUTO)
            {
               if (x < (left + 10))
               {
                  x = left + 10;
               } // if
               else if ((x + elem.clientWidth) > (w + left - 20))
               {
                  x = w + left - elem.clientWidth - 20;
               } // else if

               if (x < 0)
               {
                  x = 0;
               } // if
            } // if
            break;

         case Utils.H_POSITION_LEFT_MOUSE:
            // to left of pointer.
            var x = window.o3_x - elem.clientWidth - 20;
            break;

         case Utils.H_POSITION_RIGHT_MOUSE:
            // to right of pointer.
            var x = window.o3_x + elem.clientWidth + 10;
            break;

         case Utils.H_POSITION_CENTER:
            // center horizontally on screen.
            var x = Math.round((w - elem.clientWidth) / 2);

            if (x < 0)
            {
               x = 0;
            } // if

            x += left;
            break;

         default:
            if (isNaN(hpos))
            {
               var temp = hpos.substr(0,
                                    hpos.length - 2);
               
               if ((hpos.substr(hpos.length - 2) == 'ab') &&
                  (!isNaN(temp)))
               {
                  // absolute positioning.
                  var x = parseInt(temp);
               } // if
            } // if
            else
            {
               // relative positioning.
               var x = window.o3_x + parseInt(hpos);
            } // else
            break;
      } // switch

      elem.style.left = x + 'px';
      x_changed = true;
   } // if

   var temp = Utils.getElementPosition(elem);

   if (temp)
   {
      var left = temp[0];
      var top = temp[1];

      if (y_changed)
      {
         if (top != y)
         {
            elem.style.top = (y - top + y) + 'px';
         } // if
      } // if

      if (x_changed)
      {
         if (left != x)
         {
            elem.style.left = (x - left + x) + 'px';
         } // if
      } // if
   } // if
} // positionElem


/**
 * Removes cells from the given element.
 *
 * @param elem Element to remove cells from.
 */
Utils.removeCells = function(elem)
{
   while (elem.cells.length > 0)
   {
      elem.removeChild(elem.firstChild);
   } // while
} // removeCells


/**
 * Removes children from a given element.
 *
 * @param elem Element to remove children from.
 */
Utils.removeChildren = function(elem)
{
   while (elem.childNodes.length)
   {
      elem.removeChild(elem.firstChild);
   } // while
} // removeChildren


/**
 * Removes rows from a given element.
 *
 * @param elem Element to remove rows from.
 */
Utils.removeRows = function(elem)
{
   while (elem.rows.length > 0)
   {
      elem.removeChild(elem.firstChild);
   } // while
} // removeRows 


/**
 * Rotates an image at a given interval.
 *
 * @param id         Id of img element to rotate.
 * @param images     Array of all image URLs to rotate through.
 * @param interval   Interval (in seconds) to rotate.
 * @param effect     Effect to use to rotate (fade-slow, fade-fast, or null).
 */
Utils.rotateImage = function(id, 
                             images,
                             interval,
                             effect)
{
   if (effect == undefined)
   {
      effect = null;
   } // if

   if ((id) &&
       (images) &&
       (interval))
   {
      timer = setInterval("Utils._timerRotateImage('" + id + "')",
                          interval * 1000);
      Utils._rotateImageInfo[id] = {
         'timer' : timer,
         'images' : images,
         'effect' : effect
      };
   } // if
} // rotateImage


/**
 * This trims whitespace or a given character from the front and end
 * of a given string.
 *
 * @param s String to remove from.
 * @param c Character to remove or omit to remove whitespace.
 *
 * @return Trimmed string.
 */
Utils.trim = function(s,
                      c)
{
   var i = 0;

   if (c == undefined)
   {
      c = null;
   } // if

   // left.
   for (i = 0; i < s.length; i++)
   {
      if (c == null)
      {
         if ((s[i] != ' ') && (s[i] != '\t') && (s[i] != '\n'))
         {
            break;
         } // if
      } // if
      else if (s[i] != c)
      {
         break;
      } // else
   } // for

   if (i >= s.length)
   {
      return ('');
   } // if


   // right.
   var j;

   for (j = s.length - 1; j > i; j--)
   {
      if (c == null)
      {
         if ((s[j] != ' ') && (s[j] != '\t') && (s[j] != '\n'))
         {
            break;
         } // if
      } // if
      else if (s[j] != c)
      {
         break;
      } // else
   } // for

   s = s.substring(i,
                   j + 1);
   return (s);
} // trim 


/**
 * Updates given select control with given options.
 * Existing options will be removed.
 *
 * @param select  Select control.
 * @param opts    Option dictionary.
 */
Utils.updateSelectOptions = function(select,
                                     opts)
{
   select.options.length = 0;

   for (var i in opts)
   {
      var option = new Option(opts[i],
                              i);
      select.options[select.options.length] = option;
   } // for
} // updateSelectOptions


/**
 * Updates a text input.
 *
 * @param control       Control to update text input from.
 * @param id            Id of text input to update.
 * @param onlyIfEmpty   true to update only if text input is empty, false
 *                         to always update.
 */
Utils.updateTextInput = function(control,
                                 id,
                                 onlyIfEmpty)
{
   if (onlyIfEmpty == undefined)
   {
      onlyIfEmpty = true;
   } // if

   var elem = document.getElementById(id);

   if (elem)
   {
      if ((!onlyIfEmpty) || 
          (!elem.value.length))
      {
         elem.value = control.value;
      } // if
   } // if
} // updateTextInput


/**
 * Encodes a URL.
 *
 * @param url  URL to encode.
 *
 * @return Encoded URL.
 */
Utils.urlEncode = function(url)
{
   return (escape(url).replace(/\+/g, '%2B').replace(/\"/g,'%22').replace(/\'/g, '%27').replace(/\//g,'%2F'));
} // urlEncode 


/**
 * Converts an XML document to an object.
 *
 * @param xml  XML document to parse.
 *
 * @return Object representation of XML document.
 */
Utils.xmlToObject = function(xml)
{
   if (!xml)
   {
      return (null);
   } // if

   if (!xml.documentElement)
   {
      return (null);
   } // if

   return (Utils._xmlElemToObj(xml.documentElement));
} // xmlToObject


/**
 * Does the actual reloading after timeout is hit.
 */
Utils._reload = function()
{
   document.location = document.location;
   window.setTimeout("Utils._reload()", Utils._reloadTimeout);
} // _reload


/**
 * Searches a browser string.
 * This was originally taken from: http://www.quirksmode.org/js/detect.html.
 *
 * @param data Data to search.
 *
 * @return Array that contains browser identity and version search
 *         string or null if nothing found.
 */
Utils._searchBrowserString = function(data)
{
   for (var i = 0; i < data.length; i++)
   {
      if (data[i].string)
      {
         if (data[i].string.indexOf(data[i].subString) != -1)
         {
            return (new Array(data[i].identity, data[i].versionSearch));
            } // if
      } // if
      else if (data[i].prop)
      {
         return (new Array(data[i].identity, data[i].versionSearch));
      } // else if
   } // for

   return (null);
} // _searchBrowserString


/**
 * Searches for a browser version.
 * This was originally taken from: http://www.quirksmode.org/js/detect.html.
 *
 * @param dataString    Data string to search.
 * @param versionString Version string to look for.
 *
 * @return Version as a float or null if not found.
 */
Utils._searchBrowserVersion = function(dataString,
                                       versionString)
{
   var index = dataString.indexOf(versionString);
   
   if (index == -1)
   {
      return (null);
   } // if

   return (parseFloat(dataString.substring(index + versionString.length + 1)));
} // _searchBrowserVersion


/**
 * Called by timer from rotateImage() to do actual image rotation.
 *
 * @param id   Id of img element to rotate.
 */
Utils._timerRotateImage = function(id)
{
   if (id in Utils._rotateImageInfo)
   {
      images = Utils._rotateImageInfo[id]['images'];
      timer = Utils._rotateImageInfo[id]['timer'];
      effect = Utils._rotateImageInfo[id]['effect'];

      if ((id) &&
          (images))
      {
         elem = jQuery('#' + id);
      } // if

      if (!elem.size())
      {
         if (timer)
         {
            clearInterval(timer);
         } // if

         return;
      } // if

      var src = elem.attr('src');
      var temp = src.indexOf('/images/');

      if (temp < 0)
      {
         if (timer)
         {
            clearInterval(timer);
         } // if

         return;
      } // if

      var idx = 0;
      src = src.substr(temp);

      for (var i = 0; i < images.length; i++)
      {
         if (src == images[i])
         {
            idx = i;
            break;
         } // if
      } // for

      idx++;

      if (idx >= images.length)
      {
         idx = 0;
      } // if

      if (effect)
      {
         elem.parent().css('background-image', 'url(' + images[idx] + ')');
      } // if

      switch (effect)
      {
         case 'fade-fast':
            elem.fadeOut(500, function(){
               elem.attr('src', images[idx]);
               elem.fadeIn();
            });
            break;

         case 'fade-slow':
            elem.fadeOut(1000, function(){
               elem.attr('src', images[idx]);
               elem.fadeIn();
            });
            break;

         default:
            elem.attr('src', images[idx]);
            break;
      } // switch
   } // if
} // _timerRotateImage


/**
 * Recursively gets children from an XML element.
 *
 * @param elem XML element to get children from.
 *
 * @return Object representaton of element.
 */
Utils._xmlElemToObj = function(elem)
{
   // see if this is a single value.
   if (!elem.childNodes.length)
   {
      // empty element.
      return (null);
   } // if


   // has children.
   var obj = new Object();

   for (var i = 0; i < elem.childNodes.length; i++)
   {
      var name = elem.childNodes[i].getAttribute('name');

      if (!name)
      {
         continue;
      } // if

      var type = elem.childNodes[i].nodeType;

      switch (elem.childNodes[i].nodeName)
      {
         case 'array':
         case 'object':
            obj[name] = Utils._xmlElemToObj(elem.childNodes[i]);
            break;

         case 'boolean':
            var value = elem.childNodes[i].getAttribute('value');

            if (parseInt(value))
            {
               obj[name] = true;
            } // if
            else
            {
               obj[name] = false;
            } // else
            break;

         case 'float':
            var value = elem.childNodes[i].getAttribute('value');
            obj[name] = parseFloat(value);
            break;

         case 'integer':
            var value = elem.childNodes[i].getAttribute('value');
            obj[name] = parseInt(value);
            break;

         default:
            if (elem.childNodes[i].childNodes.length)
            {
               obj[name] = elem.childNodes[i].childNodes[0].nodeValue;
            } // if
            else
            {
               obj[name] = null;
            } // else
            break;
      } // switch
   } // for

   return (obj);
} // _xmlElemToObj
