Site navigation below

In this section

Place your text ad here.

World class Undelete and renowned raid recovery services

Web Scripts and PHP Scripts

WestNIC provides reliable web hosting services

SGD Networks offers Web Hosting, Web Hosting Hyderabad

Ahosting.biz reseller hosting, managed dedicated server with 24/7 support

This page is part 3 of an article that demonstrates a DOM1 visibility drop down menu system. Each menu has a main link and an unordered list of links that become visible, with the illusion of extending the main menu point downwards. The drop down menus are open source, accessible and forward compatible.

The scripts and CSS for these drop down menus is provided under a Creative Commons License.

View source

The scripting, CSS and XHTML markup for this drop down menu system is described below and the source code is heavily commented for reference. Convenient links are provided to download the source code further down this page.

Drop down menu source code

For easy maintenance and modular design, all the Javascript (and CSS) for this page is referenced from external files. Unsupported browsers such as Internet Explorer 3 and Netscape 2 with Javascript on will not display these menus at all, nor any noscript element, so this menu system should not be used for essential navigation links. The external script and CSS files are as follows, see below for details:

As with all Javascript for the Web, one cannot be sure that the end-users' browser has Javascript support, so there is a noscript block with links for each of the main menu points using similar markup to the dynamic menus so that the styles may still be presented accurately even if Javascript is off.

visibility-HorizontalMenus.shtml

The markup fragment below specifies the supplementary stylesheet for this page and the initial script element that loads the menu builder script:

<link
 rel="stylesheet"
 type="text/css"
 href="/styles/javascript/dom/visibility-HorizontalMenus.css" />
<script
 type="text/javascript"
 src="/scripts/dom/css/visibility-HorizontalMenuBuilder.js">
</script>
      

The fragment below shows the script element that loads the menu writer script and inserts the dynamic menus immediately after the open body tag. There is also a simplified noscript alternative with equivalent id attributes:

<script
  type="text/javascript"
  src="/scripts/dom/css/visibility-HorizontalMenuWriter.js">
</script>
<noscript>
<div id="NavBar">
  <!-- LinkBar points should match LinkBar points in
  /scripts/dom/css/visibility-HorizontalMenuBuilder.js -->
  <div id="LinkBar">
    <div id="Link1"><a href="/">Home page</a></div>
    <div id="Link2"><a href="#">Javascript</a></div>
    <div id="Link3"><a href="#">DOM</a></div>
    <div id="Link4"><a href="#">CSS</a></div>
    <div id="Link5"><a href="#">What's New</a></div>
  </div>
</div>
</noscript>
      

visibility-HorizontalMenuBuilder.js

This menu builder script defines the drop-down menu contents and event handler functions for the menus. If the DOM1 getElementById() method is supported, the string variable menutxt is used to build the menu headings and bullet lists. If this basic DOM1 feature is not supported, a simplified group of menu headings is compiled equivalent to the noscript markup.

if(document.getElementById){
  // DOM1 statements
}
      

This script also checks if DOM1 object references and properties are available before use, in particular the elements' .style object and .style.visibility property, see the menuOver() example below.

All core Javascript features are assumed to be available if this external script file is loaded and are not explicitly checked. The script is not listed here because of long lines but is heavily commented for reference, see visibility-HorizontalMenuBuilder.js.

menuOver()

The menuOver() function is called directly when the cursor triggers the onmouseover event on one of the five menu headings. This function checks if any other menus are "open" and, if so, closes them immediately. It then opens, or makes visible, the relevant menu by reference to its visibility property via the global variable LiveMenu.

This function includes a minor workaround to check that the LiveMenu.style.visibility property is not null, as this value initially appears to be the empty string in Internet Explorer 5.0 (in IE4.0 compatibility mode at least) and does not return true.

// This is the new 'live' menu, make it visible
LiveMenu = document.getElementById(MenuID);
// LiveMenu.style.visibility is
// initially empty in IE5 until
// it is assigned by these
// functions, so must check that
// it's not null before proceeding...
if((LiveMenu.style)&&(LiveMenu.style.visibility!=null)){
  LiveMenu.style.visibility = 'visible';
}
      

After this statement sets the visibility property, IE5 returns true to the simpler conditions in the other event handler functions, which simply check for the existence of the .style.visibility property.

stayOpen()

