DHTML Lab: Cross-Browser Hierarchical Menus; Menu Setup | WebReference

DHTML Lab: Cross-Browser Hierarchical Menus; Menu Setup


Cross-Browser Hierarchical Menus
menu creation and setup



More menus.

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

Creating the Menu and Item Elements

In Explorer, when we want to create a new element, we simply insert the requisite HTML into our page, even after a page load. The best way is to use the insertAdjacentHTML() method, discussed in detail, with live examples, in column 5. In our Jigsaw Puzzle script, we used this method to create the puzzle pieces on-the-fly.

If we insert an element within another element, the enclosing element becomes the parent element (the offsetParent in IE lingo).

Our menus, regardless of level, have no parent element other than the page itself. For scripting purposes, Explorer provides the document.body object, which corresponds to the HTML enclosed in the <BODY> and </BODY> tags.

Our menu items are all enclosed within a parent menu element, which is passed as the second argument to makeElement(), the element-creating function.

As before, if no second argument is passed, the page element (document.body) is assumed.

function makeElement(whichEl,whichContainer) {
  if (arguments.length==1)
    whichContainer = (NS4) ? window : document.body;
  if (NS4) {
    eval(whichEl + "= new Layer(menuWidth,whichContainer)");
  else {
    elStr = "<DIV ID=" + whichEl + " STYLE='position:absolute'></DIV>";
  return eval(whichEl);

Menu Setup

The function that defines the custom menu properties and methods, menuSetup(), has only a few additional statements:

function menuSetup(hasParent,lastItem,openCont,openItem) {
  this.menuOver = menuOver;
  this.menuOut = menuOut;
  this.onmouseover = this.menuOver;
  this.onmouseout = this.menuOut;
  this.showIt = showIt;
  this.keepInWindow = keepInWindow;  
  this.hideTree = hideTree
  this.hideParents = hideParents;
  this.hideChildren = hideChildren;
  this.hideTop = hideTop;
  this.hasChildVisible = false;
  this.isOn = false;
  this.hideTimer = null;
  if (hasParent) {
    this.hasParent = true;
    this.parentMenu = openCont;
    this.parentItem = openItem;
    this.parentItem.child = this;
  else {
    this.hasParent = false;
    this.hideSelf = hideSelf;
  if (NS4) {
    this.fullHeight = lastItem.top + lastItem.document.height;
    this.clip.bottom = this.fullHeight;
  else {
    this.fullHeight = lastItem.style.pixelTop + lastItem.offsetHeight;
	this.onselectstart = cancelSelect;
    this.moveTo = moveTo;

The custom property, fullHeight, is determined by adding the vertical position of the last menu item and its content height. The two Explorer properties used, style.pixelTop and offsetHeight are very well known to us, and have been used very often in these columns. Navigator needed fullHeight to determine the menu height and clip to that height, and also for the keep-in-window calculation later. Explorer needs it only for the latter purpose, as it clips to its own height automatically.

Dynamically created elements in Explorer have a default visibility of "inherit". We do not want the menu to inherit the visibility of its parent (the page body) which is visible. Therefore, we hide it by passing false to its custom showIt() method.

Exporer allows us to detect when a user attempts to "highlight" parts of the page by dragging the mouse. The onselectstart event handler will fire when the user attempts to select within the menu and call cancelSelect() function. We will define this further down.

Explorer lacks a two-argument method for x-y element positioning, like Navigator's moveTo(). We therefore create a custom Explorer moveTo() method that will correspond to the Navigator moveTo().

We have all noticed that Explorer constantly adapts the display to accomodate element additions or modifications. While creating our menus, the user might notice the scrollbars changing size since the menus are inserted at the bottom of the page. If we move the menus to the top-left of the page (0,0), we will avoid this scrollbar behaviour as the page does not have to grow to include the invisible menus.

We'll discuss the functions that define the custom methods later. First let's look at itemSetup(), assigned to every item's setup() method.

Produced by Peter Belesis and

All Rights Reserved. Legal Notices.
Created: Feb. 27, 1998
Revised: Feb. 27, 1998

URL: http://www.webreference.com/dhtml/column15/menu2Setup.html