[ Team LiB ] |
10.9 Providing Navigation Trail MenusNN 4, IE 4 10.9.1 ProblemYou 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 SolutionCustomize 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( )); </script> </div> Figure 10-3. A "bread crumb trail" menu10.9.3 DiscussionThis 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) catalog/ index.html (intro to catalog and links to categories) economy/ [many .html pages for this category] deluxe/ [many .html pages for this category] export/ [many .html pages for this category] support/ index.html (intro to support and links to categories) contact.html faq/ downloads/ manuals/ 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 libraryvar 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 = " » "; 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:
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 → or ⇒ 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 AlsoRecipe 1.1 for building long strings from bits and pieces; Recipe 14.1 for using document.write( ) while the page loads. |
[ Team LiB ] |