/*
** v2.0.20060106
**
** gMenu is a customizable collection of JavaScript routines which can be used
** to quickly create platform independent drop down menus.
**
** gMenu has been tested on IE 6.0, Netscape 7.1, FireFox 1.0, and Opera 8.5
**
** Copyright (C) 2004-2005  Brain Book Software LLC (formfields.com, info@formfields.com)
**
** This program is free software; you can redistribute it and/or
** modify it under the terms of the GNU General Public License
** as published by the Free Software Foundation; either version 2
** of the License, or (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
**
** See http://www.gnu.org/ for an up-to-date copy of the GPL.
*/

function gMenu(objName, prefix)
{
  var prefix = prefix;
  if (prefix == null)
    prefix = "";

  var objName = objName; // wie heisst die Instanz dieser Klasse? (wird für SetTimeout benötigt)

  // The maximum depth of sub menus (not including the root menu)
  var MAX_MENUS = 5;

  // The number of milliseconds to delay before hiding a menu
  var HIDE_MENU_DELAY = 1000;

  // The number of pixels to offset the top-left corner of the top menu from a
  // root menu item.
  this.TOP_MENU_LEFT_OFFSET = 0;
  this.TOP_MENU_TOP_OFFSET = 0;

  this.SUB_MENU_HORIZONTAL_OFFSET = -1;
  this.SUB_MENU_TOP_OFFSET = 0;

  this.TOP_MENU_POSITION = "bottom";  // wo soll das 1.Untermenü angezeigt werden? "bottom" oder "right"


  // This array keeps track of whether the mouse is over a given menu.
  var menuFocus = new Array();
  for (i = 1; i <= MAX_MENUS; i++)
    menuFocus[prefix + "menu" + i] = false;

  var activeRootMenuId;

  var curItemHasChildren = false;

  var hideMenuCounter = 0;

  this.getPosOffset = function(obj, offsetType)
  {
    var totalOffset= (offsetType == "left") ? obj.offsetLeft : obj.offsetTop;
    var parentElement = obj.offsetParent;

    while (parentElement != null)
    {
      totalOffset = (offsetType == "left") ? totalOffset + parentElement.offsetLeft : totalOffset + parentElement.offsetTop;
      parentElement = parentElement.offsetParent;
    }

    return totalOffset;
  }


  this.focusMenu = function(menu)
  {
    menuFocus[menu.id] = true;
  }


  // Mögliche CCS-Styles:
  // subMenuItemLeaf, subMenuItemLeafHighlight, subMenuItemRight, subMenuItemRightHighlight, subMenuItemLeft, subMenuItemLeftHighlight

  // Highlight current item and "unhighlight" other items in current menu
  this.setHighlighting = function(selectedNode)
  {
    for (i = 0; i < (selectedNode.parentNode).childNodes.length; i++)
    {
      var curNode = (selectedNode.parentNode).childNodes[i];
      if (curNode.id == selectedNode.id)
      {
        if(curNode.className.substr(curNode.className.length-9) != "Highlight")
          curNode.className += "Highlight";
      }
      else
      {
        if(curNode.className.substr(curNode.className.length-9) == "Highlight")
          curNode.className = curNode.className.substr(0, curNode.className.length-9);
      }
    }
  }

  // Fill in the sub menus. This is done every time a menu pops up.
  this.drawSubMenu = function(menuId, menuArray, openDirection)
  {
    var menu = document.getElementById(menuId);
    var html = '';
    for (i = 0; i < menuArray.length; i++)
    {
      var cssClass;
      if(menuArray[i][2] == null)
        cssClass = prefix + 'subMenuItemLeaf';
      else if(openDirection == 'left')
        cssClass = prefix + 'subMenuItemLeft';
      else
        cssClass = prefix + 'subMenuItemRight';

      html += '<div id="' + menuId + "-" + i + '" class="' + cssClass + '"'
        + ' onmouseover="' + (menuArray[i][2] == null ? '' : objName + '.showMenu(\'' + menuId + '\', ' + menuArray[i][2] + ', \'' + openDirection + '\', this);') + objName + '.highlightIfNeeded(this);"'
        + (menuArray[i][1] != null ? ' style="cursor:pointer;" onclick="window.location=\'' + menuArray[i][1] + '\';"' : '')
        + '>'
        + menuArray[i][0]
        + '</div>';
    }
    menu.innerHTML = html;
    return menu;
  }

  // Shows a level 1 menu, right below the root menus.
  this.showTopMenu = function(curMenu, menuArray, openDirection)
  {
     if(!document.getElementById(prefix + 'menu1'))
      return; // Seite noch nicht fertig geladen

    var curMenuLink = document.getElementById(curMenu.id + '_link');
    if (curMenuLink.className != prefix + "rootMenuActive_link")
      curMenuLink.className = prefix + 'rootMenuHighlight_link';

    if(menuArray == null)
    {
      subMenu = document.getElementById(prefix + 'menu1');
      subMenu.style.visibility = 'hidden'
    }
    else
    {
      if (menuFocus[prefix + 'menu1'])
        subMenu = document.getElementById(prefix + 'menu1');
      else
        subMenu = this.drawSubMenu(prefix + 'menu1', menuArray, openDirection);

      // daneben anzeigen
      if(this.TOP_MENU_POSITION == "right")
      {
        subMenu.style.top = this.getPosOffset(curMenu, "top") + this.TOP_MENU_TOP_OFFSET + "px";
        subMenu.style.left = this.getPosOffset(curMenu, "left") + curMenu.offsetWidth + this.TOP_MENU_LEFT_OFFSET + "px";
      }
      else
      { // unterhalb anzeigen
        subMenu.style.top = this.getPosOffset(curMenu, "top") + curMenu.offsetHeight + this.TOP_MENU_TOP_OFFSET + "px";
        subMenu.style.left = this.getPosOffset(curMenu, "left") + this.TOP_MENU_LEFT_OFFSET + "px";
        // minimale Breite des Menüs anpassen -> funktioniert nicht in Opera
        if(!window.opera)
        {
          subMenu.style.width = "";
          if(curMenuLink.offsetWidth > subMenu.offsetWidth)
            subMenu.style.width = curMenuLink.offsetWidth + "px";
        }
      }

      subMenu.style.visibility = 'visible';
    }
  
    menuFocus[curMenu.id] = true;
    activeRootMenuId = curMenu.id;
    curItemHasChildren = true;
    this.hideMenus2()
  }

  this.highlightIfNeeded = function(curItem)
  {
    if(curItem.className.substr(curItem.className.length-9) != "Highlight")
      this.setHighlighting(curItem);
    curItemHasChildren = !(curItem.className.substr(0, 15) == "subMenuItemLeaf");
  }

  // Shows a level2..leveln menu, directly to the right of the selected item.
  this.showMenu = function(curMenuId, menuArray, openDirection, curItem)
  {
    if(curItem.className.substr(curItem.className.length-9) == "Highlight")
      return;

    var curMenu = document.getElementById(curMenuId);
    var subMenuId = prefix + 'menu' + (eval(curMenuId.substr(curMenuId.length-1))+ 1);
    var subMenu;
    if (menuFocus[subMenuId])
      subMenu = document.getElementById(subMenuId);
    else
      subMenu = this.drawSubMenu(subMenuId, menuArray, openDirection);

    subMenu.style.top = curMenu.offsetTop + curItem.offsetTop + this.SUB_MENU_TOP_OFFSET + "px";

    if(openDirection == 'left')
      subMenu.style.left = curMenu.offsetLeft - subMenu.offsetWidth - this.SUB_MENU_HORIZONTAL_OFFSET + "px";
    else
      subMenu.style.left = curMenu.offsetLeft + curMenu.offsetWidth + this.SUB_MENU_HORIZONTAL_OFFSET + "px";

    subMenu.style.visibility = 'visible';

    var subSubMenuId = prefix + 'menu' + (eval(curMenuId.substr(curMenuId.length-1))+ 2);
    this.hideMenu(subSubMenuId, subMenuId);
  }

  // Recursively check all sub menus of the current menu.
  // If the mouse has left a menu and all its sub menus then hide that menu.
  this.hideMenu = function(curMenuId, parentId)
  { 
    var curMenu = document.getElementById(curMenuId);
    var hideChild = true;
    var childId = prefix + 'menu' + (eval(curMenuId.substr(curMenuId.length-1))+ 1);

    var child = document.getElementById(childId);
    if (child != null) {
      hideChild = this.hideMenu(child.id, curMenu.id);
    }

    if (!menuFocus[curMenuId] && hideChild && (!menuFocus[parentId] || !curItemHasChildren)) {
      if(curMenu) // sonst Fehler falls Seite noch nicht fertig geladen ist
        curMenu.style.visibility = 'hidden';
      return true;
    } else {
      return false;
    }
  }

  this.hideMenus = function()
  {
    if (--hideMenuCounter > 0)
      return;
    this.hideMenus2()
  }

  this.hideMenus2 = function()
  {
    var i = 1;
    var menusHidden = this.hideMenu(prefix + 'menu1', activeRootMenuId);
    while ( (rootMenu = document.getElementById(prefix + "rootMenu" + (i++))) )
    {
      var rootMenu_link = document.getElementById(rootMenu.id + '_link');
      if ( (!menuFocus[rootMenu.id] && activeRootMenuId == rootMenu.id && menusHidden && rootMenu_link.className != (prefix + "rootMenuActive_link"))
           || (activeRootMenuId != rootMenu.id && rootMenu_link.className == (prefix + "rootMenuHighlight_link")) ) {
        rootMenu_link.className = prefix + "rootMenu_link";
      }
    }
  }

  this.delayHideMenu = function(menu)
  {
    menuFocus[menu.id] = false;
    hideMenuCounter++;
    setTimeout(objName + '.hideMenus()', HIDE_MENU_DELAY);
  }
}