Tree Menu v1.4 Mack Pexton July 13, 2006



It has become common lore with XHTML/HTML programming community that menus should be constructed out of <UL> and <LI> tags and that their appearance should be determined by CSS style settings. TreeMenu is a JavaScript program that scans a <UL> and <LI> structure and makes menus that have submenus which expand or contract when clicked. For example:

Clicking on the plus symbol symbol expands the menu whereas clicking on the plus symbol symbol collapses and hides the submenu.

TreeMenus are very easy to set up. First, include the JavaScript code in the header section between the <HEAD> and </HEAD> tags.

  <script src="TreeMenu.js" type="text/javascript"></script>

Next, after the menu's <UL></UL> tags in the HTML source code, enter the following script:

  <script type="text/javascript">make_tree_menu("menu_id")</script>

where the "menu_id" is the ID you defined in the menu's top <UL> tag.

That's it. The little plus symbol and plus symbol symbols are automatically added to the beginning of the line and all the submenus are opened or closed depending upon the state you last left them in.



A zip file of this document and the the TreeMenu JavaScript source code can be downloaded here:



There are several configuration settings that alter the behavior of TreeMenu. The all have the prefix TreeMenu. in their names. Following is a list of the configuration variables with their initial values.

TreeMenu.ClassOpen = 'open';         // class name added to LI tag's class
TreeMenu.ClassClose = 'close';       // class name added to LI tag's class
TreeMenu.ClassItem = 'item';         // class name added to LI tag's class
TreeMenu.ClassLast = 'last';         // added to last LI and symbol tags' classes

TreeMenu.SymbolTag = 'span';         // symbol inserted at beginning of LI tags

TreeMenu.SymbolClassOpen = 'symbol-open';
TreeMenu.SymbolClassClose = 'symbol-close';
TreeMenu.SymbolClassItem = 'symbol-item';

TreeMenu.CookieSaveStates = true;    // flag to use a cookie to save menu state
TreeMenu.CookieExpire = 90;          // days before cookie saving menu states expires

TreeMenu takes advantage of the ability of HTML elements to have two or more class names assigned to them. The ClassOpen, ClassClose, and ClassItem class names (if defined) are added to the <LI> elements in the menu. They allow the appearance of the menu items to change when a submenu is opened or closed.

The last elements in a list quite often have different visual characteristics than the other items. TreeMenu adds the class name that is assigned to ClassLast to the last menu item's class. The first elements in a list can also have a different appearance, and those elements can be identified (in modern browsers) by the CSS :first-child pseudo-element.

Symbols are inserted into the beginning of menu items. The type of symbol inserted before each <LI> tag's contents is determined by the class variable SymbolTag. It can be either "span" or "div" or it can be empty. A symbol is NOT inserted before the <LI> tags if the SymbolTag is set to the empty string.

The class name of the inserted symbols is set to either: SymbolClassOpen, SymbolClassClose, or SymbolClassItem depending upon if the <LI> tag has enclosed <UL> tags and whether the saved open/closed state of the <LI> tag is 1 or 0. The class name defined by ClassLast is added to the symbols inserted into the last menu item.

If a symbol is NOT inserted into the menu items, you must provide your own buttons to open and close the menus.You can use regular <A> tags to open and close menus by defining them with a click handler like:

  <a href="javascript:void 0" onclick="TreeMenu.toggle(this)">Submenu</a>

Menus' open/closed states are saved in a cookie with a name derived from the top <UL> tag's id unless the CookieSaveStates is set to false.

Using cookies to save menu states introduces some limitations. First, cookies can only be so large (about 4000 bytes) so only the states of about the first 1000 submenus can be saved. Second, the number of cookies that can be saved for any one domain is 20 which restricts the number of menus that can be saved.

The make_tree_menu() function has two optional arguments which, if set to true, turns off inserting symbols before each line and skips saving the open/close menu states in a cookie. They can be used instead of setting SymbolTag to the empty string and setting CookieSaveStates to false.

  <script type="text/javascript">make_tree_menu("menu_id",1,1)</script>

TreeMenu provides two methods to open or close a menu. They are and TreeMenu.hide(ul). I use the method to ensure a menu is open before highlighting the current menu item. They take only one argument that is the element object or id of the <UL> tag you want to show or hide. They are used like:

  var ul = document.getElementById("id_of_menu_ul_tag");;

The TreeMenu.show_all(ul) and TreeMenu.hide_all(ul) methods opens and closes all the menus under the specified <UL> tag.

As of TreeMenu v1.3, there is a TreeMenu.reset(ul) method that removes the cookie saving the state of the menus thereby returning the menus to their default state the next time the page is refreshed.

Multiple menus can be made and each menu can have a different settings for the configuration variables.

