DHTML Lab: Hierarchical Menus Version 3 | 20 | WebReference

DHTML Lab: Hierarchical Menus Version 3 | 20


Hierarchical Menus: Version 3
Explorer menu re-creation


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 = "#DDDDDD";
overCol = "#CCCCCC";
overFnt = "purple";
borWid = 0;
borCol = "black";
borSty = "solid";
itemPad = 3;
imgSrc = "tri.gif";
imgSiz = 10;
separator = 1;
separatorCol = "red";
isFrames = false;
keepHilite = false; 
NSfontOver = false;
clickStart = true;
clickKill = true;
showVisited = "";

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

For Explorer, startIt() sets the menu frame unload handler to call the IEunloaded function:
menuLoc.document.body.onunload = IEunloaded;

The Good News

IE4 introduced the onreadystatechange event handler for these objects/elements:

  • IMG
  • LINK
  • document

As you can tell from the type of objects that fire this event, they are elements that load a file or control (the first seven), or are files themselves (document). That is, objects that require a server visit to load fire the readystatechange event.

The Microsoft Internet SDK (official DHTML docs) describe the event in this way:

Fires whenever the ready state for the object has changed.

Each object can choose to expose which set of ready states it is exposing. This event should be fired whenever the ready state is changed.

When an element changes to the loaded state, this event fires immediately before the firing of the load event. This event will not bubble. Events that do not bubble can only be handled on the individual object that fired the event.

Microsoft Copyright Notices for Materials Used

Five of the objects (IMG, LINK, OBJECT,SCRIPT, STYLE and document) have a readyState property which reflects the current state of the object. APPLET and EMBED load objects foreign to Explorer and cannot be queried. In the case of APPLET, it is a Java applet, and for EMBED, it could be any plug-in.

When the readystatechange event fires, the readyState property of the object is updated to one of four values:

unitializedthe object is not initialized with data
loadingthe object is currently loading its data
interactivethe object can be interacted with even though it is not fully loaded
completethe object is completely loaded

It stands to follow, therefore, that we can track the state of our frame's document by applying the onreadystatechange handler to it, and when it unloads (anything but "complete"), wait for it to load ("complete"), then rebuild the menus. Right?


The Bad News

In the documentation, above, it states that onreadystatechange "should be fired whenever the ready state is changed." I could not capture it, although it does fire since the readyState property of the document is correctly updated.

Since Explorer cannot tell us when the state changes, we must do it ourselves, in the following way. The IEunloaded() function, called when the menu frame unloads, looks like this:

function IEunloaded() {
    isLoaded = false;

IEunloaded() re-initializes our variables, sets isLoaded to false, then waits 50 milliseconds before calling a new function, keepTrack(). This pause gives the frame the time it needs to complete the unload and therefore change the readyState of the document from "complete" to "loading". When keepTrack() is called, a new page is loading into the main frame.

function keepTrack() {
    if (menuLoc.document.readyState == "complete") {
    else {

keepTrack() checks the frame document's readyState property at regular short intervals (50 milliseconds). If readyState is "complete", it means the page has loaded, so we can rebuild our menus, by re-initializing the variables and calling startIt().

Now that we know how to track the state of the menu frame for both browsers, let's return to the main flow of our script. When last we looked at it, startIt() was completing its duties and calling makeTop().

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/hier3Track.html