Menu Systems for Website Navigation

5.  Adding inter-activity to the menu system

A "fully blown" menu system indicates the currently active page by turning the appropriate button "on".  In this section, we will add the "on" state for the buttons and inter-activity between the buttons to create a menu system that behaves like mechanically interlocked switches.


Adding a button "on" state

We can add a fourth state for a link by creating a new className for the "on" state.

The function ButtonClick(), changes the link to "on".  The link will remain in this state after it has been clicked, before the new page starts to load.


Turning a button "on" for the current page

The link corresponding to the current page is turned "on" by calling the function ButtonSet() when the page first loads.  This is done by creating on onload event handler for the document.  As usual, we first check for the existence of this function, since it resides in an external JavaScript file.


<body onload="window.ButtonSet ? ButtonSet() : null">

The for loop in the function ButtonSet() compares each link's href attribute with the actual document URL to determine the correct button to turn "on".

Note that we use the browser's links array to check every link on the page.  The advantage of this approach is that no special id's are required for the buttons, reducing website maintenance when changing menu structures.  If you prefer, you could use the document.getElementsByTagName("A") method instead of document.links, but you would also need to isolate this from older browsers, which would produce errors if exposed to this code.

Turning other buttons "off" when a button is clicked

When a link is turned "on" by the function ButtonSet(), it sets a global object reference to that link - ButtonCurrent.  When a new link is first clicked, the function ButtonDep() checks if this global object reference exists and then uses this to turn the previous link "off" before changing the appearance of the new link to "depressed".  This makes the menu buttons appear to interact with each other. 


Preventing mouseovers from interfering with a button that is already "on"

We want to prevent an onmouseover or onmouseout event from having any effect on a link which is already "on".  In the previous example, we only allowed the ButtonSel() function to highlight the button when it was in the "off" state to get around the IE problem.  That just happens to suit our purposes here!  In addition, we add a condition to the ButtonOut() function to only turn the link "off" if it is "highlighted".


Menu logic functions


function ButtonSel(Button) {                      // called by onmouseover event

  // Highlight button
  if (!Button.className) {
    Button.className = "Sel";
  }
}

function ButtonOut(Button) {                       // called by onmouseout event

  // Return button to normal
  if (Button.className && Button.className == "Sel") {
    Button.className = "";
  }
}

function ButtonDep(Button) {                      // called by onmousedown event

  // Turn previous button off
  if (window.ButtonCurrent) {
    ButtonCurrent.className = "";
  }

  // Depress current button
  Button.className = "Dep";
}

function ButtonClick(Button) {                        // called by onclick event

  // Turn button on
  Button.className = "Act";

  // Set page address
  PageAddr = Button.href;         // This variable must survive outside function

  // Delay page loading to allow button to return to correct state
  setTimeout("window.location = PageAddr", 250);

  // Disable normal link operation
  return false;
}

function ButtonSet() {                            // called by page onload event
  if (document.links) {

    // Turn on correct menu button
    for (var i = 0; i < document.links.length; i++) {
      var ThisLink = document.links[i];
      if (escape(ThisLink.href).indexOf(escape(document.location.href)) != -1) {
        ThisLink.className = "Act";
        ButtonCurrent = ThisLink;
      }
    }
  }
}


Style Sheet

Using the same style sheet as the previous example, we add rules for the "on" state:


.Menu a.Act {
  color: #FFCC00;
}

The following example demonstrates a fully working inter-active 4-state menu system for single page designs.  The target pages share the same external JavaScript and CSS files.  The HTML menu definition is the same as the previous example and is identical on each page.  None of the links below are "on", since none of them correspond to the current page.