This article may contain URLs that were valid when originally published, but now link to sites or pages that no longer exist. To maintain the flow of the article, we've left these URLs in the text, but disabled the links.


MIND


This article assumes you're familiar with HTML, Dynamic HTML, VBScript, and Active Server Pages

Working with the Dynamic HTML Tree Menu Builder
William McLuskie, Richard Burgin,
and Patty Moore

Download the code (74KB)

Frustrated by the lack of a standard menu for DHTML-based applications? The DHTML Tree Menu Builder is a tool that can create, edit, and generate menus for your Web site.
Menus are a standard component of almost every GUI-based application. When you develop applications in Visual Basic®, menus are a snap; Visual Basic provides a simple menu editor that allows you to define the structure of a menu within a form. When your application is running, Visual Basic and Windows® handle all of the work that is required to render and navigate the menu.

    When you move to a browser-based intranet or Internet application, you'll quickly find that creating menus is a lot more complex. You must address two main issues. First, there isn't a standard menu for browser-based applications. As you surf the net you will find menus at the top of a Web page, at the bottom, on the left, and on the right. You will also find that they all look different. Some menus have a traditional appearance with a gray bar and dropdown submenus; some look like a series of buttons; and some are just a single level of plain text. Many Web page developers will tell you that this doesn't reflect a lack of standards, but rather freedom of expression. That's great if you want to build an artistic site or a personal Web page, but not for a business application. Your customers expect a consistent, intuitive, and easy-to-use way of navigating your application. As a programmer, you want something that is easy to develop and maintain and that performs well.

    The second issue stems directly from this lack of interface standards. Since there is no standard menu structure, you don't have a simple menu editor to use. That brings us to the purpose of this article; the DHTML Tree Menu Builder is a menu editor that you can use to create and maintain tree menus. In this article, we will describe the style of tree menu that the DHTML Tree Menu Builder generates and how it works. We will also explain the Dynamic HTML (DHTML) and HTML code that is used to render and navigate the menu. We will continue with a discussion of the two approaches that can be used to implement the tree menu—HTML files for statically built menus and Active Server Pages (ASP) files for dynamically built menus—and the advantages and disadvantages of using each approach. Finally, we will explain how the DHTML Tree Menu Builder can be used to create tree menus and generate the associated HTML and ASP files. The complete code for the DHTML Tree Menu Builder is available for download from the link at the top of this article.

The Tree Menu Style

    The menus generated by the DHTML Tree Menu Builder are designed to be placed in a frame on the left edge of your application and are implemented as a collapsible tree menu (see Figure 1). When first displayed, only the major menu headings are visible. The user sees the text for the menu headings and a plus sign to the left of the text. In the sample tree menu, Developers is a menu heading. To expand a menu heading, the user can either click the menu heading text or the plus sign. When expanded, a submenu will be displayed directly under the menu heading, and the plus sign changes to a minus sign. Each submenu is indented to make the menu more readable and to show the menu's hierarchical structure. To hide a submenu, the user can either click the menu heading text or the minus sign.

Figure 1: A Tree Menu
      Figure 1: A Tree Menu

    Submenus can contain additional menu headings or menu items. Menu items are identified by underlined text and are preceded by a bullet. Clicking on the text or the bullet triggers an action. In the sample, the menu items are links to either Web pages or email addresses. You can change this and trigger any action you want by placing the correct code in the onClick event of the menu items.

    When the user moves the mouse over a menu heading, menu item, or any of the graphics, the color of the text will change. When the mouse is moved off the text or graphic, the text is returned to its original color. This nice feature gives your users feedback while they are navigating the menu.

    Below the menu, we have included two buttons: Expand All and Collapse All. The Expand All button will expand all of the menu headings in the menu, making every menu item visible (see Figure 2). The Collapse All button does the opposite, hiding all of the menu items and all of the menu headings except the topmost menu headings (see Figure 3).

Figure 2: Expanding all Menu Items
      Figure 2: Expanding all Menu Items

Figure 3: Collapsing all Menu Items
      Figure 3: Collapsing all Menu Items

