function hideIfUnset(a, b)
{
  a = document.getElementById(a);
  b = document.getElementById(b);
  b.style.display = (a.value == '' ? 'none' : '');
}

function displayOrHide(element, display)
{
  if (element)
  {
    element.style.display = display ? "" : "none";
  }
}

function jsc_log(msg)
{
  netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
  var logger = Components.classes["@mozilla.org/consoleservice;1"].getService(Components.interfaces.nsIConsoleService);
  logger.logStringMessage(msg);
}

function updateDimensionElement(title)
{
  var valueElement = document.getElementById('value_' + title);
  var leElement = document.getElementById('rangeLe_' + title);
  var geElement = document.getElementById('rangeGe_' + title);
  if (leElement != null && geElement != null)
  {
    var v = valueElement.value;
    {
      var i = 0;
      var currentSelectedValue = leElement.selectedIndex != -1 ?
        leElement.options[leElement.selectedIndex].value : null;
      leElement.options.length = 0;
      var newSelectedIndex = 0;
      for (var j = 0; j <= valueElement.selectedIndex; j++)
      {
        leElement.options[i] = new Option(
          valueElement.options[j].text, valueElement.options[j].value);
        if (valueElement.options[j].value == currentSelectedValue)
        {
          newSelectedIndex = i;
        }
        i++;
      }
      leElement.selectedIndex =
        newSelectedIndex < leElement.options.length ? newSelectedIndex : 0;
    }
    {
      var currentSelectedValue = geElement.selectedIndex != -1 ?
        geElement.options[geElement.selectedIndex].value : null;
      geElement.options.length = 0;
      var newSelectedIndex = 0;
      var i = 0;
      geElement.options[i++] = new Option("", "-1");
      for (var j = valueElement.selectedIndex; j < valueElement.options.length; j++)
      {
        geElement.options[i] = new Option(
          valueElement.options[j].text, valueElement.options[j].value);
        if (valueElement.options[j].value == currentSelectedValue)
        {
          newSelectedIndex = i;
        }
        i++;
      }
      geElement.selectedIndex =
        newSelectedIndex < geElement.options.length ? newSelectedIndex : 0;
    }
  }
  var leRowElement = document.getElementById('widget_rangeLe_' + title);
  var geRowElement = document.getElementById('widget_rangeGe_' + title);
  displayOrHide(leRowElement, leElement != null &&
    valueElement.selectedIndex > 0 && leElement.options.length > 1);
  displayOrHide(geRowElement, geElement != null &&
    valueElement.selectedIndex > 0 && geElement.options.length > 1);
}

function getElementsByClass(out, haystack, needle)
{
  while (haystack) 
  {
    if (haystack.nodeType == Node.ELEMENT_NODE) 
    {
      if (haystack.hasAttribute("class")) 
      {
        var c = " " + haystack.className + " ";
        if (c.indexOf(" " + needle + " ") != -1)
          out.push(haystack);
      }
      getElementsByClass(out, haystack.firstChild, needle);
    }
    haystack = haystack.nextSibling;
  }
  return out;
}

function showExtendedAdmin()
{
  var out = new Array();
  needle = "extendedAdmin"; 
  getElementsByClass(out, document.documentElement, needle);
  for (var i = 0; i < out.length; i++)
  {
    out[i].style.display='';
  }
  return false;
} 

function hideExtendedAdmin()
{
  var out = new Array();
  needle = "extendedAdmin"; 
  getElementsByClass(out, document.documentElement, needle);
  for (var i = 0; i < out.length; i++)
  {
    out[i].style.display='none';
  }
  return false;
} 


/**
 * simple div hiding
 */
function showDiv(div)
{
  div.style.display = "";
}

function hideDiv(div)
{
  div.style.display = "none;";
}

function hideDivWithId(id)
{
  document.getElementById(id).style.display = "none;";
}

function showDivWithId(id)
{
  document.getElementById(id).style.display = "";
}

/**
 * Construct a query string from a form's input elements.
 */
function getQueryStringFromForm(form)
{
  var pairs = new Array();
  getQueryStringPairs(form, pairs);
  var qs = "";
  for (var i in pairs)
  {
    var pair = pairs[i];

    if (pair[1] == "" || pair[1] == null)
    {
      continue;
    }
    else if (pair[0] == 's.clickedButton')
    {
      /* uggh, this is just so wrong, but i'm having trouble getting this 
       * information any other way, as *both* button's values come through with
       * getQueryStringPairs
      */
      
      // add 'legacy' or 'fuzzy' = 'Search'
      pair[0] = pair[1]; 
      pair[1] = 'Search';
    }
    else if (pair[0] == 'legacy' || pair[0] == 'fuzzy')
    {
      /* ignore buttons */
      continue;
    }
    if (qs != "")
    {
      qs += "&";
    }
    qs += escape(pair[0]);
    qs += "=";
    qs += escape(pair[1]);
  }
  return qs;
}


