/**
 * UserAgent
 *
 * @access    public
 */
function UserAgent()
{
  var s, i;

  this.isIE    = false;  // Internet Explorer
  this.isOP    = false;  // Opera
  this.isNS    = false;  // Netscape
  this.version = null;

  var ua = navigator.userAgent;

  s = 'Opera';
  if ((i = ua.indexOf(s)) >= 0) {
    this.isOP = true;
    this.version = parseFloat(ua.substr(i + s.length));
    return;
  }

  s = 'Netscape6/';
  if ((i = ua.indexOf(s)) >= 0) {
    this.isNS = true;
    this.version = parseFloat(ua.substr(i + s.length));
    return;
  }

  // Treat any other "Gecko" browser as Netscape 6.1.

  s = 'Gecko';
  if ((i = ua.indexOf(s)) >= 0) {
    this.isNS = true;
    this.version = 6.1;
    return;
  }

  s = 'MSIE';
  if ((i = ua.indexOf(s))) {
    this.isIE = true;
    this.version = parseFloat(ua.substr(i + s.length));
    return;
  }
} // end class UserAgent

var browser = new UserAgent();


/**
 * Registers an event.
 *
 * @param   node
 * @param   string    Event type.
 * @param   function
 * @access  public
 */
function registerEvent(node, evtType, func)
{
  if (node.addEventListener) {
    node.addEventListener(evtType, func, false);
    return true;
  }

  if (node.attachEvent)
    return node.attachEvent('on' + evtType, func);

  return false;
} // end func registerEvent


/**
 * Gets node by node identifier.
 *
 * @param   string    Node identifier.
 * @return  node
 * @access  public
 */
function getNode(nodeId)
{
  if (document.getElementById) {
    return document.getElementById(nodeId);
  } else if (document.all && document.all(nodeId)) {
    return document.all(nodeId);
  } else if (document.layers && document.layers[nodeId]) {
    return document.layers[nodeId];
  } else {
    return false;
  }
} // end func getNode


/**
 * Gets offsetLeft value of element.
 *
 * @param   HTMLobject
 * @return  integer     offsetLeft of element.
 * @access  public
 */
function getPageOffsetLeft(el) 
{
  var x = el.offsetLeft;
  if (el.offsetParent != null)
    x += getPageOffsetLeft(el.offsetParent);

  return x;
} // end func getPageOffsetLeft


/**
 * Gets offsetTop value of element.
 *
 * @param   HTMLobject
 * @return  integer     offsetTop of element.
 * @access  public
 */
function getPageOffsetTop(el)
{
  var y = el.offsetTop;
  if (el.offsetParent != null)
    y += getPageOffsetTop(el.offsetParent);

  return y;
} // end func getPageOffsetTop


/**
 * Checks whether the element's className property contains the value of name.
 *
 * @param   HTMLobject
 * @param   string    class name.
 * @return  boolean   False if className property doesn't contain value of name, true otherwise.
 * @access  public
 */
function hasClassName(el, name)
{
  var list = el.className.split(' ');

  for (var i = 0; i < list.length; ++i) {
    if (list[i] == name)
      return true;
  }

  return false;
} // end func hasClassName


/**
 * Removes value of name from element's className property.
 *
 * @param   HTMLobject
 * @param   string    Name of class to be removed.
 * @access  public
 */
function removeClassName(el, name)
{
  if (el == null || el.className == null)
    return;

  var newList = new Array();
  var curList = el.className.split(' ');
  for (var i = 0; i < curList.length; ++i) {
    if (curList[i] != name)
      newList[newList.length] = curList[i];
  }
  el.className = newList.join(' ');
} // end func removeClassName


function getContainerWith(node, tagName, className) 
{
  while (node != null) {
    if (node.tagName != null && node.tagName == tagName && hasClassName(node, className))
      return node;
    node = node.parentNode;
  }

  return node;
} // end func getContainerWith


/**
 * Gets cookie by name of it.
 *
 * @param   string    Cookie name.
 * @return  string    Returns the value stored in cookie.
 * @access  public
 */
function getCookie(cookieName)
{
  var start, end;
  var cookieStr = document.cookie;

  if ((start = cookieStr.indexOf(cookieName + '=')) != -1) {
    start += cookieName.length + 1;
    if ((end = cookieStr.indexOf(';', start)) == -1)
      end = cookieStr.length;

    return cookieStr.substring(start, end);
  }

  return '';
} // end func getCookie


