var fm_activeButton = null;
var fm_closeTimer = null;
var fm_activateOnMouseDown = true;
var fm_showMenuIcon = true;
var basePath = '';

/**
 * FoldedMenu
 *
 * @author    Keita Ito <ki@networker.de>
 * @version   $Id$
 */
function FoldedMenu(node)
{
  this.node = node;
  this.menuItems = new Array();


  /**
   * Sets nodeContent property of node.
   *
   * @access  public
   */
  FoldedMenu.prototype.setButtonLabel = function(content)
  {
    this.node.innerHTML                = content;
    this.node.style.paddingRight       = '15px';
    this.node.style.backgroundImage    = 'url(' + basePath + '/img/fmArrowDown.png)';
    this.node.style.backgroundPosition = 'right center';
    this.node.style.backgroundRepeat   = 'no-repeat';
  } // end func setButtonLabel


  /**
   * Sets nodeContent property of node.
   *
   * @access  public
   */
  FoldedMenu.prototype.setButtonHref = function(href)
  {
    this.node.href      = href;
    this.node.className = this.node.className.length ? this.node.className + ' fmMenuButton' : 'fmMenuButton';
  } // end func setButtonHref


  /**
   * Adds menu item.
   *
   * @param   MenuItem
   * @access  public
   */
  FoldedMenu.prototype.addMenuItem = function(menuItem)
  {
    this.menuItems[this.menuItems.length] = menuItem;
  } // end func addMenuItem


  /**
   * Creates dynamic menu.
   *
   * @access  public
   */
  FoldedMenu.prototype.create = function()
  {
    if (this.node == null)
      return false;

    var sm = document.createElement('div');
    var id = this.node.id + 'Menu';

    sm.className = 'fmMenu';
    sm.setAttribute('id', id);
    if (hasClassName(this.node, 'fmMenuButton'))
      sm.className += ' topLevel';
    registerEvent(sm, 'mouseover', function(e) {fm_menuMouseOver(e)});

    if (hasClassName(this.node, 'fmMenuButton')) {
      registerEvent(this.node, 'mouseover', function(e) {fm_buttonMouseOver(e, id)});
      registerEvent(this.node, 'click', function(e) {fm_buttonClick(e, id)});
    } else if (hasClassName(this.node, 'fmMenu')) {
      registerEvent(this.node, 'mouseover', function(e) {fm_menuMouseOver(e)});
    } else if (hasClassName(this.node, 'fmMenuItem')) {
      registerEvent(this.node, 'mouseover', function(e) {fm_itemMouseOver(e, id)});
    }

    var html = '';
    for (var i = 0; i < this.menuItems.length; ++i)
      html += this.menuItems[i].getLinkHtml() + '\n';
    document.getElementsByTagName('body')[0].appendChild(sm);
    sm.innerHTML = html;
  } // end func create

} // end class FoldedMenu


/**
 * FoldedMenuItem
 *
 * @author    Keita Ito <ki@networker.de>
 * @version   $Id$
 */
function FoldedMenuItem(value)
{
  this.label      = (value == null) ? '' : value;
  this.href       = null;
  this.id         = null;
  this.isDisabled = false
  this.src        = null


  /**
   * Sets value of href.
   *
   * @param   string    Value of href.
   * @access  public
   */
  FoldedMenuItem.prototype.setHref = function(href)
  {
    this.href = href;
  } // end func setHref


  /**
   * Sets value of src.
   *
   * @param   string    Value of src.
   * @access  public
   */
  FoldedMenuItem.prototype.setSrc = function(src)
  {
    this.src = src;
  } // end func setSrc


  /**
   * Sets value of id.
   *
   * @param   string    Value of id.
   * @access  public
   */
  FoldedMenuItem.prototype.setId = function(id)
  {
    this.id = id;
  } // end func setId


  /**
   * Sets value of setIsDisabled.
   *
   * @param   boolean   Value of isDisabled.
   * @access  public
   */
  FoldedMenuItem.prototype.setIsDisabled = function(isDisabled)
  {
    this.isDisabled = isDisabled;
  } // end func setIsDisabled


  /**
   * Gets HTML code for menu item.
   *
   * @return  string
   * @access  public
   */
  FoldedMenuItem.prototype.getLinkHtml = function()
  {
    if (this.label == null || this.label == '')
      return '<div class="fmSeparator"></div>';

    var _class = ' class="fmMenuItem';
    if (this.isDisabled)
      _class += ' disabled';
    _class += '"';

    var _label       = this.label;
    var _href        = ' href="' + ((this.isDisabled || this.href == null || this.href == '') ? 'javascript:void(0)' : this.href) + '"';
    var _onclick     = '';
    var _onmouseover = '';
    var _id          = '';
    var _style       = '';

    if (this.src !== null && this.src !== '' && fm_showMenuIcon)
      _style = ' style="background-image: url(' + this.src + '); padding-left: 24px"';

    if (this.id == null || this.id == '') {
      if (this.href == null || this.href == '' || this.isDisabled)
        _onclick = ' onclick="this.blur(); return false"';
    } else if (!this.isDisabled) {
      _id          = ' id="' + this.id + '"';
      _onmouseover = ' onmouseover="fm_itemMouseOver(event, \'' + this.id + 'Menu\')"';
      _label       = '<span class="fmMenuItemText">' + this.label + '</span><span class="fmMenuItemArrow">&#9656;</span>';
    }

    return '<a' + _class + _href + _id + _style + _onclick + _onmouseover + '>' + _label + '</a>';
  } // end func getLinkHtml

} // end class FoldedMenuItem