Tree Menu Code

    Now that you've seen what the menu does, let's examine the code that makes it work. Look at the code in Team.htm, shown in Figure 4. There are three main sections of the code that we need to discuss: the <BODY> tag, the menu definition, and the mouse handler subroutines. (Note that the DHTML and VBScript used in this article require Microsoft® Internet Explorer 4.0 or later.)

    The <BODY> tag and its 11 attributes are straightforward. The first five set the colors used for the page's text and background. The next two attributes set the page margins within the browser. The eighth attribute is LANGUAGE, which is set to VBScript. Since Internet Explorer defaults to JScript®, we must explicitly declare that we are using VBScript in our mouse handler subroutines. The last three attributes are used to associate the mouse events we need to trap with our mouse handler subroutines.

    The menu definition itself is the chunk of HTML code near the center of the file. The definition for the entire menu is wrapped inside a <DIV> tag. The primary purpose of the <DIV> tags is to control the indentation within the menu. This is accomplished by setting the MARGIN-LEFT style attribute on each <DIV> tag.

    The basic format for the menu definition is:

 <IMG  ID=MI-n><SPAN  ID=MT-n>  Menu Heading Text  </SPAN>
 <DIV  ID=C-n  STYLE="MARGIN-LEFT:nn;DISPLAY:NONE;" >
 Submenu
 </DIV>
Note that this is not complete HTML code; it's meant to show the attributes we are discussing. Each menu header is assigned a unique ID number to identify it. When the DHTML Tree Menu Builder is used, the ID numbers are generated as contiguous integers beginning with one. The ID number is then used to build the ID attributes for the menu heading's <IMG>, <SPAN>, and <DIV> tags.

    Each menu heading is preceded by the plus sign. The ID attribute for the <IMG> tag is in the format of MI-n, where MI stands for menu image and n is the menu heading's ID number. The menu heading text is then enclosed within a <SPAN> tag. The ID attribute for the <SPAN> tag is in the format of MT-n, where MT stands for menu text and n is the menu heading's ID number. The submenu itself is enclosed within a <DIV> tag. The ID attribute for the <DIV> tag is in the format of C-n, where C stands for child and n is the menu heading's ID number. There are two style settings in the <DIV> tag. The first, MARGIN-LEFT, is used to control indentation. The second, DISPLAY:NONE, is used to initially hide the contents of the submenu.

    We are only concerned with trapping three mouse events for our tree menu: onClick, onMouseOver, and onMouseOut. These are associated to the three subroutines: clickHandler, mouseOverHandler, and mouseOutHandler. The clickHandler subroutine is responsible for showing or hiding the appropriate submenu and changing the graphic to either a plus or minus sign. This subroutine is also responsible for the action found in the Expand All and Collapse All buttons. The mouseOverHandler and mouseOutHandler routines are responsible for changing the color of the menu text whenever the mouse moves over the text or graphic for a menu heading.

    Take a few minutes to examine the code for these handlers. They all follow the same basic format:

  • Identify the object on which the event fired.
  • Determine the ID number of the menu heading associated with that object.
  • Build the appropriate IDs for the menu image (MI-n), menu text (MT-n), and child division (C-n).
  • Change the style attributes for the <IMG>, <SPAN>, and <DIV> tags.

Less Static, More Dynamic

    This approach to building tree menus is not so simple. It is easy to understand how the code works, but the problem is in building and maintaining a tree menu that has more than a few menu headings and menu items. We started to have difficulty when our menus reached a hundred or so elements and we needed to modify the tree menu.

    Removing an item is straightforward; just search on the menu text and delete the appropriate lines from the code. Adding or moving a menu item is more difficult. When you create a menu heading, it must have a unique ID number. You can attempt to keep your ID numbers sequential, but then each time you add a menu heading you have to renumber all of the MI-n, MT-n, and C-n attributes in the menu definition from the point you added the new menu heading. This is a cumbersome task in a large menu definition.

    Another approach would be to arbitrarily make up a new ID number. You would then have to do a search through the code to ensure that the ID number has not been used already. If you use the same ID number for more than one menu heading, the menu headings with duplicate ID numbers will not expand. Using either approach, try to imagine assigning a change to the menu definition to a less experienced programmer or to yourself six months from now. The time it takes to familiarize yourself with the code is not cost effective.

    In the next implementation of the tree menu, we wanted to reduce the amount of static HTML required to define the menu and replace it with a more dynamic definition. The first step in doing this was to specify a way to define a tree menu using a database table (see Figure 5). The menu table contains five columns, which are described in Figure 6. Currently there are seven control settings that you can use (see Figure 7). All seven are used to set the colors that are used by the browser to render your tree menu. If you leave any of these settings out, a default value will be used.

