Tree Menu
  The menu at left appears and acts very much like the Explorer menu on Windows machines. Clicking on an item loads an associated link. Clicking on a folder will also toggle it open or close it, revealing or hiding a submenu. To close all the folders, you can click on the root at top.

Features include:

  • Any number of items may be defined for a menu and folders can be nested arbitrarily deep.
  • The selected item or folder is highlighted when clicked.
  • The page will automatically scroll to place the selected item in view.
  • Folders may optionally include a link.
  • The menu state is saved so when a visitor leaves and returns to your page, the menu will appear exactly as it did when last viewed.
  • You can customize the page colors and graphics to suite your needs.

Latest Update

Feb. 18, 1999 - Improved response time and added options to change menu colors and graphics directory.

If you have a previous version you can use this one by downloading the new versions of treeMenu.html and treeMenuCode.js. Then update your version of myMenu.js by adding values for the new page colors and the image directory variables.

Using Tree Menu

This section describes how to set up and create your own tree menu.

Files

The main file defines the frameset and contains all the code. Below is a list of all the files used and their purpose:

  • tree.html - defines the left and right frames and imports the JavaScript code. This code could also be stored directly in the file if desired.
  • treeMenuCode.js - Contains all the JavaScript code needed to build and display the menu and save it's state.
  • myMenu.js - Defines this particular tree menu.
  • treeMenu.html - Initially a blank page which is rebuilt dynamically to display the menu whenever its state is updated.
  • treeMain.html - This page.

Setting Up the Menu

To create your menu, you need to build your own version of myMenu.js. Before you start defining the menu itself, you need to set some global variables:

  • treeMenu - This is the top-level menu. See below on how to create this.

  • treeMenuName - This should be set to some string which will be used to uniquely identify this particular menu. It's used as the name of the cookie which will store the menu state. If you update your menu, change the name so the data will be recreated from scratch to match the new configuration.

  • treeMenuDays - This value is used to set the expiration date for the menu cookie. Use an integer to specify the number of days the cookie will be valid for. If the user doesn't return to your page before then, the cookie expires and the menu state is reset to where all folders are closed and no item is selected.

  • treeMenuFrame - Set this to the name of the frame that will contain the menu.

  • treeMenuImgDir - Specifies the path to the menu and icon images. For example, if you put the images in a sub-directory called "graphics" set this to "graphics/". If the images are in the same directory, set this to a null string ("").

  • treeMenuBgColor, treeMenuFgColor,treeMenuHiBg, treeMenuHiFg - color values used for the menu frame background, item text and selected item background and text respectively. Standard RGB color values or color names may be used, e.g. "#ffffff" or "white".

  • treeMenuRoot - This is the text that will be used for the menu root. Here it's set to "Site Menu".

  • treeMenuWidth - This defines the width of the menu in pixels. The graphics and text for each menu item should fit on a single line, otherwise the display will appear broken. If this happens, increase the value.

Note that all the above variable should be defined and set with a value. Leaving any out will cause the menu to fail.

Defining the Menu

The file treeMenuCode.js defines two new JavaScript objects, TreeMenu and TreeMenuItem along with some methods to attach an item to a menu or to make an item a submenu.

First, define the top-level menu using the treeMenu global variable:

var treeMenu = new TreeMenu();

Now create some items for it by defining some TreeMenuItem() objects. You specify one to four arguments for an item. The first is the text used in the menu display. The rest apply to the link for the item. They are:

  • text the text for the menu item.
  • url (optional) the URL address for a link.
  • target (optional) the name of the target window or frame for the link.
  • icon (optional) the icon to use in the menu display if this is not a folder.

Then you use the addItem method to attach an item to a menu. Here is the code to define and add the main menu items:

treeMenu.addItem(new TreeMenuItem("Dynamic HTML"));
treeMenu.addItem(new TreeMenuItem("Java Applets"));
treeMenu.addItem(new TreeMenuItem("JavaScript"));
treeMenu.addItem(new TreeMenuItem("Contact Me", "../contact.html", "main"));
treeMenu.addItem(new TreeMenuItem("My Webpage", "../intro.html", "main"));
treeMenu.addItem(new TreeMenuItem("Resources", "../links.html", "main"));
treeMenu.addItem(new TreeMenuItem("What's New", "../new.html", "main"));

