function getMouse(event)
{
  coords = { x: 0, y: 0 };

  if (!event)
    event = window.event;

  if (event.pageX || event.pageY) {
    coords.x = event.pageX;
    coords.y = event.pageY;
  }
  else if (event.clientX || event.clientY) {
    if (document.documentElement != null) {
      coords.x = event.clientX + document.documentElement.scrollLeft;
      coords.y = event.clientY + document.documentElement.scrollTop;
    }
    else {
      coords.x = event.clientX + document.body.scrollLeft;
      coords.y = event.clientY + document.body.scrollTop;
    }
  }

  return coords;
}


function getOffset(element)
{
  coords = { x: 0, y: 0 };

  while (element != null) {
    coords.x += element.offsetLeft;
    coords.y += element.offsetTop;
    element = element.offsetParent;
  }

  return coords;
}


function getScrollOffset(element)
{
  coords = { x: 0, y: 0 };

  while (element != null) {
    coords.x += element.scrollLeft || 0;
    coords.y += element.scrollTop || 0;
    element = element.parentNode;
  }

  return coords;
}


function stopPropagation(event)
{
  if (!event)
    var event = window.event;
  if (event.cancelBubble != null)
    event.cancelBubble = true;
  if (event.stopPropagation) 
    event.stopPropagation();
}


function addEventListener(elem, type, func, propagate)
{
  if (elem.addEventListener)
    elem.addEventListener(type, func, propagate);
  else if (elem.attachEvent)
    elem.attachEvent("on" + type, func);
}


function removeEventListener(elem, type, func, propagate)
{
  if (elem.removeEventListener)
    elem.removeEventListener(type, func, propagate);
  else if (elem.detachEvent)
    elem.detachEvent("on" + type, func);
}


function getPageDimensions()
{
  if (document.body.scrollHeight > document.body.offsetHeight)
    return {
      width: document.body.scrollWidth,
      height: document.body.scrollHeight
    };
  else
    return {
      width: document.body.offsetWidth,
      height: document.body.offsetHeight
    };
}


function Class(object)
{
  return function () {
    for (property in object)
      this[property] = object[property];

    return this.initialize.apply(this, arguments);
  }
}


function el(element)
{
  return (typeof element == "string" ?
	  document.getElementById(element) : element);
}


function getElementsByClassName(className)
{
  var children = document.getElementsByTagName('*') || document.all;
  var elements = [];

  for (var i = 0; i < children.length; i++) {
    var child = children[i];
    var classNames = child.className.split(' ');

    for (var j = 0; j < classNames.length; j++)
      if (classNames[j] == className) {
        elements[elements.length] = child;
        break;
      }
  }

  return elements;
}


function withinElement(element, x, y)
{
  var ofs = getOffset(element);

  return (ofs.x <= x &&
          ofs.x + element.offsetWidth >= x &&
          ofs.y <= y &&
          ofs.y + element.offsetHeight >= y);
}


function isAncestor(element, descendant)
{
  while (descendant.parentNode)
    if (descendant.parentNode == element)
      return true;
    else
      descendant = descendant.parentNode;

  return false;
}