Figure 5: Tree Menu Database Table
      Figure 5: Tree Menu Database Table

    One thing to note is the use of the E menu type. The M menu type indicates a menu header. Everything that follows it, up to the next E, is the definition for the submenu. Therefore, every M must have a corresponding E. It is possible to nest submenus within other submenus.

    Figure 8 provides the definition for the sample tree menu. Now that we have a definition for a tree menu in the database, we need to transpose the definition into something that is understandable to the browser. To do this, we created an ASP file that reads the database and dynamically generates the required HTML code (see Figure 9).

Figure 8: A Tree Menu Definition
      Figure 8: A Tree Menu Definition

    The Team.asp file is essentially the same as Team.htm. The <BODY> tag and the mouse handler subroutines are the same. The difference is in the middle of the file. Rather than having the static HTML definition of the menu, you'll find this line:

 Response.Write buildMenu()
The buildMenu function reads the menu definition from the database and returns a string that contains the definition converted into HTML code. In fact, if you run Team.asp, then use the browser's View Source command, you'll see that the HTML sent to the browser is identical to the HTML found in Team.htm.

Is More Dynamic Better?

    At this point, we've introduced two ways of building tree menus: a static HTML definition and a dynamic database definition. Let's ask a few questions about the two techniques.

    Is it easy to create a new menu? No. In order to create the static definition, you must understand HTML and the format of the definition in the HTML code. To create the dynamic definition, you must know SQL (or some other tool to manipulate the database) as well as the format of the definition in the database.

    Is it easy to modify a menu? No. It is difficult and time-consuming to make changes to the static HTML code or to the definition records in the database.

    Is the menu definition intuitive? No. Both the static definition in the HTML code and the dynamic definition in the database are physically different from the tree menu itself. It is often difficult to manipulate either definition without being able to visualize the definition's representation as a tree menu. You must edit the definition, then run the corresponding HTML or ASP file in order to see your changes.

    Is the approach efficient? Yes. The HTML file is created during development and delivered when requested by the browser. This is simple and efficient. When using the dynamic definition, on the other hand, each request from the browser requires the ASP file to open and query the database. It must then process the definition, build the menu, and return the HTML. The static definition is best for menus that hardly ever change, while the dynamic definition is suited for menus that change on a daily or even hourly basis.

    So you have two solid approaches for delivering tree menus to the browser. The problem lies in creating and editing the menu definitions themselves. The best solution is to wrap the menu definitions into some sort of GUI. Which brings us to the DHTML Tree Menu Builder.

The DHTML Tree Menu Builder

    The DHTML Tree Menu Builder is a Windows-based application that allows you to create and modify the definition for a tree menu. You can then use the definition to generate either a static HTML file or a dynamic ASP file.

    The DHTML Tree Menu Builder application uses the same database table that we discussed earlier to store the tree menu definitions. When the application starts, the user is prompted to enter the names of the database and the table where the definition is stored and the name of the tree menu (see Figure 10). The user may alternatively select File | New to create a new definition. Currently, the application is coded to work with a Microsoft Access.mdb file that is located in the same directory as the application.

Figure 10: Tree Menu Information
      Figure 10: Tree Menu Information

    At the top of the main window, you will find a block of information about the current menu and its corresponding definition (see Figure 11). This includes the names of the database and table where the definition is stored, the definition, the generated static HTML file, and the generated dynamic ASP file.