function fm_buttonClick(event, menuId)
{
  var button = window.event ? window.event.srcElement : event.currentTarget;

  while (button.tagName != 'A')
    button = button.parentNode;

  if (button.blur)
    button.blur();

  if (button.menu == null) {
    button.menu = getNode(menuId);
    if (button.menu.isInitialized == null)
      fm_initMenu(button.menu);
  }

  if (!fm_activateOnMouseDown) {
    if (button.onmouseout == null)
      button.onmouseout = fm_mouseOut;
    if (button == fm_activeButton)
      return false;
  }

  if (fm_activeButton != null) {
    if (fm_closeTimer > 0)
      clearTimeout(fm_closeTimer);
    fm_resetButton(fm_activeButton);
  }

  if (button != fm_activeButton) {
    fm_buttonMouseOut(button);
    fm_activeButton = button;
  } else {
    fm_activeButton = null;
  }

  return false;
} // end func fm_buttonClick


function fm_buttonMouseOver(event, menuId)
{
  if (!fm_activateOnMouseDown && fm_activeButton == null) {
    fm_buttonClick(event, menuId);
    return;
  }

  var button = window.event ? window.event.srcElement : event.currentTarget;

  while (button.tagName != 'A')
    button = button.parentNode;

  if (fm_activeButton == null)
    return;

  if (fm_activeButton != button) {
    fm_buttonClick(event, menuId);
  } else if (fm_closeTimer > 0) {
    clearTimeout(fm_closeTimer);
  }
} // end func fm_buttonMouseOver


function fm_buttonMouseOut(button)
{
  button.className += ' fmMenuButtonActive';

  if (!fm_activateOnMouseDown) {
    if (button.onmouseout == null)
      button.onmouseout = fm_mouseOut;
    if (button.menu.onmouseout == null)
      button.menu.onmouseout = fm_mouseOut;
  }

  var x = getPageOffsetLeft(button);
  var y = getPageOffsetTop(button) + button.offsetHeight;

  if (document.all && document.all[0].currentStyle) {
    x += button.offsetParent.clientLeft;
    y += button.offsetParent.clientTop;
  }

  // increase menu width
  if (button.offsetWidth > button.menu.offsetWidth) {
    button.menu.style.width = button.offsetWidth + 'px';

    var itemList = button.menu.getElementsByTagName('A');
    if (itemList.length > 0) {
      var itemWidth = itemList[0].offsetWidth;

      var i, j, textEl, arrowEl;
      for (i = 0; i < itemList.length; ++i) {
        spanList = itemList[i].getElementsByTagName('SPAN');
        textEl  = null;
        arrowEl = null;
        for (j = 0; j < spanList.length; ++j) {
          if (hasClassName(spanList[j], 'fmMenuItemText'))
            textEl = spanList[j];
          if (hasClassName(spanList[j], 'fmMenuItemArrow'))
            arrowEl = spanList[j];
        }
        if (textEl != null && arrowEl != null) {
          textEl.style.paddingRight = (button.offsetWidth - (textEl.offsetWidth + arrowEl.offsetWidth)) + 'px';
        }
      }
    }
  }

  var maxX;

  if (document.all && document.all[0].currentStyle) {
    maxX = Math.max(document.documentElement.scrollLeft, document.body.scrollLeft) + (document.documentElement.clientWidth != 0 ? document.documentElement.clientWidth : document.body.clientWidth);
  } else if (browser.isOP) {
    maxX = document.documentElement.scrollLeft + window.innerWidth;
//  } else if (browser.isNS) {
  } else {
    maxX = window.scrollX + window.innerWidth;
  }
  maxX -= button.menu.offsetWidth;

  if (x > maxX)
    x = Math.max(0, x + button.offsetWidth - button.menu.offsetWidth);

  button.menu.style.left = x + 'px';
  button.menu.style.top  = y + 'px';
  button.menu.style.visibility = 'visible';

  if (button.menu.iframeEl != null) {
    button.menu.iframeEl.style.left    = button.menu.style.left;
    button.menu.iframeEl.style.top     = button.menu.style.top;
    button.menu.iframeEl.style.width   = button.menu.offsetWidth + 'px';
    button.menu.iframeEl.style.height  = button.menu.offsetHeight + 'px';
    button.menu.iframeEl.style.display = '';
  }
} // end func fm_buttonMouseOut


