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.

Some of the features:

  • 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, fonts and graphics to suite your needs.

Using the Script

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:

  • index.html - defines the left and right frames and imports the JavaScript code.
  • 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 an item is clicked on.
  • 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 ("").

  • treeMenuBackground - URL of an image to use for the menu frame background. Set to a null string ("") if you don't want a background image. Note that treeMenuImgDir is not used for the image, you should specify the same URL you would use in a <BODY> tag.

  • 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".

  • treeMenuFont, treeMenuFontSize - These values will be used for the face and size paramters of the <font> tag for menu text. The menu at left uses "MS Sans Serif,Arial,Helvetica" with a size of "1".

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

  • treeMenuFolders - Controls the display of the '+' and '-' icons next to folders. If set to 1, the icon will always appear next to a folder. When set to 0 the icon will only appear next to folders that contain one or more sub-folders. Setting this to -1 means the icons will never appear.

  • treeMenuAltText - May be true or false. If set to true, images for the menu icons will use the item text for the ALT parameter. Most current browsers will display this as a tool tip when the icon is moused over. This can be useful when the item text extends past the edge of menu frame.

All the above variables should be defined and set with a value. There are no defaults so leaving any out may cause the menu to fail. Here's a look at the values used for the menu at left:

var treeMenu = new TreeMenu();
var treeMenuName = "myMenu_1.0";
var treeMenuDays = 7;
var treeMenuFrame = "menuFrame";
var treeMenuImgDir = "graphics/";
var treeMenuBackground = "";
var treeMenuBgColor = "#ffffff";
var treeMenuFgColor = "#000000";
var treeMenuHiBg = "#008080";
var treeMenuHiFg = "#ffffff";
var treeMenuFont = "MS Sans Serif,Arial,Helvetica";
var treeMenuFontSize   = 1;
var treeMenuRoot = "Site Menu";
var treeMenuFolders = 0;
var treeMenuAltText = true;

Defining the Menu

The file treeMenuCode.js defines two new JavaScript objects, TreeMenu and TreeMenuItem along with some methods to add 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("Active Server Pages"));
treeMenu.addItem(new TreeMenuItem("Dynamic HTML"));
treeMenu.addItem(new TreeMenuItem("Java"));
treeMenu.addItem(new TreeMenuItem("JavaScript"));
treeMenu.addItem(new TreeMenuItem("About This Site",
  "/about.html", "_blank"));
treeMenu.addItem(new TreeMenuItem("Contact Brain Jar",
   "/contact.asp", "_blank"));
treeMenu.addItem(new TreeMenuItem("What's New",
   "/new.html", "_blank"));

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 (you could define a link for them as well, but in this case we won't). 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 'Active Server Pages', treeMenu.items[1] is 'Dynamic HTML', etc.

Defining and Attaching Submenus

We create submenus just like the main menu, using new variables. Here we'll create the 'Active Server Pages' submenu:

var asp = new TreeMenu();
asp.addItem(new TreeMenuItem("Code Examples"));
asp.addItem(new TreeMenuItem("Sites"));

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(asp);

This makes the first item in treeMenu a submenu which contains all the items defined in asp.

Each of the items on the 'asp' submenu is also a submenu so for each we create a new TreeMenu, add items to it and then attach it to the appropriate item in the asp submenu.

// Define ASP code examples submenu and
// attach to first item of ASP submenu.

var asp_ex = new TreeMenu();
asp_ex.addItem(...);
asp_ex.addItem(...);
...
asp.items[0].makeSubmenu(asp_ex);

// Define ASP sites submenu and attach
// to second item of ASP submenu.

var asp_sites = new TreeMenu();
asp_sites.addItem(...);
asp_sites.addItem(...);
...
asp.items[2].makeSubmenu(asp_sites);

The creation of the DHTML submenus is similar.

Now for the 'Java Applets' submenu we add some items and attach it to the main menu. It has no submenus of it's own so this is all we need to do with it.

var java = new TreeMenu();
java.addItem(...);
java.addItem(...);

...

// Attach to second item of main menu.

treeMenu.items[1].makeSubmenu(java);

The 'JavaScript' submenu is also similar to the 'Active Server Pages' and 'DHTML' submenus so there's no need to repeat the code here.

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

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.

Tip: When you update a menu definition, change the value of treeMenuName as well. This will force the script to start create new cookies for the menu data. Otherwise, the old cookie values may be used and this can cause the menu to not work properly.

How it Works

The script defines two objects. One representing an individual menu and another representing an individual item. An item can itself be a menu, allowing for a hierarchial tree structure to be built.

The TreeMenu and TreeMenuItem Objects

The TreeMenu object consists simply of an array used for storing items. It has one method, addItem(), for adding a menu item to this list.

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 pointer which can be set to a TreeMenu object if it is to be a folder. The makeSubmenu() method is used to assign this pointer. 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 hierarchical 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 that new cookies will be created from scratch and the old cookie values won't conflict with the new menu structure.

If the user's browser does not support cookies, or if they have been disabled, the menu state will be lost when the user exits the page.

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 to run the treeMenuScroll() function, which will scroll the page if necessary for the selected item to 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 and background, if any. It also adds a call to treeMenuScroll() in the onload event of the body tag.

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 so the proper 'tee' or 'corner' graphic can be used.

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 item'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, all are 18x18 pixels in size:

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_spacer.gif (transparent, used for spacing)

You can also download treeMenu.zip (17K) which contains all the above files.


Home