DHTML Lab: Hierarchical Menus Ver. 2 (Cross-Browser/Frames); onLoad | WebReference

DHTML Lab: Hierarchical Menus Ver. 2 (Cross-Browser/Frames); onLoad


Hierarchical Menus Ver. 2 (Cross-Browser/Frames)


Parameters used for the menus on this page:

menuWidth = 120;
childOverlap = 50;
childOffset = 5;
perCentOver = null;
secondsVisible = .5;
fntCol = "blue";
fntSiz = 10;
fntBold = false;
fntItal = false;
fntFam = "sans-serif";
backCol = "#DDDDDD";
overCol = "#FFCCCC";
overFnt = "purple";
borWid = 2;
borCol = "black";
borSty = "solid";
itemPad = 3;
imgSrc = "tri.gif";
imgSiz = 10;
separator = 1;
separatorCol = "red";
isFrames = false;

Menu Animated GIF
Animated GIF demonstrating heirarchical menus for non-DHTML browsers.

In longer 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.

Window or Frame

The menus are created when the window or frameset loads. Our first task, therefore, in our main script is to assign the onload event handler. Should it handle a full-window page load or a frameset load? We create the loader variable and assign to it the relevant object, depending on the value of isFrames and the browser being used:

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

The statement above is our first use, in these columns, of nested JavaScript "?:" special conditional operators. The above is the same as this verbose version:

if (isFrames) {
    if (NS4) {
        loader = parent;
    else {
        loader = parent.document.body;
else {
    loader = window;
loader.onload = startIt;

Once our page/frameset is loaded, the startIt() function will be called.

More Variables

Next, we establish the child menu overlap based on the value of perCentOver, if it has a value assigned to it. mSecVis stores the millisecond value of the delay-before-hiding of top-level menus, and imgStr contains HTML for the right-aligned image that denotes the existence of a child menu for an item. All three statements are the same as version 1.

if (perCentOver != null) {
    childOverlap = (perCentOver/100) * menuWidth
mSecsVis = secondsVisible*1000;
imgStr = "<IMG SRC=" + imgSrc + " WIDTH=" + imgSiz +
[cc] " HEIGHT=" + imgSiz +" BORDER=0

The remainder of our global variables are declared in a function, just as we did in version 1 (frames). There is one new variable, beingCreated:

function initVars() {
    topCount = 1;
    areCreated = false;
    beingCreated = false;
    isOverMenu = false;
    currentMenu = null;
    allTimer = null;

topCount - tracks the total of top-level menus created
areCreated - tracks whether the menus have been created
beingCreated - tracks whether the menus are in the process of being created
isOverMenu - tracks whether the user's cursor is over a menu
currentMenu - tracks the menu the user's cursor is over
allTimer - initialization of timer variable to be used with setTimeout()

Once the initVars() function is defined, we call it, initializing the variables:


Final Overhead Tasks

When the page/frameset loads and startIt() is called, it first assigns a value to a new variable, menuLoc, which stores the location of the menus. If we are working with a frameset, the menu location will be the frame name previously stored in mainFrName. If we are working with a full window page, menuLoc is assigned the window object.

If we are working with a frameset, the main frame's onunload event handler is assigned the initVars() function, as in Version 1 (frames). This assures that our global variables are re-initialized when the page in the main frame is exited, allowing us to recreate the menus for the page that will replace it in the frame.

function startIt() {
  if (isFrames) {
    menuLoc = eval("parent.frames." + mainFrName);
    if (NS4) menuLoc.onunload = initVars;
    if (IE4) menuLoc.document.body.onunload = initVars;
  else {
    menuLoc = window;
  if (NS4) setTimeout("loader.onresize=reDo",100);

We then guard against the Navigator resize problem, by capturing and directing the resize event. This technique is described in detail in DHTML Diner.

Lastly, startIt() passes control to makeTop(), which will oversee the creation of the menus.

Produced by Peter Belesis and

All Rights Reserved. Legal Notices.
Created: May. 22, 1998
Revised: May. 22, 1998

URL: http://www.webreference.com/dhtml/column20/hier2Load.html