function fm_resetButton(button)
{
  if (button == null)
    return;

  removeClassName(button, 'fmMenuButtonActive');

  if (button.menu != null) {
    fm_closeSubmenu(button.menu);
    button.menu.style.visibility = 'hidden';

    if (button.menu.iframeEl != null)
      button.menu.iframeEl.style.display = 'none';
  }
} // end func fm_resetButton


function fm_menuMouseOver(event)
{
  var menu = window.event ? getContainerWith(window.event.srcElement, 'DIV', 'fmMenu') : event.currentTarget;

  if (menu.activeItem != null);
    fm_closeSubmenu(menu);
} // end func fm_menuMouseOver


function fm_itemMouseOver(event, menuId)
{
  var item = window.event ? getContainerWith(window.event.srcElement, 'A', 'fmMenuItem') : event.currentTarget;
  var menu = getContainerWith(item, 'DIV', 'fmMenu');

  if (menu.activeItem != null)
    fm_closeSubmenu(menu);
  menu.activeItem = item;

  item.className += ' fmMenuItemHighlight';

  if (item.subMenu == null) {
    item.subMenu = getNode(menuId);
    if (item.subMenu.isInitialized == null)
      fm_initMenu(item.subMenu);
  }

  if (!fm_activateOnMouseDown && item.subMenu.onmouseout == null)
    item.subMenu.onmouseout = fm_mouseOut;

  var x = getPageOffsetLeft(item) + item.offsetWidth;
  var y = getPageOffsetTop(item);

  var maxX, maxY;

  if (item.subMenu.currentStyle) {
    maxX = Math.max(document.documentElement.scrollLeft, document.body.scrollLeft) + (document.documentElement.clientWidth != 0 ? document.documentElement.clientWidth : document.body.clientWidth);
    maxY = Math.max(document.documentElement.scrollTop, document.body.scrollTop) + (document.documentElement.clientHeight != 0 ? document.documentElement.clientHeight : document.body.clientHeight);
  } else if (browser.isOP) {
    maxX = document.documentElement.scrollLeft + window.innerWidth;
    maxY = document.documentElement.scrollTop  + window.innerHeight;
//  } else if (browser.isNS) {
  } else {
    maxX = window.scrollX + window.innerWidth;
    maxY = window.scrollY + window.innerHeight;
  }
  maxX -= item.subMenu.offsetWidth;
  maxY -= item.subMenu.offsetHeight;

  if (x > maxX)
    x = Math.max(0, x - item.offsetWidth - item.subMenu.offsetWidth + (menu.offsetWidth - item.offsetWidth));
  y = Math.max(0, Math.min(y, maxY));

  item.subMenu.style.left       = x + 'px';
  item.subMenu.style.top        = y + 'px';
  item.subMenu.style.visibility = 'visible';

  if (item.subMenu.iframeEl != null) {
    item.subMenu.iframeEl.style.left    = item.subMenu.style.left;
    item.subMenu.iframeEl.style.top     = item.subMenu.style.top;
    item.subMenu.iframeEl.style.width   = item.subMenu.offsetWidth + 'px';
    item.subMenu.iframeEl.style.height  = item.subMenu.offsetHeight + 'px';
    item.subMenu.iframeEl.style.display = '';
  }

  if (window.event) {
    window.event.cancelBubble = true;
  } else {
    event.stopPropagation();
  }
} // end func fm_itemMouseOver


