The JavaScript Menu Component

Creating Cross-Browser Dynamic HTML Menus

By Gary Smith


Part 2: New Features


Send comments and questions about this article to View Source.

The free-to-the-public JavaScript Menu component enables you to build customized floating menus from pure, cross-browser Dynamic HTML (DHTML) and object-oriented JavaScript. It provides the pull-down menu element that's common in most graphical user interfaces (GUIs) and thus can improve both the navigation and the real estate of your web pages. And it's not only cross-browser, but also cross-platform (running on Unix, Mac, and Windows).

This is my second article on the JavaScript Menu component. Since my first article, The JavaScript Menu Component: Creating Cross-Browser Dynamic HTML Menus, I've updated the JavaScript Menu code to include several new features, such as drag-and-drop menus, static menus, and tracking menus. In this article I'll discuss many of the new Menu component features. (Note that only version 4.0 and 5.0 browsers will display the DHTML menus; 3.0 browsers will simply ignore them.) If you're using an older version of the Menu component and want to take advantage of the new features, you'll need to upgrade to the new version of the menu.js library that goes with this article. (Don't worry, it's all backward compatible.)

I'll assume you're familiar with the basic syntax of the JavaScript language and that you've already read my first article on the Menu component, which covers the basics of adding menus to web pages. Please check out the Frequently Asked Questions (FAQ) page for the Menu component if you have specific questions. If your questions aren't answered in the FAQ page, send me email. I'll try to keep the FAQ page updated with frequent questions, based on user feedback. I also plan to find ways to improve the ease of deployment of the Menu component based on your feedback.

A QUICK REVIEW

Let's quickly review the three basic steps to add a menu to your web page, as described in detail in my first article:

  1. Copy and paste the following <SCRIPT> tags into your web page to add the menu.js JavaScript library:
    <SCRIPT LANGUAGE="JavaScript1.2" SRC="http://developer.netscape.com/viewsource/smith_menu/menu.js"></SCRIPT>
  2. Copy and paste the following menu script:
    <SCRIPT LANGUAGE="JavaScript1.2">
        var myMenu = new Menu();
        myMenu.addMenuItem("my menu item A");
        myMenu.addMenuItem("my menu item B");
        myMenu.addMenuItem("my menu item C");
        myMenu.addMenuItem("my menu item D");
        myMenu.writeMenus();
    </SCRIPT>
  3. Copy and paste the following link to display the myMenu menu:
    <A HREF="javascript:window.showMenu(window.myMenu);">display myMenu</A>

To see what this menu object displays, click the following link:

display myMenu

For your benefit, I've also created a Simple Menu page that contains this simplified code. View the source of the Simple Menu page (by choosing Page Source from the View menu when you're in the page) to see how it's done. For more detailed information on these basic steps, please refer to my previous article.

DRAG-AND-DROP MENUS

Drag and drop is one of the new features I added to this version of the Menu component. By default, all of your menus will become draggable with the new version of menu.js. To drag your menu, click on it and then drag it wherever you want within your web page.

You can try this new feature with any of the menus displayed in this article since they're all draggable. To try it now, roll your mouse over the following link and then drag it:

myMenu

If you want to disable the drag-and-drop feature for a menu, set the disableDrag property to true for that particular menu, as shown in Example 1. The menu will no longer be draggable.


Example 1

<SCRIPT LANGUAGE="JavaScript1.2">
    window.myMenu = new Menu();
    
    myMenu.addMenuItem("my menu item A");
    myMenu.addMenuItem("my menu item B");
    myMenu.addMenuItem("my menu item C");
    myMenu.addMenuItem("my menu item D");
	
    myMenu.disableDrag = true;
    
    myMenu.writeMenus();
</SCRIPT>


Moving on, the next section illustrates another useful new feature of the Menu component.

STATIC MENUS

By default, menus are set to be hidden when the mouse focus is removed from them by the user. You can change this default behavior so that your menus become static and don't disappear. Example 2 shows how to disable the default "hide" feature by setting the disableHide property to true.