/**
 * Sets cookie value of a cookie entry.
 *
 * @param   string    Cookie name.
 * @param   string    Value identifier.
 * @param   string    Value to store.
 * @access  public
 */
function setCookieVal(cookieName, id, val)
{
  var tmp, i, cookieArray, cookieHash;

  cookieArray = getCookie(cookieName).split('&');
  cookieHash  = new Array;

  // store existent cookie values in an associative array
  for (i = 0; i < cookieArray.length; ++i) {
    if ((tmp = cookieArray[i].split('=')) != '')
      cookieHash[tmp[0]] = tmp[1];
  }

  cookieHash[id] = val;

  // write content of the associative array back
  cookieArray = new Array;
  for (var i in cookieHash)
    cookieArray[cookieArray.length] = i + '=' + escape(cookieHash[i]);
  document.cookie = cookieName + '=' + cookieArray.join('&');
} // end func setCookieVal


/**
 * Unsets cookie values.
 *
 * @param   string    Cookie name.
 * @access  public
 */
function unsetCookie(cookieName)
{
  document.cookie = cookieName + "=null";
} // end func unsetCookie


/**
 * Gets cookie value of a cookie entry.
 *
 * @param   string    Cookie name.
 * @param   string    Value identifier.
 * @return  string    Returns the value of the cookie entry.
 * @access  public
 */
function getCookieVal(cookieName, id)
{
  var valStr, start, end;

  valStr = getCookie(cookieName);

  if ((start = valStr.indexOf(id + '=')) != -1) {
    start += id.length + 1;
    if ((end = valStr.indexOf('&', start)) == -1)
      end = valStr.length;

    return valStr.substring(start, end);
  }

  return '';
} // end func getCookieVal


/**
 * Fixes rendering bug of IE.
 *
 * @access  public
 */
function fixButton(className)
{
  if (!(document.all && document.all[0].currentStyle))
    return;

  var body     = document.getElementsByTagName('body')[0];
  var elements = document.getElementsByTagName('input');

  for (var i = 0; i < elements.length; ++i) {
    if (!hasClassName(elements[i], className))
      continue;

    var node = document.createElement('span');
    node.className = 'hiddenText';
    node.innerHTML = elements[i].value;
    body.appendChild(node);
    elements[i].style.width = node.offsetWidth + 31 + 'px';
    elements[i].style.paddingLeft = '23px';
    body.removeChild(node);
    registerEvent(elements[i], 'mouseover', function(event) {swapButtonClassName(window.event.srcElement, '', 'Hover')});
    registerEvent(elements[i], 'mouseout', function(event) {swapButtonClassName(window.event.srcElement, 'Hover', '')});
    registerEvent(elements[i], 'mouseout', function(event) {swapButtonClassName(window.event.srcElement, 'Active', ''); window.event.srcElement.blur()});
    registerEvent(elements[i], 'mousedown', function(event) {swapButtonClassName(window.event.srcElement, 'Hover', 'Active'); window.event.srcElement.blur()});
    registerEvent(elements[i], 'mouseup', function(event) {swapButtonClassName(window.event.srcElement, 'Active', 'Hover'); window.event.srcElement.blur()});
  }
} // end func fixButton


function swapButtonClassName(el, from, to)
{
  var list = el.className.split(' ');
  var prefix = '';
  var suffix = 'Button' + from;

  for (var i = 0; i < list.length; ++i) {
    if (list[i].indexOf(suffix) == list[i].length - suffix.length) {
      if (prefix == '')
        prefix = list[i].substring(0, list[i].length - suffix.length);
      if (prefix != '')
        removeClassName(el, list[i]);
    }
  }

  if (prefix != '')
    el.className += ' ' + prefix + 'Button' + to;

  if (to != '')
    el.className += ' button' + to;
  if (from != '')
    removeClassName(el, 'button' + from);
} // end func swapButtonClassName


function isParentOf(parent, child)
{
  var node = child;

  while (node.parentNode != null) {
    if (node.parentNode == parent)
      return true;
    node = node.parentNode
  }
  return false;
} // end func isParentOf