DHTML Lab: Hierarchical Menus Version 3 | 9 | WebReference

DHTML Lab: Hierarchical Menus Version 3 | 9


Hierarchical Menus: Version 3
variable declaration


Click the link above to reveal menu. Click anywhere on the page to hide menu.

Parameters used for the menus on this page:

menuVersion = 3;
menuWidth = 120;
childOverlap = 50;
childOffset = 5;
perCentOver = null;
secondsVisible = .5;
fntCol = "black";
fntSiz = "10";
fntBold = false;
fntItal = false;
fntFam = "sans-serif";
backCol = "#FCC997";
overCol = "#B36A09";
overFnt = "black";
borWid = 2;
borCol = "black";
borSty = "solid";
itemPad = 3;
imgSrc = "tri.gif";
imgSiz = 10;
separator = 1;
separatorCol = "black";
keepHilite = true; 
NSfontOver = false;
clickStart = true;
clickKill = true;
showVisited = "";
isFrames = false;

Background Reading:

  column 18
  column 20

<SPACER> tag:
  column 10

  column 14
  column 18
  column 20

In script listings, cross-browser code is blue, Navigator-specific code is red, and Explorer code is green.

The [cc] symbol denotes code continuation. The code is part of the preceding line. It is placed on a new line for column formatting considerations only.

It must be repeated here that, unless you are familiar with version 2 of the menu script, the remainder of this column will seem unfathomable. We will discuss only the version 3 additions and modifications. Suggested background reading for each page is linked to in the left column.


The script begins as before, by identifying the existence of a frameset and defining the onload handler accordingly:

loader = (isFrames) ? (NS4) ? parent :
[cc]  parent.document.body : window;
loader.onload = startIt;

Load state variables

Two new variables are declared to help us track the load state of the window/frame that contains the menus:

isLoaded = false;
NSresized = false;
The first, isLoaded, will remain false until the menu window/frame has fully loaded. It is used to avoid errors when mousing over menu display links during page load, and for recreating menus in framesets when the menu frame loads.

The second, NSresized, tracks the firing of the window resize event for NS4 users. We will use it to minimize the harm done to DHTML by user resizing of the browser window.

Compatibility with Older Versions

Next, we check for the existence of the menuVersion variable. If it exists, it means that the parameter variables are for version 3. If it doesn't exist, we must be working with an old page, so several features are turned off by setting the new version 3 parameters to false.

if (!window.menuVersion) {
    clickKill = showVisited = NSfontOver =
    [cc]  keepHilite = clickStart = false;

Right-to-Left Cascade

The mSecsVis variable is set, as before, and then we introduce a new variable: isRight. Version 3 allows menus to cascade from the right to left "properly." That is, not only are the child menus placed on the left of the parents, but the triangle image appears on the left and items are indented accordingly.

mSecsVis = secondsVisible*1000;
isRight = (window.navFrLoc && navFrLoc == "right");

As mentioned previously, the navFrLoc variable can be set in a non-frameset document (with isFrames set to false) to denote menus that should cascade from right to left. isRight identifies the existence of navFrLoc, and whether it is set to "right". Menu creation and display statements will later check the value of isRight to determine menu look and behaviour.

The "more" Image

Since our triangle image can now appear either on the right or the left, the imgStr variable is constructed with reference to isRight:

imgSuf = (isRight) ? ">"  : "ALIGN=RIGHT>";
imgStr = "<IMG SRC=" + imgSrc + " WIDTH=" + imgSiz +
[cc]  " HEIGHT=" + imgSiz +" BORDER=0 VSPACE=2 " + imgSuf;
spStr = (isRight && NS4) ? "<SPACER TYPE=HORIZONTAL SIZE="+imgSiz+">" : "";

We first create imgSuf, a "suffix" for imgStr which omits the standard ALIGN=RIGHT attribute if the image should appear on the left. (i.e. if isRight is true). Our image HTML (imgStr) is then built by appending imgSuf to the HTML string.

In a right-to-left menu tree, items without a child menu, and consequently, without a triangle image, must be indented from the left margin to align vertically with items that have an image visible. In IE4, we dynamically change the left "padding" of an item, but in NS4, we have to add this space physically upon item creation. The best way, is to use the NS-specific <SPACER> tag. If the menus are not right-to-left or the browser used is IE4, then the spacing variable, spStr, is assigned an empty string value.

In a frameset, the imgSrc variable should be an absolute URL! (ex. http://www.webreference.com/dhtml/art/tri.gif) This will allow all main frame pages to access it, since some of these pages may not be in the same directory as the original frameset.

General Variables

Two old variables, menuLoc and areCreated, have an additional role in version 3. They are referenced when clearing the various timeouts set by the script. A major problem with version 2 was the IE4 timeout behaviour in framesets. The "hide" timers were still in effect even after a new page loaded, resulting in script errors. In version 3, we will be clearing all timer variables when the page unloads, starting with a clean slate with every new page. We therefore declare these two variables as global variables, early in our script. The menus have not been created, so areCreated is false. We have yet to determine the page/frame in which the menus will reside, so menuLoc is null.

menuLoc = null;
areCreated = false;

The function that sets and resets our major variables, initVars(), has one major addition. It clears all timer variables if the menus have been created. This means that the first time it is called, when areCreated is false, it will skip the timer-clearing statements. On subsequent calls, when the page is unloading, and areCreated is true, the timer variables will be cleared, and script errors avoided.

function initVars() {
    if(areCreated) {
        for(i=1; i<topCount; i++) {
            cur = eval("elMenu"+i);
    topCount = 1;
    areCreated = false;
    beingCreated = false;
    isOverMenu = false;
    currentMenu = null;
    allTimer = null;

Immediately after we define initVars(), we call it, as before, setting the variables.

Produced by Peter Belesis and

All Rights Reserved. Legal Notices.
Created: Sept. 03, 1998
Revised: Sept. 03, 1998

URL: http://www.webreference.com/dhtml/column21/hier3Load.html