Example 2

<SCRIPT LANGUAGE="JavaScript1.2">
<!--
    window.myMenu2 = new Menu("Example 2");

    myMenu2.addMenuItem("red", "document.bgColor='red'");
    myMenu2.addMenuItem("white", "document.bgColor='white'");
    myMenu2.addMenuItem("blue", "document.bgColor='blue'");

    myMenu2.disableHide = true;

    myMenu2.writeMenus();
//-->
</SCRIPT>


Notice this example passes actions to change the document bgColor property of this page to red, white, and blue. To see what this menu object displays, roll your mouse over the following link:

myMenu2

Assuming the drag-and-drop property isn't disabled, you can drag this static menu into the corner of the page and leave it there for later.

If you really want to make a static menu go away, you can click on the menu with the right mouse button, or you can drag it out of the way. The following section describes another type of static menu, this one enabling menu tracking as well.

TRACKING MENUS

The enableTracker property, another new menu feature, enables you to set your menus to always track and stay within the visible area of your web page. In other words, when you scroll the document up or down, this property will enable your menu to follow where you scroll to in your page and keep track of the relative position. Example 3 shows you how to take advantage of this feature by setting the enableTracker property to true.


Example 3

<SCRIPT LANGUAGE="JavaScript1.2">
<!--
    window.myMenu3 = new Menu("Example 3");

    myMenu3.addMenuItem("red", "document.bgColor='red'");
    myMenu3.addMenuItem("white", "document.bgColor='white'");
    myMenu3.addMenuItem("blue", "document.bgColor='blue'");
    myMenu3.addMenuItem("green", "document.bgColor='green'");

    myMenu3.enableTracker = true;

    myMenu3.writeMenus();
//-->
</SCRIPT>


To see what this menu object displays, roll your mouse over the following link:

myMenu3

Now that the enableTracker property is set to true, you can scroll up and down the page to see this menu follow and track its relative position. Notice that this menu is visibly static and draggable, so you can drag it over into the corner and it will stay there. Not only will it stay there, it will also reset that new corner location as its new relative position for menu tracking.

A SEPARATOR FOR MENU ITEMS