The first <UL> tag in a menu needs to be named with an ID attribute. Menus sharing the same ID name on all pages within a domain share the same menu states. In other words, menus opened by the user stay open when navigating from page to page.




Example 1: Basic

This menu is the same as the first example menu in the introduction.

The menu was created from the following <UL> and <LI> tags.

<div class="menu">
<ul id="example1">
<li>Blog Sites
  <li><a href="">Tommy Olsen</a></li>
  <li><a href="">Jeffrey Zeldman</a></li>
  <li><a href="">Eric Meyer</a></li>
<li>Other Sites
  <li><a href="">Accessify</a></li>
  <li><a href="">World Wide Web Consortium</a>
    <li><a href="">The W3C Markup Validator</a></li>
    <li><a href="">The W3C CSS Validator</a></li>
    <li><a href="">The Web Content Accessibility
<script type="text/javascript">make_tree_menu('example1');</script>
</div class="menu">

The images used in menu and the menu indentations are defined in the following CSS styles. I enclose my menus in <DIV> tags to make the style settings more generic and flexible.

/* Menu container */
.menu	{
	border:solid #FF9900 1px;
	padding:10px 5px 10px 5px;
	margin:12px 12px 12px 50px;

/* Menu styles */
.menu ul
.menu li
	margin:0px 0px 0px 5px;

/* Submenu styles */
.menu ul ul 
	{ background-color:#F6F6F6; }
.menu li li
	{ margin:0px 0px 0px 16px; }

/* Symbol styles */
.menu .symbol-item,
.menu .symbol-open,
.menu .symbol-close
	background-position:left center;
.menu .symbol-item  { background-image:url(icons/page.png); }
.menu .symbol-open  { background-image:url(icons/minus.png); }
.menu .symbol-close { background-image:url(icons/plus.png);}

/* Menu line styles */
.menu  { font-weight:bold; }
.menu li.close { font-weight:normal; }

The buttons "Show All", "Hide All", and "Reset" demonstrate the TreeMenu.show_all(ul), TreeMenu.hide_all(ul), and the TreeMenu.reset(ul) methods which opens or closes all the menus and removes the cookie preserving the users current menu states so the menus are displayed in their original default form.


Example 2: Simple

The following example shows the simplest of menus. There are not any CSS style settings, only the browser default settings are used. The menu consists of only <UL>, <LI> and <A> tags. No symbols are inserted at the beginning of each menu item. The bullets are the browser's standard bullet symbols.

Since symbols are not automatically inserted to open and collapse a menu, <A> tags have been defined with an onclick="TreeMenu.toggle(this)" attribute to open and close the menus.

The above menus were created from the following <UL> and <LI> tags. The second argument to make_tree_menu() that is set to 1 prevents the symbols from being automatically inserted at the beginning of the lines. We could have set the configuration variable TreeMenu.SymbolTag = ''; which would have also prevented the insertion of symbols.

<ul id="example2">
<li><a href="javascript:void 0" onclick="TreeMenu.toggle(this)">JavaScript</a>
  <li><a href=''>JavaScript Source</a></li>
  <li><a href=''>WebReference JavaScript Articles</a></li>
  <li><a href=''></a></li>
<li><a href="javascript:void 0" onclick="TreeMenu.toggle(this)">Web Development</a>
  <li><a href=''>Web Reference</a></li>
  <li><a href=''>Web Developer</a></li>
  <li><a href=''>WDVL</a></li>
<li><a href="javascript:void 0" onclick="TreeMenu.toggle(this)">Forums</a>
  <li><a href=''>XML</a></li>
  <li><a href=''>HTML</a></li>
  <li><a href=''>JavaScript</a></li>
  <li><a href=''>Perl</a></li>
  <li><a href=''>PHP</a></li>
<li><a href="javascript:void 0" onclick="TreeMenu.toggle(this)">Miscellaneous Web Sites</a>
  <li><a href=''>The Counter</a></li>
  <li><a href=''>The Guestbook</a></li>
  <li><a href=''>The List of ISPs</a></li>
  <li><a href=''>Internet Jobs</a></li>
<script type="text/javascript">make_tree_menu('example2',1)</script>

Example 3: Singular

This next example is like the previous with one exception (aside from different css settings): the call to make_tree_menu() has its fourth argument set to true, which is the same as setting the configuration variable TreeMenu.Singular to true. It allows only one menu (per level) to be open at a time. This type of menu is sometimes called an accordion menu.

  <script type="text/javascript">make_tree_menu("menu_id",1,0,1)</script>

Example 4: File List

The fourth example is a PHP program that produces a listing of files and folders on the server. Together with TreeMenu, the folders expand and collapse as in Window's Explorer.

File Listing