The most common question we get is about the old dhtml menu and how to use it with frames or how to modify it to work as a popup menu. Therefor I've created a new menu system from scratch that took these issues into account from the beginning.

The problems with frames

Frames are so called windowed controls and such are created in a new window object. These windows are opaque and can not be displayed below ordinary HTML elements. The only thing that can be displayed in front of a windowed control is another windowed control. I choose to use scriptlets because these allows a good abstraction and allows the author to assign methods and properties to them as well.

The theory

I will not explain in detail how this script is made but I will point out the basic idea. When a menu is going to be displayed a scriptlet is inserted dynamically with insertAdjacentHTML and once this scriptlet is loaded the content of the menu is copied into the scriptlet and the scriptlet is made visible.

To make it work more like a popup menu the function that makes the menu visible takes a special object, Boundaries, as an argument. This object represents a box that the menu should be displayed relative to. (More about this later.)

Creating Menus

The menus are built with tables much like in the old menu but there are some small differences. The table should have the class set to menu and you should also set the cellspacing to 0. Each row in the table is treated as a menu item. The attribute called href is used for the location that should be loaded when the item is clicked and target is for the name of the designated window to load the location in. Below is a simple menu:

<table cellspacing="0" class="menu" id="testMenu1">
<tr href="javascript:alert('You clicked a menu item')">
   <td></td>
   <td nowrap>Menu Item 1</td>
   <td></td>
</tr>
<tr href="http://webfx.eae.net" target="_blank">
   <td class="icon"><img src="../../images/favicon.gif"></td>
   <td nowrap>Menu Item 2</td>
   <td></td>
</tr>
</table>

Notice the class icon added to the TD containing the icon image. This menu looks like this.

Sub Menus

Sub menus look exactly like normal subs. The difference is the menu item that associates the sub menu. The menu item should have the class name set to sub and you could either include a nested table or set an attribute called menu to the id of the sub menu. I'll show you how.

<table class="menu" cellspacing="0" id="testMenu2">
<tr class="sub" menu="testMenu1">
   <td></td>
   <td>Menu with <b>menu</b> attribute</td>
   <td class="more">4</td>
</tr>
<tr class="sub">
   <td></td>
   <td>menu with nested table tags</td>
   <td class="more">4

      <table class="menu" cellspacing="0">
      <tr>
         <td></td>
         <td>Simple</td>
         <td></td>
      </tr>
      </table>

   </td>
</tr>
</table>

Here I've added a TD with the class more to create a right arrow that indicates that there is a sub menu. This menu looks like this.

Disabled and separators

To disable a menu item just set the class name to disabled. A separator is a little bit trickier but once you have made one you can just copy the code.

<table cellspacing="0" class="menu" id="testMenu3">
<tr class="disabled">
   <td class="icon"><img src="../../images/openfoldericon.gif"></td>
   <td nowrap>Disabled Menu Item</td>
   <td></td>
</tr>
<tr class="disabled">
	<td colspan="3" style="height: 10px; padding: 0;"><div style="border: 1px inset ; height: 2; overflow: hidden;"></div></td>
</tr>
<tr title="You can also use tooltips easily">
   <td></td>
   <td nowrap>Above is a separator</td>
   <td></td>
</tr>
</table>

The code for the separator is not as nice as I wish but at least it looks and behaves as it is supposed. The menu looks like this.

Customizing the look

The only place that is responsible for the look of the menus is the css file so if you know CSS you can easily change the look and feel of the menus.

Showing a Menu

To show a menu you just call a function called showMenu that takes three arguments. The first is a the table element that describes the menu. The second is a Boundaries object and the third (which is optional) is to describe wheter the menu should be displayed below ("vertical") or besides ("horizontal") the box definde by the boundaries. A Boundaries object can be created in three differnet ways. The first is to give it one argument that is an HTML element that the menu should be displayed around:

new Boundaries(htmlElement)

The second and third take either 2 or 4 arguments and the first two are the left and top position and the third and fourth arguments are the width and height of the boundaries. If the two last arguments are omitted the width and height is set to zero.

new Boundaries(left, top, width, height)
new Boundaries(left, top) // equals new Boundaries(left, top, 0, 0)

Now you are ready to show your menu:

<a href="" onclick="showMenu(testMenu3, new Boundaries(this), 'vertical'); return false;">this</a>

Next I'll show you how to create a popup menu (IE5 only) and then I'll describe how to create a menu bar and last but not least I'll show you how to combine this with the dock bar.

Creating menus
Use menu as a popup menu
Plain menu with a framed page
Dockable menu
Customize the look
Download this sample
Discuss this article

Author: Erik Arvidsson