Note that the items will be displayed in the order they are added. The first three items here will be submenus, so only the text is given. For links you can leave off the icon value if you wish to use the default images.

We can then reference each item in this menu using the .items array, where treeMenu.items[0] is 'Dynamic HTML', treeMenu.items[1] is 'Java Applets', etc.

Defining and Attaching Submenus

We create submenus just like the main menu, using new variables. Here we'll create the 'Dynamic HTML' submenu:

var dhtml = new TreeMenu();
dhtml.addItem(new TreeMenuItem("References"));
dhtml.addItem(new TreeMenuItem("Asteroids", "../dhtml/asteroids/index.html", "blank"));
dhtml.addItem(new TreeMenuItem("Cross-Browser DHTML Library",
                               "../dhtml/cbdhtml.html", "blank"));
dhtml.addItem(new TreeMenuItem("Dynamic HTML", "../dhtml.html", "main"));

Now, to attach this submenu to the main menu, we first reference the main menu item we want to attach it to and use .makeSubmenu() passing the submenu variable as the argument:

treeMenu.items[0].makeSubmenu(dhtml);

This makes the first item in treeMenu a submenu which contains all the items defined in dthml. Likewise, we create submenus for 'Java Applets' and 'JavaScript' and attach them:

var java = new TreeMenu();
java.addItem(...);
java.addItem(...);
...
treeMenu.items[1].makeSubmenu(java);    // Attach to second item of main menu.

var js = new TreeMenu();
js.addItem(...);
js.addItem(...);
...
treeMenu.items[2].makeSubmenu(js);      // Attach to third item of main menu.

Now, to go a level deeper, we want to make submenus for 'References' and 'Sites' in the 'Dynamic HTML'submenu. So we create a new menus called dhtml_refs and dhtml_sites and attach them by referencing the first item and second items of dhtml:

var dhtml_refs = new TreeMenu();
dhtml_refs.addItem(new TreeMenuItem(...));
dhtml_refs.addItem(new TreeMenuItem(...));
...
dhtml.items[0].makeSubmenu(dhtml_refs);    // Attach to first item of dhtml menu.

var dhtml_sites = new TreeMenu();
dhtml_sites.addItem(new TreeMenuItem(...));
dhtml_sites.addItem(new TreeMenuItem(...));
...
dhtml.items[0].makeSubmenu(dhtml_sites);    // Attach to second item of dhtml menu.

Likewise, the 'JavaScript' item has three submenus. So we create the menus and attach them to the js submenu:

var js_ex = new TreeMenu();
js_ex.addItem(...);
js_ex.addItem(...);
...
js.items[0].makeSubmenu(js_ex);      // Attach to first item of js menu.

var js_refs = new TreeMenu();
js_refs.addItem(...);
js_refs.addItem(...);
...
js.items[1].makeSubmenu(js_refs);    // Attach to second item of js menu.

var js_sites = new TreeMenu();
js_sites.addItem(...);
js_sites.addItem(...);
...
js.items[1].makeSubmenu(js_sites);    // Attach to third item of js menu.

For your own menus, you can define as many items as you want in each menu and nest menus as deep as you want.

Customizing Colors and Icons

To change the menu colors, edit the treeMenu.html file to change the background and link colors in the <body> tag. To change the colors used to highlight the selected item, edit the definition of the all.selected style.

You can also change the graphics and icons used for each of the menu parts, see the list of images at the bottom of the page.

Coding Details

Much of the code has been streamlined from the previous version. I've also changed the global variable and function names to begin with 'treeMenu' so that it won't interfere with any other JavaScript code you may add.

The TreeMenu and TreeMenuItem Objects

These are the the key to setting up and displaying the menu. The TreeMenu object consists simply of an array to store the items and a method to add them.