By default, the JavaScript Menu component automatically adds a horizontal border, one pixel high, between each of the menu items. You can eliminate this border and add your own single border (or separator) between specific menu items with the addMenuSeparator() method. (If you're familiar with Java, this works just like the addSeparator() method in the JDK java.awt.Menu class.) Example 4 illustrates the use of the addMenuSeparator() method.


Example 4

<SCRIPT LANGUAGE="JavaScript1.2">
<!--
    window.myMenu4 = new Menu("Example 4");

    myMenu4.addMenuItem("DevEdge Online", "location='http://developer.netscape.com'");
    myMenu4.addMenuItem("View Source Magazine", "location='/viewsource'");
    myMenu4.addMenuSeparator();
    myMenu4.addMenuItem("Netscape Netcenter", "location='http://home.netscape.com/'");
    myMenu4.addMenuItem("Download", "location='http://home.netscape.com/download/'");
    
    myMenu4.writeMenus();
//-->
</SCRIPT>


To see what this menu object displays, roll your mouse over the following link:

myMenu4

Notice that the addMenuSeparator() method removes all the default borders (by setting the menuItemBorder from one to zero pixels) and places a separator between the two menu items where you placed the addMenuSeparator() method call.

(Earlier versions of the Menu component actually had the addMenuSeparator() method, but I took it out of the previous version of the Menu component to reduce the code size for the Open Studio site. Now it's back in.)

IMAGE-BASED MENU ITEMS

There are two ways you can add graphic images for your menu items in the Menu component. The first way is to add a standard HTML <IMG> tag with the SRC attributes set to reference your image, like this:

myMenu.addMenuItem("<IMG SRC='images/mozilla.gif'>");

You can then add the onMouseOver and onMouseOut event handlers to change the image source, something like this:

myMenu.addMenuItem("<IMG SRC='images/mozilla.gif' onMouseOver='myMouseOver(this);' 
   onMouseOut='myMouseOut(this);'>");

In fact, you can add any standard <IMG> tag attributes to your <IMG> tag.

The second way to add images for your menu items is via a new feature of the Menu component that enables you to directly add the reference to your image, as in the following example:

myMenu.addMenuItem("images/mozilla.gif");

This way you aren't bothered with adding the <IMG> tag. And even better, you don't have to add the onMouseOver or onMouseOut event handlers to change the image source. Example 5 shows how to use this API.


Example 5

<SCRIPT LANGUAGE="JavaScript1.2">
<!--
    window.myMenu5 = new Menu("Example 5");

    myMenu5.addMenuItem("images/mozilla.gif", "top.location='http://www.mozilla.org'", "#000000", "images/mozilla2.gif");
    myMenu5.addMenuItem("images/mozilla.gif", "top.location='http://www.mozilla.org'", "#000000", "images/mozilla2.gif");
    myMenu5.addMenuItem("images/mozilla.gif", "top.location='http://www.mozilla.org'", "#000000", "images/mozilla2.gif");
    myMenu5.addMenuItem("images/mozilla.gif", "top.location='http://www.mozilla.org'", "#000000", "images/mozilla2.gif");
    myMenu5.addMenuItem("images/mozilla.gif", "location='http://www.mozilla.org'", "#000000", 
    
    myMenu5.writeMenus();
//-->
</SCRIPT>


Notice in Example 5 that four arguments are now being passed to the addMenuItem() method:

For more information on the second and third arguments, see my first article.

To see what this menu object displays, roll your mouse over the following link, which calls the showMenu() method to display the menu:

myMenu5

When you mouseover the menu item, notice that the image gets replaced with the image referenced in the fourth menu item argument (in this case, "images/mozilla2.gif"). Christian Denat recommended including this new way of adding images. He also modified his copy of the Menu code to support a similar API for adding images more easily. Merci beaucoup, Christian!

MENU ITEM HIGHLIGHTING

I've also improved the highlighting of menu items in this new version of the Menu component. Black and white are the default colors for highlighting menu items; you can now change these colors with the fontColor and fontColorHilite menu properties, as shown in Example 6.


Example 6

<SCRIPT LANGUAGE="JavaScript1.2">
<!--

    window.myMenu6 = new Menu("Example 6");
    myMenu6.addMenuItem("red", "document.bgColor='red'");
    myMenu6.addMenuItem("white", "document.bgColor='white'");
    myMenu6.addMenuItem("blue", "document.bgColor='blue'");
    myMenu6.addMenuItem("green", "document.bgColor='green'");
    myMenu6.fontColor = "red";
    myMenu6.fontColorHilite = "yellow";
    myMenu6.writeMenus();

//-->
</SCRIPT>


myMenu6

Notice the font color of these menu items dynamically highlights from red to yellow. (Earlier versions of the Menu component actually had the fontColorHilite property, but I took it out of the previous version of the Menu component to reduce the code size for the Open Studio site.)

For more information on the menu properties, see the section entitled Customizing Menus in my previous article.

MULTIPLE CALLS TO WRITEMENUS()

The writeMenus() method has been improved in this version of the Menu component. Previously, you could only call the writeMenus() method once at the end of your menu script, but now you can call the writeMenus() method anywhere. This means that you can dynamically generate menus based on user wants. Example 7 shows how you can call the writeMenus() method multiple times.


Example 7

<SCRIPT LANGUAGE="JavaScript1.2">
<!--
    window.myMenu = new Menu();
    myMenu.addMenuItem("my menu item A");
    myMenu.addMenuItem("my menu item B");
    myMenu.addMenuItem("my menu item C");

    myMenu.writeMenus();

    window.myMenu2 = new Menu("Example 2");
    myMenu2.addMenuItem("red", "document.bgColor='red'");
    myMenu2.addMenuItem("white", "document.bgColor='white'");
    myMenu2.addMenuItem("blue", "document.bgColor='blue'");

    myMenu2.writeMenus();

    window.myMenu3 = new Menu("Example 3");
    myMenu3.addMenuItem("red", "document.bgColor='red'");
    myMenu3.addMenuItem("white", "document.bgColor='white'");
    myMenu3.addMenuItem("blue", "document.bgColor='blue'");
    myMenu3.addMenuItem("green", "document.bgColor='green'");

    myMenu3.writeMenus();

//-->
</SCRIPT>


However, in most cases I still recommend calling the writeMenus() method only once at the end of your script. For more information on the writeMenus() method, see this topic in the Frequently Asked Questions. See my previous article for how to use the writeMenus() method with multiple menus.

MENUS IN FRAMES

HTML and CSS-P-based content can't overlap across frameset borders, just as images can't. Therefore, just as with images, you need to choose which frame you want the menus to be displayed in. In the frame you choose, do everything as usual to create your menus and load them into the frame. Then, so that another frame can make calls to display the menus in your chosen menus frame, you need to create a function that calls the showMenu() function in the menus frame. This can be done by using the window object hierarchy of the browser to jump from one frame to another, because a window containing a frameset has a root parent (or top) object that contains multiple children (window and document) objects, one per page. Examples of menus in vertical frames and menus in horizontal frames show how to do this.

These examples use a new event handler function called showMenuInFrame(). Depending on where you want the menus to be displayed on your site, this function may vary. (This is why I haven't added it into the Menu component library; however, it can be added at your request.) View the page source of the first (toc) frame to see how it's done. The trick here is that you need to do a little more code sharing and create a event handler, like showMenuInFrame(), in the frame that makes the call to display the menu in the menus frame.

The showMenuInFrame() function, which is in the first frame of the examples, passes the menu label and the x and y coordinates as arguments to the showMenu() function, which is actually located in the second frame along with the Menu component and the CSS-P-based menu content. There are other ways to do this, but this seems to be the simplest. Alternatively, I could have called the showMenu() function directly - and you still can - but the x and y coordinates might not be what you expected (unless you explicitly hard-code them), because the mouse is actually over the first ( toc ) frame at that time, not the second frame where the menus are. (Remember, each frame has its own separate window and document objects, containing a separate set of x and y properties.)

Note that the second frame creates and loads the menus the same way that this page does, but instead of having the menu objects code in the page itself, it includes a JavaScript library called mymenus.js that contains all the code for the menu objects. This way I can include the mymenus.js library (along with the menu.js library) in multiple documents in order to share and cache the same menu objects code.

If you need help, get as far as you can and then email your staged URL. Based on your feedback, we can come up with something more generic and compatible for everyone.

GOING FORWARD

I hope you've enjoyed this article and that it will help you add better navigation to your web site. I've tried to cover every detail I could think of to help you customize and add menus to your web pages. If you previously were using the version of the Menu component from my first article, I hope you'll enjoy all the new features (including the ones I didn't discuss).

Check out the Sample Menus page for a list of several other menu samples. If your site uses the Menu component, you can submit your URL for possible posting on the Sample Menus page. The more examples we can gather, the more we can help each other out, because we can see each other's various ways of deploying menus and improving them.

I plan to update and improve the Menu component based on feedback from developers, so please email your suggestions, requests, or comments regarding this component.


FURTHER RESOURCES


View Source wants your feedback!
Write to us and let us know
what you think of this article.

Many thanks to Paul Dreyfus for the opportunity to write this second article on the Menu component, and special thanks to Lorraine Anderson for the excellent editing job.

Gary Smith is a Netscape engineer who occasionally writes sample code and articles for DevEdge Online and View Source, such as the article Connecting JavaScript to Java with LiveConnect.

(5.99)

For more Internet development resources, try Netscape TechSearch

DevEdge Online FAQ
Developer Response Center
Join DevEdge Program
Copyright © 1999 Netscape Communications Corporation.
This site powered by: Netscape Enterprise Server and Netscape Compass Server.