How to Build Pull-Down Menus with JavaScript
JavaScript is great for making things happen on Web pages. But Web sites must ultimately serve their users, and there are many ways in which you can use JavaScript to enhance the user experience by improving the user interface of your sites.
Modern operating systems have trained users to expect certain behaviors in response to their actions. For example, when people see a row of words at the very top of a screen, they recognize it as a menu bar, and they expect pull-down menus. There aren't such things as part of the basic HTML toolkit, but you can accomplish the effect with a well-turned JavaScript. The reason that we have to do this sort of backing-and-filling is that from a user interface standpoint, the Web threw out the baby with the bath water. With HTML, we gained lots of great new capabilities (like hyperlinking), but virtually forgot about twenty years of user interface design.
Pull-Down Menus
One of the best reasons to use JavaScript and DHTML is to improve the user interface and the surfer's browsing experience. Script 1, which works in version 4 (and later) browsers, emulates the pull-down menus of a standard application, as shown in Figures 1 and 2.
Figure 1 The menus when they're up...
Figure 2 ...and when one of them comes down.
To create a pull-down menu:
stdBrowser = (document.getElementById) ? true : false
function toggleMenu(currElem, nextPos) {
menuObj = (stdBrowser) ? document.getElementById(currElem).style : eval("document." + currElem)
This line sets up the menuObj variable to the menu that we want to toggle. If we're in a standards-supporting browser, we use getElementById and currElem to get the object. If we're in Netscape 4.x, use the eval method instead.
if (toggleMenu.arguments. length == 1) { nextPos = (parseInt(menuObj.top) == -5) ? -90 : -5 }
If only one parameter was passed to toggleMenu (remember, nextPos was optional), then nextPos needs to be set here. The property toggleMenu.arguments.length contains how many parameters were passed to the function, so the next line will only be executed if nextPos wasn't passed. In that line, we toggle the current placement of the menu: if the current value of top is Ð5, then nextPos is set to Ð90, otherwise, nextPos is set to Ð5. This will be the new position of the pull-down menu.
menuObj.top = (stdBrowser) ? nextPos + "px" : nextPos
This line resets the menu to the desired place. If our visitor has an up-to-date browser, then we need to add px (for "pixels") on the end when we set top. Otherwise, it's a numeric value.
<DIV ID="fileMenu" CLASS="menu" onMouseover="toggleMenu('fileMenu', -5)" onMouseout="toggleMenu ('fileMenu',-90)">
For the browsers that support onMouseover and onMouseout on DIVs (we handle the ones that don't in the next step), either rolling over the menu or rolling off the menu will trigger a call to toggleMenu. When we roll over the menu, we know that the user wants to bring the menu down, so we pass the name of the menu and the next position for it, -5. When we roll off the menu, we know that the user wants the menu to snap back up again, so we pass the menu name plus a new position of Ð90.
<A HREF="javascript: toggleMenu('fileMenu')">File</A>
On browsers that can't handle rollovers on DIV tags (such as Netscape 4), the only way to toggle the placement of the menu is to click on the menu title. In this line, clicking on the word "File" will pull the menu up when it's down, and vice versa. Consequently, when this link is clicked, the toggleMenu function is called (with only one parameter) to toggle the placement of everything within the fileMenu <DIV>.
First, check to see if the browser supports the W3C DOM, i.e., that it's a modern browser that supports current standards.
This line starts a new function, toggleMenu(), which is passed the variable currElem. This variable is the current element that the user has chosen to toggle. The variable nextPos contains where you want to set the top position of the menu (in pixels, with the zero point being the top of the browser window). This parameter is optional (see step 4 to see how this is handled).