-->
Bookmark and Share

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.

Browser Compatibility

Getting the pixel coordinates of an element can be a little tricky. The 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.