Even when the extended menus' visibility property is hidden, Opera 4.0 registers onmouseover events on the drop-down bullet lists because it does not support the CSS z-index property. The stayOpen() function is a workaround to suppress this behaviour, which simply checks to see if the menu is logically "open" and forwards a call to menuOver() if it is. If the menu is supposed to be closed, the function returns immediately.

function stayOpen(MenuID){
  // If menuOver has not been called
  // or the menu is hidden, do nothing
  if((LiveMenu==null)||
     ((LiveMenu.style)&&
      (LiveMenu.style.visibility)&&
      (LiveMenu.style.visibility=='hidden')))return;
  else menuOver(MenuID);
}
      

menuOut()

The menuOut() function is triggered by onmouseout events in the exposed bullet list anchors. The function initialises a setTimeout() control that holds a given menu open for 250 milliseconds so the user can move the cursor down the list before it closes. If stayOpen() calls are triggered by the onmouseover event handlers in these lists, the menus stay open. If not, the hideNow() function is called when the timeout expires.

hideNow()

As its name implies, this function immediately "closes", or makes hidden, whichever menu is specified by the global LiveMenu variable:

if((LiveMenu.style)&&(LiveMenu.style.visibility)){
  LiveMenu.style.visibility = 'hidden';
}
      

visibility-HorizontalMenuWriter.js

This menu writer script simply writes the XHTML markup for the menus defined in the menu builder script into the flow of the document. If the global string variable menutxt has not been defined for whatever reason, the menus will not be output. The listing for visibility-HorizontalMenuWriter.js is given below:

// If menutxt is defined and not
// empty, write it to the document
///////////////////////////////////////
if((menutxt)&&(menutxt!='')){
  document.write(menutxt);
}
      

Here again, the core Javascript method document.write() is assumed to be available if this external script file has loaded.

visibility-HorizontalMenus.css

This stylesheet, visibility-HorizontalMenus.css, supplements the standard site-wide Code Style CSS to declare styles specifically for these drop-down menus. It uses an @import rule to hide the main styles from Netscape 4 and Internet Explorer 3, but some simple styles are included to improve appearances where supported.

/*
  Created:  2000-10-21
  Issued:   2001-01-11
  Modified: 2005-02-23

  Copyright (c) 2001-2006 by Philip Shaw, phil@codestyle.org

  This work is licensed under the Creative Commons
  Attribution-NonCommercial-ShareAlike License.
  To view a copy of this license, visit
  http://creativecommons.org/licenses/by-nc-sa/2.0/
  or send a letter to Creative Commons, 559 Nathan
  Abbott Way, Stanford, California 94305, USA.
*/

@import url(visibility-HorizontalMenusImport.css);
/*
  Basic styles for NN4.
*/
#Link1, #Link2, #Link3, #Link4, #Link5{
  float:            left;
  width:            17.9%;
}
#Header{
  clear:            left;
}
      

The series of grouped #Link1 declarations refer to the main link heading div elements, which float horizontally across the top of the page. These are sized using percentage lengths to ensure that these menu panels will scale proportionally to fit most screen resolutions. These are styled in more detail by margin, padding and border declarations in the @import stylesheet.

visibility-HorizontalMenusImport.css

The @import stylesheet, visibility-HorizontalMenusImport.css, declares the detailed presentation of the menus for supporting browsers. Non-supporting browsers will display a simpler page format. In many cases the declarations have been grouped to ensure that display properties and positioning of the menu and bullet list containers, #LinkBar and #MenuBar, are almost identical. The vital exceptions are the z-index and vertical positioning given by the top property, which makes them overlap very slightly on the bottom edge of the menu heading divs.

/*
  Created:   2000-11-12
  Issued     2001-01-11
  Modified:  2008-02-23

  Copyright (c) 2001-2008 by Philip Shaw, phil@codestyle.org

  This work is licensed under the Creative Commons
  Attribution-NonCommercial-ShareAlike License.
  To view a copy of this license, visit
  http://creativecommons.org/licenses/by-nc-sa/2.0/
  or send a letter to Creative Commons, 559 Nathan
  Abbott Way, Stanford, California 94305, USA.
*/

