10.9 Providing Navigation Trail Menus

NN 4, IE 4

10.9.1 Problem

You want the top of every page in a deep and highly structured site to display "bread crumb trails" of where the user is within a hierarchy path.

10.9.2 Solution

Customize and apply the trail.js library (shown in Example 10-5 in the Discussion) to a location on your pages where the menu trail is to appear. Figure 10-3 shows one example on a page that includes the following HTML and script call to the makeTrailMenu( ) function in the library:

<div id="trailMenu" style="position:absolute; left:200px; top:200px">
<script language="JavaScript" type="text/javascript">
document.write(makeTrailMenu( ));
Figure 10-3. A "bread crumb trail" menu

10.9.3 Discussion

This recipe assumes that your web documents on the server are structured in a directory hierarchy that matches the conceptual organization of the site. For example:

index.html (home at the root directory)
        index.html (intro to catalog and links to categories)
            [many .html pages for this category]
            [many .html pages for this category]
            [many .html pages for this category]
        index.html (intro to support and links to categories)

Example 10-5 shows the code for the trail.js library, which should be linked into every page of the site that fits within the structural hierarchy.

Example 10-5. The trail.js library
var trailMenu = new Object( );
trailMenu["catalog"] = "Product Line";
trailMenu["economy"] = "Budget";
trailMenu["deluxe"] = "Luxury";
trailMenu["export"] = "Export Only";
trailMenu["support"] = "Product Support";
trailMenu["faq"] = "Frequently Asked Questions";
trailMenu["downloads"] = "Free Downloads";
trailMenu["manuals"] = "Manuals";
function makeTrailMenu( ) {
    var parseStart, volDelim, parseEnd;
    var output = 
        "<span style='font-family:Arial, Helvetica, sans-serif; font-size:12px;" +
        "color:#000000; padding:4px'>";
    var linkStyle = "color:#339966";
    var path = location.pathname;
    var separator = "&nbsp;&raquo;&nbsp;";
    var re = /\\/g;
    path = path.replace(re, "/");
    var trail = location.protocol + "//" + location.hostname;
    var leaves = path.split("/");
    if (location.protocol.indexOf("file") != -1) {
        parseStart = 1;
        volDelim = "/";
    } else {
        parseStart = 0;
        volDelim = "";
    if (leaves[leaves.length-1] =  = "" || leaves[leaves.length-1] =  = "index.html" || 
        leaves[leaves.length-1] =  = "default.html") {
        parseEnd = leaves.length -1;
    } else {
        parseEnd = leaves.length;
    for (var i = parseStart; i < parseEnd; i++) {
        if (i =  = parseStart) {
            trail += "/" + leaves[i] + volDelim;
            output += "<a href='" + trail + "' style='" + linkStyle + "'>";
            output += "Home";
        } else if (i =  = parseEnd - 1) {
            output += document.title;
            separator = "";
        } else {
            trail += leaves[i] + "/";
            output += "<a href='" + trail + "' style='" + linkStyle + "'>";
            output += trailMenu[leaves[i]];
        output += "</a>" + separator;
    output += "</span>";
    return output;

The library begins by defining an object whose string property names are the various directory names of your site (in any order) and the corresponding plain language label you want to appear in the menus. Next is the makeTrailMenu( ) function, which assembles the HTML for the page's navigation trail menu, based on the path of the current document and its title. This example uses a guillemet character (») to act as arrows between levels.

This trail menu system works best on sites that serve up pages from .html files because the location.pathname property contains a lot of the information that the code uses to generate the menus. You can also make this work with sites served by server-side programs (.pl, .asp, .jsp, .php, and others), provided the directory structure is preserved. Of course, if you are using server programming to generate content for pages, you might as well use that programming power to assemble the menu trail before ever leaving the server.

The only implementation and maintenance necessities are as follows:

  • Each page must have a descriptive <title> tag.

  • Each directory must have a home page (such as index.html or default.html) served up when the URL points to the directory.

  • Each file must include the trail.js library containing the data and routines.

  • Changes or additions made to the site's directory structure need to be noted in the trailMenu object definition in the trail.js file.

Employing a custom object (trailMenu) for the lookup table of directory names and user-friendly labels offers a much faster way of performing the lookups than a more typical array. Items do not have to be in any particular order with respect to the directory structure, but keeping the structures aligned makes it easier to maintain over time as directories are added, removed, and renamed.

You have virtually unlimited flexibility in the stylesheet attributes that affect the appearance of the trail menu. It is also possible to remove the style sheet from the tag and link it into the page from a separate .css file if you prefer, provided you assign an ID or class identifier to the menu container and associate the container with the imported style rule. Additionally, the menu can be in the page's body, in a table, or, as shown in the recipe, a positioned element unto itself.

Slightly more challenging is implementing this kind of menu within a frameset, where the menu occupies its own frame and the content that changes is in another frame. The same algorithms apply, but you have to watch out for two points in particular. First, you need a way to trigger the rewriting of the menu each time a content page changes. The way to do this is through the onload event of each page. It could invoke a function (loaded into each page from an external .js library) that assembles the menu (using the location property of the content window), and writes the content of the other frame. You also need to modify the links that surround each clickable item in the menu so that the target is the content-bearing frame.

In the recipe, the separator between hierarchy levels in the menu consists of a character that looks like an arrow (a guillemet character is actually a right-pointing double angle quotation mark). I would have liked to have used a character that looked more like an arrow, such as the &rarr; or &rArr; entities, but neither is supported by IE for Windows (through Version 6) or Netscape prior to Version 7 (although they are supported in IE 5 for the Macintosh). But the separator can be any HTML of your choice, including an image. Simply assign the HTML to the separator variable.

10.9.4 See Also

Recipe 1.1 for building long strings from bits and pieces; Recipe 14.1 for using document.write( ) while the page loads.