Figure 11: DHTML Tree Menu Builder Main Window
      Figure 11: DHTML Tree Menu Builder Main Window

    Just below the information block, there are seven dropdown listboxes. These correspond to the seven pieces of control information that we discussed earlier. Next, there are four arrows. These allow the user to manipulate the items in the menu. The right arrow demotes the currently selected item to make it a child of the item directly above it, in effect creating a submenu. The left arrow promotes the currently selected item to make it a sibling of its parent, in effect removing it from the submenu. The up and down arrows are used to move the currently selected item either up or down. If the item is a submenu item, you are only allowed to move it within the submenu in which it is defined. If the item is a menu heading, all of the items in its submenu will be moved also. These four arrow buttons are similar in functionality to the four arrow buttons found in the Visual Basic Menu Editor. Next, there are three command buttons that allow the user to add a new menu item below the currently selected item (see Figure 12), edit the currently selected item, or delete the currently selected item.

Figure 12: Adding a Menu Item
      Figure 12: Adding a Menu Item

    The bottom portion of the main window is used to display the tree menu definition in a tree view control. This allows the user to see the menu in the same way it will be rendered in the browser. If a menu item contains a link, the URL for the link is displayed to the right of the menu text. For regular links (menu type L), the URL is enclosed in round brackets. The URL for an external document link (menu type D) is enclosed in square brackets. This is meant to help the user distinguish between the two different types of links without knowing about the L and D menu type codes.

    The application's menu bar includes File, Menu, and Help. Under the File menu, you'll find New Definition, Open Definition, Save Definition, Save Definition As, and Exit. The first two of these are used to create a new definition or open an existing definition and load it from the database table. The next two are used to write any changes back to the database.

    The Menu menu contains two items. Build Menu in HTML is used to create a .htm file that contains a static HTML definition for the current tree menu. Build Menu Driver in ASP is used to create the ASP file that contains the VBScript to load the tree menu definition from the database at runtime. Finally, the Help menu contains the standard Help and About menu items.

    Try out the application. Load up the sample tree menu and change it around. Create a new tree menu from scratch, save the definition to the database, and then look at the table to see exactly how the definition was saved. Then generate HTML and ASP files for testing in your browser.

    The DHTML Tree Menu Builder application was initially written in a few hours. It is not a complicated application, nor is it flashy. There are no bells or whistles, but a little bit of code has solved the three problems we mentioned earlier, and has provided several advantages. Let's go through our four questions again, basing our answers on this application. Is it easy to create a new menu? Yes. The GUI makes it simple since the user no longer needs to understand HTML, SQL, or the format of the definition itself. The user can also see the layout of the tree menu in the application as the definition is being built.

    Is it easy to modify the menu? Yes. Modifying a menu is as easy as opening, editing, and saving it. Again, no special knowledge of HTML, SQL, or the format of the definition is required.

    Is the menu definition intuitive? It doesn't matter because the format of the menu definition is completely hidden from the user.

    Is the approach efficient? Yes. The GUI allows the user to create a tree menu quickly and easily. Then the user can generate either the static HTML file or the dynamic ASP file, depending on the needs of the site.

    The DHTML Tree Menu Builder application provides several other advantages. First, it makes it easy to clone a tree menu by opening an existing definition, making changes, and then saving it as a new menu. Second, it enforces good programming standards in the HTML and DHTML code of your HTML and ASP files. Third, it takes care of the HTML, DHTML, VBScript, and database access details for you. And finally, it can be delivered to a client or user who is not a software developer to let them maintain their own tree menus.

Summary

    This article we covered a lot of ground. First, we took a look at the HTML and DHTML code used to render and manipulate a tree menu in the browser. Second, we described the use of static HTML versus dynamically generated HTML. Third, the code demonstrates using ActiveX Data Objects to access a table from both ASP, VBScript, and a Visual Basic-based application. Finally, we presented a good example of building and using a code generator to help you follow the old maxim, "Work smarter, not harder."

MSDN
http://msdn.microsoft.com/voices/archive.asp#clinic
and
http://msdn.microsoft.com/scripting

From the July 1999 issue of Microsoft Internet Developer.