/**
 * Construct query string key/value pairs from an element's child input
 * elements.
 */
function getQueryStringPairs(element, pairs)
{
  for (var child = element.firstChild; child != null; child = child.nextSibling)
  {
    if (!child.tagName)
    {
      continue;
    }
    var tag = new String(child.tagName);
    if (child.name && child.name != "")
    {
      var elementName = tag.toLowerCase();
      if (elementName == "input")
      {
        if (child.type && child.type != "submit")
        {
          var value = null;
          if (child.type && child.type == "checkbox")
          {
            value = (child.checked && child.value) ? child.value : null;
          }
          else
          {
            // a check for the child.value property
            value = child.value;
          }
          if (value != null && (isString(value) && !isEmpty(value)))
          {
            pairs[pairs.length] = new Array(child.name, value);
          }
        }
      }
      else if (elementName == "select" && child.childNodes && child.childNodes.length)
      {
        for(var i = 0; i < child.childNodes.length; i++)
        {
          var cn = child.childNodes[i];
          if (cn.tagName && cn.tagName.toLowerCase() == 'option' && cn.selected)
          {
            pairs[pairs.length] = new Array(child.name, cn.value);
          }
        }
      }
    }
    getQueryStringPairs(child, pairs);
  }
}

/**
 * Converts HSV triplet to numeric RGB value.
 */
function hsvToRgb(h, s, v)
{
  h = Math.min(Math.max(h, 0), 1);
  s = Math.min(Math.max(s, 0), 1);
  v = Math.min(Math.max(v, 0), 1);
  h *= 6.0
  var i = Math.floor(h);
  var f = h - i;
  if ((i & 1) == 0)
  {
    f = 1 - f;
  }
  var m = v * (1 - s);
  var n = v * (1 - s * f);
  var rgb;
  switch (i)
  {
    case 6:
    case 0:
      rgb = [v, n, m];
      break;
    case 1:
      rgb = [n, v, m];
      break;
    case 2:
      rgb = [m, v, n];
      break;
    case 3:
      rgb = [m, n, v];
      break;
    case 4:
      rgb = [n, m, v];
      break;
    case 5:
      rgb = [v, m, n];
      break;
    default:
      rgb = [0, 0, 0];
  }
  return rgb;
}

function _styleClassRegexp(styleClass)
{
  return new RegExp("\\b" + styleClass + "\\b", "g");
}

function addStyleClass(element, styleClass)
{
  if (!_styleClassRegexp(styleClass).test(element.className))
  {
    element.className = element.className + " " + styleClass;
  }
}

function removeStyleClass(element, styleClass)
{
  element.className = element.className.replace(
    _styleClassRegexp(styleClass), "");
}

/**
 * Calculates the absolute rectangular bounds of an element, relative to the
 * document body.
 *
 * @param element
 *   element to inspect.
 * @return
 *   an Object with the following fields set: <code>left</code>,
 *   <code>right</code>, <code>top</code> and </code>bottom</code>.
 */
function getAbsoluteBounds(element)
{
  var bounds = new Object();
  bounds.left = 0;
  bounds.top = 0;
  bounds.right = 0;
  bounds.bottom = 0;
  var e = element;
  while (e != null)
  {
    bounds.left += e.offsetLeft;
    bounds.top += e.offsetTop;
    e = e.offsetParent;
  }
  bounds.right = bounds.left + element.offsetWidth;
  bounds.bottom = bounds.top + element.offsetHeight;
  bounds.toString = function () 
  {
    return bounds.top + ", " + bounds.right + ", " + bounds.bottom + ", " + bounds.left;
  };
  return bounds;
}

function setAbsoluteBounds(element, bounds)
{
  element.style.left = bounds.left + "px";
  element.style.top = bounds.top + "px";
  element.style.right = bounds.right + "px";
  element.style.bottom = bounds.bottom + "px";
}


function addEventListenerTo(element, eventName, listener)
{
  if (typeof element.addEventListener != typeof undefined)
  {
    element.addEventListener(eventName, listener, false);
  }
  else if (typeof element.attachEvent != typeof undefined)
  {
    element.attachEvent("on" + eventName, listener);
  }
  else
  {
    throw "Element does not support events";
  }
}

function removeEventListenerFrom(element, eventName, listener)
{
  if (typeof element.removeEventListener != typeof undefined)
  {
    element.removeEventListener(eventName, listener, false);
  }
  else if (typeof element.detachEvent != typeof undefined)
  {
    element.detachEvent("on" + eventName, listener);
  }
  else
  {
    throw "Element does not support events";
  }
}