function fm_closeSubmenu(menu)
{
  if (menu == null || menu.activeItem == null)
    return;

  if (menu.activeItem.subMenu != null) {
    fm_closeSubmenu(menu.activeItem.subMenu);
    menu.activeItem.subMenu.style.visibility = 'hidden';

    if (menu.activeItem.subMenu.iframeEl != null)
      menu.activeItem.subMenu.iframeEl.style.display = 'none';

    menu.activeItem.subMenu = null;
  }

  removeClassName(menu.activeItem, 'fmMenuItemHighlight');
  menu.activeItem = null;
} // end func fm_closeSubmenu


function fm_mouseOut(event)
{
  if (fm_activeButton == null)
    return;

  var el;
  if (window.event) {
    el = window.event.toElement;
  } else if (event.relatedTarget != null) {
    el = (event.relatedTarget.tagName ? event.relatedTarget : event.relatedTarget.parentNode);
  }

  if (getContainerWith(el, 'DIV', 'fmMenu') == null)
    fm_closeTimer = setTimeout('fm_resetButton(fm_activeButton);fm_activeButton = null;', 100);
} // end func fm_mouseOut


/**
 * Inits menu.
 *
 * @param   FoldedMenu
 * @access  public
 */
function fm_initMenu(menu)
{
  var spanList;
  if (menu.currentStyle) {
    menu.style.lineHeight = '2.5ex';
    spanList = menu.getElementsByTagName('SPAN');
    for (i = 0; i < spanList.length; ++i) {
      if (hasClassName(spanList[i], 'fmMenuItemArrow')) {
        spanList[i].style.fontFamily = 'Webdings';
        spanList[i].firstChild.nodeValue = '4';
      }
    }
  }

  var itemList = menu.getElementsByTagName('A');
  if (itemList.length == 0)
    return;

  var itemWidth = itemList[0].offsetWidth;

  var i, j, textEl, arrowEl;
  for (i = 0; i < itemList.length; ++i) {
    spanList = itemList[i].getElementsByTagName('SPAN');
    textEl  = null;
    arrowEl = null;
    for (j = 0; j < spanList.length; ++j) {
      if (hasClassName(spanList[j], 'fmMenuItemText'))
        textEl = spanList[j];
      if (hasClassName(spanList[j], 'fmMenuItemArrow'))
        arrowEl = spanList[j];
    }
    if (textEl != null && arrowEl != null) {
      textEl.style.paddingRight = (itemWidth - (textEl.offsetLeft + textEl.offsetWidth + arrowEl.offsetWidth)) + 'px';
      // remove negative right margin to fix display bug
      if (browser.isOP)
        arrowEl.style.marginRight = '0px';
    }
  }

  if (document.all && document.all[0].currentStyle) {
    // fix IE hover problem by setting explicit width on first item
    var w = itemList[0].offsetWidth;
    itemList[0].style.width = w + 'px';
    var dw = itemList[0].offsetWidth - w;
    w -= dw;
    itemList[0].style.width = w + 'px';

    menu.iframeEl = menu.parentNode.insertBefore(document.createElement('IFRAME'), menu);
    menu.iframeEl.style.display  = 'none';
    menu.iframeEl.style.position = 'absolute';
    menu.iframeEl.style.filter   = "alpha(opacity=0)";
  }

  menu.isInitialized = true;
} // end func fm_initMenu


function fm_pageMouseDown(event)
{
  if (fm_activeButton == null)
    return;

  var el = document.all ? window.event.srcElement : (event.target.tagName ? event.target : event.target.parentNode);
  if (el == fm_activeButton)
    return;

  if (getContainerWith(el, 'DIV', 'fmMenu') == null) {
    fm_resetButton(fm_activeButton);
    fm_activeButton = null;
  }
} // end func fm_pageMouseDown


if (fm_activateOnMouseDown)
  registerEvent(document, 'mousedown', fm_pageMouseDown);
