Web DevCenter
oreilly.comSafari Books Online.Conferences.
MySQL Conference and Expo April 14-17, 2008, Santa Clara, CA

Sponsored Developer Resources

Web Columns
Adobe GoLive
Essential JavaScript
Megnut

Web Topics
All Articles
Browsers
ColdFusion
CSS
Database
Flash
Graphics
HTML/XHTML/DHTML
Scripting Languages
Tools
Weblogs

Atom 1.0 Feed RSS 1.0 Feed RSS 2.0 Feed

Learning Lab






Hierarchical Menus with the Underrated style.display Object
Pages: 1, 2

Enough, show me the code!

This script requires just a couple of complementary functions: hideLevel() and showLevel(). Each of them takes the id of the menu "level" they're acting on, like "projectlinks" and "chapters," and uses it to flip that level's display setting.



function hideLevel( _levelId) {
	var thisLevel = document.getElementById( _levelId );
	thisLevel.style.display = "none";
	}

function showLevel( _levelId) {
	var thisLevel = document.getElementById( _levelId );
	if ( thisLevel.style.display == "none") {
		thisLevel.style.display = "block";
		}
	else {
		hideLevel( _levelId);
		}
	}

In order to reduce clutter, I decided to make showLevel() take care of both circumstances, hiding and showing the level, by including an if statement that checks whether the level is already displayed or not. This way, we can make the links always call showLevel(), but have the script know which of the two functions is appropriate and run the right one. If the list of chapters below "Designing with JavaScript" is already visible, for example, clicking on that link will hide the chapters instead of revealing them.

Designing with JavaScript

Related Reading

Designing with JavaScript
Creating Dynamic Web Pages
By Nick Heinle, Bill Pena

To be honest, the script is slightly more complicated than this. As you may have noticed in the screenshots above, I've also included plus- and minus-sign images beside the links, indicating the state of that level. This visual aid completes the hierarchical menu metaphor, basically mimicking the "Folders View" in Windows Explorer. It's also trivial to add, and if you've ever made an image rollover, you already know how.

First we create a couple of image objects and load our images into the script:

var plusImg = new Image();
	plusImg.src = "./images/plus.png"
var minusImg = new Image();
	minusImg.src = "./images/minus.png"

Then, we just modify our previous hideLevel() and showLevel() functions a little to make them switch the plus or minus image beside the clicked link:

function hideLevel( _levelId, _imgId ) {
	var thisLevel = document.getElementById( _levelId );
	var thisImg = document.getElementById( _imgId );
	thisLevel.style.display = "none";
	thisImg.src = plusImg.src;
	}

function showLevel( _levelId, _imgId ) {
	var thisLevel = document.getElementById( _levelId );
	var thisImg = document.getElementById( _imgId );
	if ( thisLevel.style.display == "none") {
		thisLevel.style.display = "block";
		thisImg.src = minusImg.src;
		}
	else {
		hideLevel( _levelId, _imgId);
		}
	}

Whereas before we passed the function just one id, the level being manipulated, we now need to pass it the id of the image next to the link. So our links now look something like this:

<a href="javascript:showLevel( 'projectlinks', 'projImg');">Projects</a>

Last but not least, we want the menu to be completely collapsed when the page loads. We don't want to open with all links displayed, because that would defeat the point of making a menu. So we want to create one more function, hideAll(), that gets called once when the page loads and hides all of the links at once. All we have to do is create a function that calls hideLevel() multiple times, once for each level of the menu.

function hideAll() {
	hideLevel("chapters", "chapImg");
	hideLevel("projectlinks", "projImg");
	hideLevel("interestlinks", "intsImg");
	}

Then add a call to hideAll() when the page loads, like so:

<body onLoad="javascript:hideAll();">

It's as simple as that.

Now that you've seen a breakdown of how this script works, take a look at the complete product, and feel free to adapt it for your own needs. Remember to use browser detection! Once you've explored using the style.display object, write and tell me about your experiences, and let me know if you've found it useful.

<script language="JavaScript">
<!--

var plusImg = new Image();
	plusImg.src = "./images/plus.png"
var minusImg = new Image();
	minusImg.src = "./images/minus.png"

function hideLevel( _levelId, _imgId ) {
	var thisLevel = document.getElementById( _levelId );
	var thisImg = document.getElementById( _imgId );
	thisLevel.style.display = "none";
	thisImg.src = plusImg.src;
	}
	
function hideAll() {
	hideLevel("chapters", "chapImg");
	hideLevel("projectlinks", "projImg");
	hideLevel("interestlinks", "intsImg");
	}
	
function showLevel( _levelId, _imgId ) {
	var thisLevel = document.getElementById( _levelId );
	var thisImg = document.getElementById( _imgId );
	if ( thisLevel.style.display == "none") {
		thisLevel.style.display = "block";
		thisImg.src = minusImg.src;
		}
	else {
		hideLevel( _levelId, _imgId);
		}
	}
// -->
</script>

Bill Pena is a freelance Web/information designer and writer. He was also the designer for Safari: Tech Books Online, O'Reilly's online books service.


O'Reilly & Associates recently released (November 2001) Designing with JavaScript, 2nd Edition.

Return to the JavaScript and CSS DevCenter.