Revenge of the Menu Bar
See the demo page for the finished version of the code.Event Handlers for Menus
As with the menu bar buttons, we start by setting some event handlers in the tags for the menus.
<div id="menu3" class="menu" onmouseover="menuMouseover(event)"> <a class="menuItem" href="...">Menu 3 Item 1</a> <a class="menuItem" href="...">Menu 3 Item 2</a> <a class="menuItem" href="...">Menu 3 Item 3</a> <a class="menuItem" href="..." onclick="return false;" onmouseover="menuItemMouseover(event, 'menu3_4');"> <span class="menuItemText">Menu 3 Item 4</span> <span class="menuItemArrow">▶</span></a> <a class="menuItem" href="...">Menu 3 Item 5</a> <a class="menuItem" href="..." onclick="return false;" onmouseover="menuItemMouseover(event, 'menu3_6');"> <span class="menuItemText">Menu 3 Item 6</span> <span class="menuItemArrow">▶</span> </a> </div>
On each of the items that will have a sub menu we set the link's
onmouseover
event to call the function
menuItemMouseover().
As usual, the first argument is the event
object. The second gives the ID of the sub menu to be associated with the
item.
Also note the use of onclick="return false;"
on the item link.
This simply prevents the browser from trying to load the link's URL when it is
clicked on. This can be omitted should you want to actually link a page to the
item.
On the menu DIV itself, onmousover
is set to call the function
menuMouseover().
This time, only the event object needs to be
passed.
The sub menus are defined just like the main menus, using the same HTML format and style classes. They can in turn have items with sub menus assigned to them. Below is an example.
<div id="menu3_4" class="menu"> <a class="menuItem" href="...">Menu 3-4 Item 1</a> <div class="menuItemSep"></div> <a class="menuItem" href="...">Menu 3-4 Item 2</a> <a class="menuItem" href="...">Menu 3-4 Item 3</a> <div class="menuItemSep"></div> <a class="menuItem" href="...">Menu 3-4 Item 4</a> <a class="menuItem" href="...">Menu 3-4 Item 5</a> </div> <div id="menu3_6" class="menu" onmouseover="menuMouseover(event)"> <a class="menuItem" href="..." onclick="return false;" onmouseover="menuItemMouseover(event, 'menu3_6_1');"> <span class="menuItemText">Menu 3-6 Item 1</span> <span class="menuItemArrow">▶</span></a> <a class="menuItem" href="...">Menu 3-6 Item 2</a> <a class="menuItem" href="...">Menu 3-6 Item 3</a> </div> <div id="menu3_6_1" class="menu"> <a class="menuItem" href="...">Menu 3-6-1 Item 1</a> <a class="menuItem" href="...">Menu 3-6-1 Item 2</a> <a class="menuItem" href="...">Menu 3-6-1 Item 3</a> <a class="menuItem" href="...">Menu 3-6-1 Item 4</a> </div>
Note that the onmouseover
handler on the menu DIV is only
required if the any of its items have sub menus. Otherwise it can be left
off.
The menuItemMouseover()
function will handle the task of
displaying an item's sub menu while the menuMouseover()
function
will take care of hiding those same sub menus when they are not needed.
The Menu Item mouseover
Event Handler
This function is similar to the one that displays the main menu under a button. It must deactivate any currently active sub menu, position the designated sub menu and make it visible.
Again, it first identifies the item link element that fired the event.
Calling on the getContainerWith()
function it also identifies the
owning menu DIV element.
function menuItemMouseover(event, menuId) { var item, menu, x, y; // Find the target item element and its parent menu element. if (browser.isIE) item = getContainerWith(window.event.srcElement, "A", "menuItem"); else item = event.currentTarget; menu = getContainerWith(item, "DIV", "menu");
The menu element is needed because we'll be adding a user defined property
to it for keeping track of which sub menu is active. This is analogous to how
the activeButton
global variable was used to track the currently
active button on the menu bar.
In fact, the next step is to check this property, named
activeItem,
and close any sub menu it may be referencing. Then the
current item is recorded as the active one.
// Close any active sub menu and mark this one as active. if (menu.activeItem != null) closeSubMenu(menu); menu.activeItem = item;
As with the active button, we change the item's appearance by adding the
menuItemHighlight
style class to its className
property.
// Highlight the item element. item.className += " menuItemHighlight";
As this class was has the same settings as the link's :hover
pseudo-class, the item will appear remain highlighted even if the user moves
the mouse off of it.
The sub menu, just like the menus for the buttons, needs to be initialized the first time it is displayed.
// Initialize the sub menu, if not already done. if (item.subMenu == null) { item.subMenu = document.getElementById(menuId); if (item.subMenu.isInitialized == null) menuInit(item.subMenu); }
The code also saves a reference to the sub menu as a user defined property
on the item named subMenu.
This creates a chain of references:
activeButton
-> menu
-> activeItem
-> subMenu
-> activeItem
->
subMenu,
etc., which will be helpful in closing menus when needed.
But first, we still need to position the requested sub menu and make it
visible.