Revenge of the Menu Bar
See the demo page for the finished version of the code.Activating a Button and Menu
To activate a button, the "menuButtonActive" style class is added to its
className
property to change its appearance. Then its menu
is positioned just below it and made visible.
function depressButton(button) { var x, y; // Update the button's style class to make it look like it's // depressed. button.className += " menuButtonActive"; // Position the associated drop down menu under the button and // show it. x = getPageOffsetLeft(button); y = getPageOffsetTop(button) + button.offsetHeight; button.menu.style.left = x + "px"; button.menu.style.top = y + "px"; button.menu.style.visibility = "visible"; }
getPageOffsetLeft()
and getPageOffsetTop()
are
used to find the button's position on the page. Adding the height of the button
gives the pixel coordinates just below it. The menu is then moved there and
made visible.
offsetLeft
and offsetTop
properties used to calculate
these do not always reflect the element's true position on a given page,
depending on the browser, style settings used and the menu bar's location
within the page.
For individual situations you may need to adjust the computed x
and y
values by adding constants. For example, in the
demo, this code is added just before the menu is moved:
// For IE, adjust position. if (browser.isIE) { x += button.offsetParent.clientLeft; y += button.offsetParent.clientTop; }
Deactivating a Button and Menu
Deactivating a button is much simpler. We just need to remove the
menuButtonActive
class from the button link and make the menu
invisible.
function resetButton(button) { // Restore the button's style class. removeClassName(button, "menuButtonActive"); // Hide the button's menu, first closing any sub menus. if (button.menu != null) { closeSubMenu(button.menu); button.menu.style.visibility = "hidden"; } }
Any sub menus need to be closed as well and this is done with a call to
closeSubMenu().
Details on sub menus are given further on. For
now, let's look at the results of the code so far. (Note that the menu items in
these samples have been disabled, so clicking on them will not load a new
page.)
You can click on any button to activate or deactivate it. Note that if you click on one button while another is active, the old one is reset and the new one is activated.
Next, we want to add some code to handle mouseovers on the buttons. The effect will be to make the active button "jump" as you move the mouse from one button to another.
The Button onmouseover
Event Handler
To implement this, we first add another event handler to the button
tags. This one calls the function buttonMouseover()
on
mouseover
events, naturally enough.
<a class="menuButton" href="" onclick="return buttonClick(event, 'menu1');" onmouseover="buttonMouseover(event, 'menu1');" >Button 1</a>
It takes the same two arguments used for buttonClick(),
the
event object and the ID of the menu associated with the button.
function buttonMouseover(event, menuId) { var button; // Find the target button element. if (browser.isIE) button = window.event.srcElement; else button = event.currentTarget; // If any other button menu is active, make this one active instead. if (activeButton != null && activeButton != button) buttonClick(event, menuId); }
Once again, it first identifies the link element for the button. Then it
checks to see if some other button is currently active, using the
activeButton
global. If so, it deactivates that button and then
calls buttonClick()
to activate this one.
In effect, it acts just like buttonClick()
except that it only
works when some button is already active. You can try it below to see the
effect.
Now, when a button is active, you can move the mouse from one button to another and it will switch the activate button automatically. This mimics the behaviour commonly seen in application menu bars.
Unfortunately, the only way to deactivate the buttons entirely is to click on the active button again. We'll fix this next so that you can click anywhere on the page to clear the active button.