/*
  Move the Code Style logo down
  beneath the menus:
  background-position: [horiz.] [vert.]
*/
div#Header {
  color:            #000;
  background:       url(/images/logo-EurostileLozenge.png)
                    #FFF
                    3% 2.7em
                    no-repeat;
  height:           7em;
}
#MenuBar, #LinkBar {
  float:            none;
  width:            98%;
  position:         absolute;
  left:             1.5%;
  border:           none;
}
/*
  z-index necessary to make links
  visible in Netscape 6
*/
#MenuBar {
  top:              1.5em;
  z-index:          4;
}
#LinkBar {
  top:              0.1em;
  z-index:          3;
}
/*
  Main menu and link styles identical.
*/
#Menu1, #Menu2, #Menu3, #Menu4, #Menu5,
#Link1, #Link2, #Link3, #Link4, #Link5 {
  float:            left;
  width:            17.9%;
  border-style:     solid;
  border-color:     #eee #dfdfdf #666 #ccc;
  margin:           0.6% 0.2%;
  padding-left:     1%;
  color:            #039;
  background:       #eee;
  font-family:      "times new roman",
                    serif;
  font-weight:      normal;
  font-size:        larger;
}
/*
  Differences in menu and link styles.
*/
#Menu1, #Menu2, #Menu3, #Menu4, #Menu5 {
  border-width:     0px 2px 1px 2px;
  visibility:       hidden;
}
#Link1, #Link2, #Link3, #Link4, #Link5 {
  border-width:     2px 2px 1px 2px;
  visibility:       visible;
  height:           1.3em;
}
/*
  Must override float on the menu divs.
*/
#Menu1 UL, #Menu2 UL, #Menu3 UL,
#Menu4 UL, #Menu5 UL  {
  float:            none;
  margin:           0em 0em 0em 1em;
  padding:          0.2em 0em 0.5em 0em;
  font-family:      "times new roman",
                    serif;
}
/*
  Make the whole width of the links
  active -- height necessary for IE 5.5
*/
#LinkBar a, #MenuBar a {
  display:          block;
  height:           1.3em;
}
#Menu1 a:visited, #Menu2 a:visited,
#Menu3 a:visited, #Menu4 a:visited,
#Menu5 a:visited, #Link1 a:visited,
#Link2 a:visited, #Link3 a:visited,
#Link4 a:visited, #Link5 a:visited {
  color:            #039;
  background:       #EEE;
}
#Menu1 a:link, #Menu2 a:link,
#Menu3 a:link, #Menu4 a:link,
#Menu5 a:link, #Link1 a:link,
#Link2 a:link, #Link3 a:link,
#Link4 a:link, #Link5 a:link {
  color:            #039;
  background:       #EEE;
}
#Menu1 a:hover, #Menu2 a:hover,
#Menu3 a:hover, #Menu4 a:hover,
#Menu5 a:hover, #Link1 a:hover,
#Link2 a:hover, #Link3 a:hover,
#Link4 a:hover, #Link5 a:hover {
  color:            #C00;
  background:       #EEE;
}
/*
  Substitute padding for omitted
  Code Style URI.
*/
.Title {
  padding-top:      1em;
}
/*
  Push #Header down to make room for
  menus, margin-top doesn't have the
  same effect with IE5.5 and Mozilla,
  so the logo image must be moved set
  to 100% (bottom) too.
*/
#Header {
  padding-top:      2em;
}
      

The numbered series of ten paired #Link1 and #Menu1 declarations for the five menus are handled in a similar way by grouped selectors. The vital differences between these selectors, visibility, border-top and height are declared beneath and complete the illusion of the extensible drop-down panel.

The final declarations for .Title and #Header simply move these standard page components down further than normal to accommodate the height of the menus.

Style note

The specificity of the A:hover property in the drop-down menus is evidently being calculated differently in Netscape 6, compared with Opera 5 and Internet Explorer 5. Netscape 6.0 and 6.1 do not show the hover style, but this bug is fixed in Mozilla build 2001092003 and later.

Drop down menu review

This is the final part of this article, follow these links to return to previous pages.

DOM drop down menu customisation FAQ

Article feedback

Your comments on this article will be appreciated, please use the form below to submit your views. If you would like a reply or article update notification, include your email address.

Information: Your email address will not be mis-used. If you include your address you may be sent a personal reply, you will not be added to any mailing list unless you request update notification. Read the site privacy statement for details.

Style warning - please read

Home · CSS · Java · Javascript · HTML · Help · Log