The TreeMenuItem object contains variables to store the item's display text, icon image source (if specified) and data for it's associated link (if any). It also has a flag to indicate if it is itself a menu and a variable that points to the TreeMenu object to be used. The makeSubmenu() method is what set's these values. It also has an index variable which relates it to the proper value in the menu state cookie (see below) so we can track which folder items are open and which are closed.

Using these, the menu is built when the top-level page is first loaded, creating a hierarchial structure in the global treeMenu variable.

Menu State Data

One cookie is used to track which folders in the menu are open and which are closed. Every item has a boolean value associated with it in this cookie. The values are read in just before the menu is drawn and the values are updated every time the user clicks on an item.

A separate cookie is used to keep track of which item was last clicked, allowing it to be highlighted when drawn. It is also used to determine how far the window needs to be scrolled if that item falls outside of the menu frame's viewable region.

Note that if you update your menu, you should also change the value of treeMenuName so new cookies will be created from scratch.

Drawing the Menu

The file treeMenu.html uses the onLoad event in the <BODY> tag to call the treeMenuDisplay() function located in the parent file. This function rewrites HTML code of the menu frame to build the menu display based on the current menu state. This new HTML also includes an onLoad call but this time it runs the treeMenuScroll() function to scroll the page so that the selected item will be in view.

treeMenuDisplay() works as follows. First, it fetches the cookie data so we will know which folders are to be open and which item was selected last. Then some global variables are set to track where we are in the menu hierarchy and help with the graphics placement.

Then the menu frame document is cleared using the document.open() method. This allows it to completely rewrite the HTML code of the frame. It generates the proper HTML tags to define style sheets and set the page colors. It also adds a call to treeMenuScroll() in the onLoad event of the body tag so the page will scroll to put the currently selected item in view, if necessary.

Then, we start the display with a <table> tag. The first row just contains the root icon and text. Each following row will contain a menu item.

Here, the recursive nature of the tree menu objects is what makes the display drawing work. We make a call to treeMenuListItems() passing it the top level menu (the treeMenu variable). When it returns, all the items will have been drawn and we just finish with the closing </table> tag.

treeMenuListItems() is very simple, it just takes the given menu and loops thru each item making a call to treeMenuDisplayItem() to write it out. It also passes a flag to indicate whether the item being passed is the last one in the menu or not.

treeMenuDisplayItem() is the workhorse. It writes out the proper images and text for the given item as a table row. Some global variables are used to track how far to indent the item and what images are needed to create the tree layout. Then, based on the properties of the menu item, it displays the proper icon (folder, file icon, custom icon, etc.) and it's text.

If an item happens to be a submenu it checks the cookie data to determine if it should be expanded or not. If so, it makes a recursive call to treeMenuListItems() passing it the item's submenu.

In this function, we also update the global scrolling values if the given item is the selected one.

Once the menu is finally drawn, some closing tags are output and the menu frame will now reflect the proper menu view.

Making the Menu Interactive

Each item is written as a hypertext link with a call to treeMenuClick() that will cause a redisplay of the menu if the item is clicked. The function is passed the items's index value, so we can update the cookie data and a couple of boolean flags letting it know if the item links to another page and if it is a folder.

The function updates the cookie values, toggling the folder open or closed if it's a submenu and marking the item as the selected one. It then makes a call to treeMenuDisplay() which results in an updated display of the menu.

For the menu root, we call treeMenuRootClick() instead which simply deletes the cookies and redraws the menu frame. This causes it to start with all folders closed and no item selected.

Source

The source for each file can be viewed using these links:

The images for the menu tree are shown below:

menu_root.gif menu_tee.gif
menu_bar.gif menu_tee_plus.gif
menu_folder_closed.gif menu_tee_minus.gif
menu_folder_open.gif menu_corner.gif
menu_link_local.gif (default) menu_corner_plus.gif
menu_link_external.gif (default) menu_corner_minus.gif
menu_link_ref.gif (custom) menu_link_java.gif (custom)
menu_pixel.gif (single transparent pixel, used for spacing)

You can also download treeMenu.zip which contains all the above files.


Home