The JavaScript Menu component
provides a user- and developer-friendly
way for you to build easily customized, floating menus
made up of pure, cross-browser Dynamic HTML (DHTML) and object-oriented JavaScript. In this article
I'll show how you can use the (free to the public)
Menu component to build
DHTML menus in your own web site or web application.
(Note that only version 4.0 browsers will display the DHTML menus; 3.0 browsers will simply ignore them.)
The I'll show how easy yet useful it can be to take advantage of DHTML
in your web site or application.
Using optimized, pre-built DHTML widgets that are portable like the I'll assume you're familiar with the basic syntax of the JavaScript language.
If you're new to JavaScript, this is a great place to learn a lot about it quickly.
If you already know JavaScript, you should soon enjoy modifying and customizing your own menu objects
(through an object-oriented architecture that resembles JavaBeans, or the
Adding the above The syntax for creating your own menus isn't very different from that of
regular client-side JavaScript code.
The This new expression creates a new menu object called You can add "menu items" to your newly created menu object with
the
If you're familiar with the Java language, you may notice that the syntax of the
This script creates a new menu object with four menu items, each with its own string label:
I should also explain the Moving on, Example 2 creates another, more useful menu.
This example is similar to Example 1, but it passes a second parameter to Notice that like the label parameter, the action parameter is a text string,
but in this case a string of code.
The action string is registered by the For example, instead of passing a string of code like
Getting Started
Adding menus to your web site is easy.
To begin, you need to add the following line of code into your web page:
<SCRIPT LANGUAGE="JavaScript1.2" SRC="http://developer.netscape.com/viewsource/smith_menu/menu.js"></SCRIPT>
Here the standard HTML <SCRIPT> tag contains a SRC attribute
for including the menu.js JavaScript library in your page source.
This library contains the code for the Menu component constructor and functions that you'll need for building menus.
It's best to place this tag in the HEAD section of your page source.
As you may know, one of the many benefits of using JavaScript libraries is that they're
kept in memory via Navigator's cache,
so the library code doesn't have to be downloaded each time.
Also, the library code can be shared by multiple pages and by different sites;
when a change is made to the library file, it applies to all the pages that are sharing
that code.
Creating Menus
var myMenu = new Menu();
myMenu.addMenuItem("my item");
Example 1
<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>
Example 2
<SCRIPT LANGUAGE="JavaScript1.2">
<!--
var myMenu2 = new Menu();
myMenu2.addMenuItem("DevEdge Online", "location='http://developer.netscape.com'");
myMenu2.addMenuItem("Open Studio", "location='http://developer.netscape.com/openstudio/'");
myMenu2.addMenuItem("Netcenter", "location='http://home.netscape.com'");
myMenu2.addMenuItem("Download", "location='http://home.netscape.com/download/'");
myMenu2.writeMenus();
//-->
</SCRIPT>
Example 3
<SCRIPT LANGUAGE="JavaScript1.2">
<!--
var myMenu3 = new Menu();
myMenu3.addMenuItem("Red", "document.bgColor='red'");
myMenu3.addMenuItem("Green", "document.bgColor='green'");
myMenu3.addMenuItem("Blue", "document.bgColor='blue'");
myMenu3.addMenuItem("White", "document.bgColor='white'");
myMenu3.writeMenus();
//-->
</SCRIPT>
display myMenu3
As you can see, the Let's summarize the three basic steps it takes to quickly add a dynamic menu to your web page:
Now that you know how easy it is to add a menu to your web page, let's look at how to customize menus.
You can change the sizes, fonts, and colors of your menus by changing the settings of the
To see what this code displays, click the following link:
<SCRIPT> tag for adding the Menu library.
Customizing Menus
Example 4
<SCRIPT LANGUAGE="JavaScript1.2">
<!--
var myMenu4 = new Menu();
myMenu4.addMenuItem("DevEdge Online", "location='http://developer.netscape.com'");
myMenu4.addMenuItem("Open Studio", "location='http://developer.netscape.com/openstudio/'");
myMenu4.addMenuItem("Netcenter", "location='http://home.netscape.com'");
myMenu4.addMenuItem("Download", "location='http://home.netscape.com/download/'");
myMenu4.fontColor = "blue";
myMenu4.menuItemBgColor = "yellow";
myMenu4.writeMenus();
//-->
</SCRIPT>
display myMenu4
This sample script includes two extra lines of code that override two of the default property values, by
setting the menu's There are several other properties that you can customize in the Example 5 creates the same menus as Example 4, but sets
a few additional color and size properties to display a menu with a
completely different look.
To see what this menu object displays, click the following link:
this.fontSize = 14;
this.fontWeight = "plain";
this.fontFamily = "arial, helvetica, espy, sans-serif";
this.fontColor = "#000000";
this.bgColor = "#555555";
this.menuBorder = 1;
this.menuItemBorder = 1;
this.menuItemIndent = 15;
this.menuItemHeight = 20;
this.menuItemBgColor = "#cccccc";
this.menuLiteBgColor = "#ffffff";
this.menuBorderBgColor = "#777777";
this.menuHiliteBgColor = "#bbbbbb";
this.menuContainerBgColor = "#cccccc";
this.childMenuIcon = "images/gs.gif";
Example 5
<SCRIPT LANGUAGE="JavaScript1.2">
<!--
window.myMenu5 = new Menu();
myMenu5.addMenuItem("DevEdge Online", "location='http://developer.netscape.com'");
myMenu5.addMenuItem("Open Studio", "location='http://developer.netscape.com/openstudio/'");
myMenu5.addMenuItem("Netcenter", "location='http://home.netscape.com'");
myMenu5.addMenuItem("Download", "location='http://home.netscape.com/download/'");
myMenu5.fontSize = 18;
myMenu5.fontWeight = "Bold";
myMenu5.fontColor = "white";
myMenu5.bgColor = "#CDB79E";
myMenu5.menuItemBgColor = "#8B0000";
myMenu5.menuHiliteBgColor = "#000084";
myMenu5.menuItemHeight = 25;
myMenu5.writeMenus();
//-->
</SCRIPT>
display myMenu5
This time the menu is brick-red, with a larger, bolder font.
As you can see, the font characteristics are determined by the menu's
This sample script creates three menu objects:
Creating Multiple Menus
You can add multiple menu objects and scripts to your page in various ways and display them whenever you want.
Compare Example 6 to the earlier examples.
Example 6
<SCRIPT LANGUAGE="JavaScript1.2">
<!--
function loadMenus ()
{
window.myMenu6 = new Menu("myMenu6");
myMenu6.addMenuItem("DevEdge Online", "location='http://developer.netscape.com'");
myMenu6.addMenuItem("Open Studio", "location='http://developer.netscape.com/openstudio/'");
myMenu6.addMenuItem("Netcenter", "location='http://home.netscape.com'");
myMenu6.addMenuItem("Download", "location='http://home.netscape.com/download/'");
window.search = new Menu("Search");
search.addMenuItem("Net Search", "location='http://home.netscape.com/escapes/search'");
search.addMenuItem("Excite", "location='http://www.excite.com'");
search.addMenuItem("Infoseek", "location='http://www.infoseek.com'");
search.addMenuItem("Lycos", "location='http://www.lycos.com'");
search.addMenuItem("Yahoo", "location='http://www.yahoo.com'");
window.mozilla = new Menu("Mozilla");
mozilla.addMenuItem("Mozilla.org", "location='http://www.mozilla.org'");
mozilla.addMenuItem("Projects", "location='http://www.mozilla.org/projects.html'");
mozilla.addMenuItem("Source Code", "location='http://www.mozilla.org/source-code.html'");
mozilla.writeMenus();
}
//-->
</SCRIPT>
Notice that the three new menu objects in Example 6 are contained inside a function called
loadMenus(). Placing your menu code in a function enables you to load your menus whenever you want, because the menu objects aren't actually created until the function is called. For example, you can call this function after your page is loaded, allowing the main content of your page to load the menus.Although there are three menus, this script contains only one call to the
writeMenus() method. That's a feature of the Menu component: you only need to call writeMenus() once, because every time you create a menu object for your page, the new object gets registered and stored in an array called window.menus, which contains all the menus you've created for that window. Whenever you call writeMenus() (which in turn calls document.writeln()), it writes all the menus stored in the window.menus array. This way your script calls document.writeln() only once for all the menus, rather than calling it several times, which can be much slower. For the Open Studio web site, writeMenus() takes less than one second to load its menus, and this article quickly loads about 20 example menus (hopefully you'll have far fewer menus than that!).The
window.menus array is a regular JavaScript array, so you can access the elements of it the same way you access other JavaScript arrays that you create, or the window.images or window.forms array. The window.menus array is readable and writeable; you can modify it or access the objects it contains at any time.Also notice that Example 6 doesn't use the JavaScript
var keyword like the earlier examples. Instead of using var myMenu6 = new Menu();this example creates a new window object property, with the following syntax:
window.myMenu6 = new Menu();If I had instead used the
var keyword, the myMenu6 object would have been declared only as a local variable of the loadMenus() function. However, I want myMenu6 to be a "global" variable (or window property), so I declared it as a property of the window object. This is one of the many powerful features of the JavaScript language.In this section, I'll show how you can add "child" menus, or submenus, into your regular menus to display a deeper hierarchical menu tree. Creating a child menu is exactly the same as creating a regular menu. (Again, it's similar to using the Java
Menu class in the JDK.) Example 7 shows how to create a single child menu hosted inside a regular "parent" menu.<SCRIPT LANGUAGE="JavaScript1.2"> <!-- function loadMenus () { window.mySubMenu7 = new Menu("JavaScript"); mySubMenu7.addMenuItem("JavaScript 1.1", "location='/eng/mozilla/3.0/handbook/javascript/index.html'"); mySubMenu7.addMenuItem("JavaScript 1.2", "location='/docs/manuals/communicator/jsguide4/index.htm'"); mySubMenu7.addMenuItem("JavaScript Reference", "location='/docs/manuals/communicator/jsref/index.htm'"); window.myMenu7 = new Menu("Technologies"); myMenu7.addMenuItem("Dynamic HTML", "location='http://developer.netscape.com'"); myMenu7.addMenuItem(mySubMenu7); myMenu7.addMenuItem("Java", "location='http://home.netscape.com'"); myMenu7.addMenuItem("Plug-ins", "location='http://home.netscape.com'"); myMenu7.writeMenus(); } //--> </SCRIPT>
display myMenu7
As in the Java language, once you create a menu object, you can pass it as a child menu
for another menu; Example 7 does this by passing the You can also share the same child menu or menus with several different
parent menus, and vice versa.
Example 8 shows how to create a menu that serves as the "root" parent menu for several
different child menus. This script is quite short, because
it uses the prescripted menu objects from the previous examples as the child menus.
Example 8
<SCRIPT LANGUAGE="JavaScript1.2">
<!--
function loadMenus ()
{
window.myMenu8 = new Menu("my menu tree");
myMenu8.addMenuItem(myMenu2);
myMenu8.addMenuItem(myMenu3);
myMenu8.addMenuItem(myMenu4);
myMenu8.addMenuItem(myMenu5);
myMenu8.addMenuItem(myMenu7);
myMenu8.writeMenus();
}
//-->
</SCRIPT>
display myMenu8
Notice that the labels displayed in Consequently, the Although you can logically add as many child menus into as many parent menus as you want
(to as many levels deep as you want), you should try not to use too many child menus,
to avoid annoying or confusing the user.
In fact, I recommend avoiding the use of child menus altogether whenever possible, although
having one or two of them once in a while is usually OK.
Just keep it simple.
Example 9 illustrates what you would have to do to customize
the font and color styles for three sample menu objects
without prototyping.
To change the font and color styles,
I added four new lines of code to Example 6 for
each of the three menu objects, for a total of 12 new lines.
Imagine if there had been ten menu objects: this could add up to a lot of new code.
If you want these style properties to be different for each menu object, you have no alternative;
however, if you want all your menus to have the same customized look and feel,
using the menu prototyping feature is faster, as well as easier to maintain.
Example 10 accomplishes the same thing as Example 9
but with prototyping.
Compared to Example 9, this example uses only five lines of code rather than 12; the more
menus there are, the more lines of code saved.
This is done via the Click the following link to see what this example displays:
Prototyping Menu Styles
You've seen how to customize the font and color styles of a menu object by changing the default property values,
and how to create multiple customized and child menus.
Usually when creating multiple customized menus for your web page,
you'll want to use the same font and color styles for all your menus.
For this reason, I added style prototyping into the architecture of the Menu object.
Example 9
<SCRIPT LANGUAGE="JavaScript1.2">
<!--
function loadMenus ()
{
window.myMenu9a = new Menu("Example 9a");
myMenu9a.addMenuItem("DevEdge Online", "location='http://developer.netscape.com'");
myMenu9a.addMenuItem("Open Studio", "location='http://developer.netscape.com/openstudio/'");
myMenu9a.addMenuItem("Netcenter", "location='http://home.netscape.com'");
myMenu9a.addMenuItem("Download", "location='http://home.netscape.com/download/'");
myMenu9a.fontColor = "#ffffff";
myMenu9a.menuItemBgColor = "#000000";
myMenu9a.menuHiliteBgColor = "#6699CC";
myMenu9a.bgColor = "#AAAAAA";
window.myMenu9b = new Menu("Example 9b");
myMenu9b.addMenuItem("Net Search", "location='http://home.netscape.com/escapes/myMenu9b'");
myMenu9b.addMenuItem("Excite", "location='http://www.excite.com'");
myMenu9b.addMenuItem("Infoseek", "location='http://www.infoseek.com'");
myMenu9b.addMenuItem("Lycos", "location='http://www.lycos.com'");
myMenu9b.addMenuItem("Yahoo", "location='http://www.yahoo.com'");
myMenu9b.fontColor = "#ffffff";
myMenu9b.menuItemBgColor = "#000000";
myMenu9b.menuHiliteBgColor = "#6699CC";
myMenu9b.bgColor = "#AAAAAA";
window.myMenu9c = new Menu("Example 9c");
myMenu9c.addMenuItem("Mozilla.org", "location='http://www.mozilla.org'");
myMenu9c.addMenuItem("Projects", "location='http://www.mozilla.org/projects.html'");
myMenu9c.addMenuItem("Source Code", "location='http://www.mozilla.org/source-code.html'");
myMenu9c.fontColor = "#ffffff";
myMenu9c.menuItemBgColor = "#000000";
myMenu9c.menuHiliteBgColor = "#6699CC";
myMenu9c.bgColor = "#AAAAAA";
myMenu9c.writeMenus();
}
//-->
</SCRIPT>
display myMenu9b
display myMenu9c
Example 10
<SCRIPT LANGUAGE="JavaScript1.2">
<!--
function loadMenus ()
{
window.myMenu10a = new Menu("Example 10a");
myMenu10a.addMenuItem("DevEdge Online", "location='http://developer.netscape.com'");
myMenu10a.addMenuItem("Open Studio", "location='http://developer.netscape.com/openstudio/'");
myMenu10a.addMenuItem("Netcenter", "location='http://home.netscape.com'");
myMenu10a.addMenuItem("Download", "location='http://home.netscape.com/download/'");
window.myMenu10b = new Menu("Example 10b");
myMenu10b.addMenuItem("Net Search", "location='http://home.netscape.com/escapes/myMenu10b'");
myMenu10b.addMenuItem("Excite", "location='http://www.excite.com'");
myMenu10b.addMenuItem("Infoseek", "location='http://www.infoseek.com'");
myMenu10b.addMenuItem("Lycos", "location='http://www.lycos.com'");
myMenu10b.addMenuItem("Yahoo", "location='http://www.yahoo.com'");
window.myMenu10c = new Menu("Example 10c");
myMenu10c.addMenuItem("Mozilla.org", "location='http://www.mozilla.org'");
myMenu10c.addMenuItem("Projects", "location='http://www.mozilla.org/projects.html'");
myMenu10c.addMenuItem("Source Code", "location='http://www.mozilla.org/source-code.html'");
myMenu10c.fontColor = "#ffffff";
myMenu10c.menuItemBgColor = "#000000";
myMenu10c.menuHiliteBgColor = "#6699CC";
myMenu10c.bgColor = "#AAAAAA";
myMenu10c.prototypeStyles = myMenu10c;
myMenu10c.writeMenus();
}
//-->
</SCRIPT>
display myMenu10b
display myMenu10c
Displaying Menus
Remember that your menus are CSS-P-based objects
that you can show and hide using the visibility property.
To make life easier for you, I've built showMenu() and
hideMenu() functions into the Menu component.
The showMenu() method is what I've been using all along to show the example menus.
Here's how to use showMenu() as an event handler:
<A HREF="javascript://" onClick="showMenu(mozilla);">display mozilla</A>
display mozilla
As you can see, I set the Passing a menu object as an argument to
<A HREF="javascript://" onClick="showMenu(mozilla, 150);">display mozilla</A>
Click the following link to see where this example displays the mozilla menu:
display mozilla
I've defined
You can also use other event handlers and actions to show and hide menus.
Here's how to use the familiar
<A HREF="javascript://" onMouseOver="showMenu(mozilla);">display mozilla</A>
This is the same as the previous example, except that it uses onMouseOver instead of onClick
to show the menu.
Run your mouse over the following link to see how this works:
display mozilla
You may prefer using You can implement the You can also pass the
menu's label string or CSS-P object ID
to
<A HREF="javascript://" onMouseOver='showMenu("Mozilla");'>display mozilla</A>
display mozilla
See the difference?
The argument passed to On the subject of hiding menus:
Usually you don't have to worry about doing this, because the Open Studio is a perfect example of this.
It not only uses all the The way Open Studio shares its menu objects is by storing them in a JavaScript library
named If you like menus, you really should use Open Studio as a reference.
It shows how useful menu objects can be, and how well they work on a busy web site
-- and they're very customized (white letters on a black background, with blue as the highlight color,
to match the site).
Let's look at how object sniffing works in the
Object sniffing can be more reliable than browser sniffing.
However, if you're using a browser sniffer, don't make common mistakes
like An Currently, a
weaker area for Communicator 4.0 is the layout: when you resize the window it sometimes
loses some of the properties for CSS-P objects (the IE4 has a layout bug, too: you'll need to load your menus before the
window's You'll also often need to specify the width of your menus for IE4,
because IE4 doesn't explicitly assign values to CSS-P object properties.
When you create CSS-P objects the default behavior usually isn't
what you think it should be
(especially the The DOM in Communicator handles default behavior much better, because it assigns
default values to virtually all CSS-P properties for your objects.
In this case your menus will always be the width of your largest menu item.
Note that the I plan to update and improve the
Sharing Menus Across Domains
You can really take advantage of the basic features of the Internet with JavaScript,
especially when you use JavaScript libraries.
Storing your menu code in JavaScript .js libraries allows you not only to share code
on your own domain, but also to safely share it across different domains, similar to how folks have shared
GIF images since the beginning of the web's existence.
In other words, you can view the prototypical Menu library
as a real Internet component or shared object.
Cross-Browser Compatibility
Netscape Communicator 4 and Microsoft Internet Explorer 4 support different document object models (DOMs).
The Menu component accommodates for these kind of differences.
Look at the Menu source to see exactly how this is done.
Notice that I didn't use any of the traditional "browser sniffing" techniques.
Instead of looking for numerous browser versions and names, I used "object sniffing," which is a lot simpler.
if (document.layers)
{
document.layers["myObjectID"].top = 100;
}
else if (document.all)
{
document.all["myObjectID"].styles.pixelTop = 100;
}
Known Issues
One of the main features of the Menu component is cross-browser compatibility;
however, both Communicator 4 and Internet Explorer 4 are known to sometimes fall short
in different areas regarding
their new DOMs and the DHTML "draft standards."
The IE implementation of JScript is getting better,
but it's still virtually light years behind the
standard implementation of JavaScript 1.2 and LiveConnect in Communicator.
On the other hand, IE4 seems to hold more water regarding the HTML 4.0 draft,
because it came out later than Communicator; however, so far it's still less stable.
Keep in mind that the upcoming 5.0 browsers will support DHTML much better and will
conform to the W3C final specs, which until now have been a moving target
(Netscape, at least, is committed to supporting all the W3C standards).
Going Forward
Many thanks to Paul Dreyfus, Andres Espineira, and Richard Hall for the opportunity to write this article, and special thanks to Caroline Rose for the excellent editing job.
Gary Smith is a Netscape engineer, creator of Visual DHTML, Dialog Widget, and Webtop Widget. He works on new technology projects involving LiveConnect, JavaScript, Java, CGI, XML/RDF, and web-crawling technologies. Occasionally he writes sample code and documentation for DevEdge Online, such as the View Source article Connecting JavaScript to Java with LiveConnect.
DevEdge Online FAQ
Developer Response Center Join DevEdge Program |
Copyright © 1998 Netscape Communications Corporation.
This site powered by: Netscape Enterprise Server and Netscape Publishing System 1.6. |