JavaScript Click Menu

Jan0308Jan 03, 08

As the result of a recent email conversation, I decided to create a simple menu system using JavaScript.

After completing the original script, it became apparent that it could be modified so that users could experience familiar "click" navigation. It is quite common to use nested lists to create the "menu" effect, but when the user wishes to expand a portion of a hidden list, speed should be the primary concern. Hence, A good solution is to use a script to augment your menu system, for which I propose the following:
window.oldMenuOnLoad = window.onload ? window.onload : function(){}; window.onload = function() { var lis = document.getElementsByTagName("li"); for(var c in lis) { if(lis[c] && lis[c].className && lis[c].className.indexOf("submenu") > -1 && lis[c].getElementsByTagName('ul').length==1) { lis[c].childNodes[0].onmousedown = function(e) { this.blur(); return false; }; lis[c].childNodes[0].onmouseup = function(e) { if(!e) e=window.event; var submenu = this.parentNode.getElementsByTagName('ul')[0]; if( (e.button && e.button!=2) || (e.which && e.which!=2) ) { this.blur(); if(window.menu_currentOpenSubmenu && window.menu_currentOpenSubmenu != submenu) window.menu_document_onmouseup(); else if(window.menu_currentOpenSubmenu) return false; submenu.onmouseout = function() { window.menu_currentMouseOutTimer = setTimeout("window.menu_document_onmouseup();", 3000); }; submenu.onmousemove = function() { if(window.menu_currentMouseOutTimer) clearTimeout(window.menu_currentMouseOutTimer); }; = "hidden"; submenu.className = submenu.className.indexOf(' open')==-1 ? (submenu.className + ' open') : submenu.className.substring(0,submenu.className.indexOf(' open')); window.menu_currentOpenSubmenu = submenu; for(var i=0; i<10; i++) setTimeout("if(window.menu_currentOpenSubmenu) = '"+(submenu.offsetHeight/(10-i) - submenu.offsetHeight)+"px';", i*20); setTimeout("if(window.menu_currentOpenSubmenu) = 'visible';", 10); window.menu_onMouseDownOld = document.onmouseup ? document.onmouseup : function(e){}; setTimeout("document.onmouseup = window.menu_document_onmouseup;", 1); window.menu_document_onmouseup = function() { if(window.menu_currentOpenSubmenu) { if(window.menu_currentOpenSubmenu.className) window.menu_currentOpenSubmenu.className = window.menu_currentOpenSubmenu.className.substring(0, window.menu_currentOpenSubmenu.className.indexOf(' open')); window.menu_currentOpenSubmenu = null; } document.onmouseup = window.menu_onMouseDownOld; }; } if(e.returnValue) e.returnValue = false; if(e.preventDefault) e.preventDefault(); return false; } } } window.oldMenuOnLoad(); };

<ul class="navmenu"> <li><a href="#">Link 1</a></li> <li><a href="#">Link 2</a></li> <li class="submenu"><a href="javascript:void(0);">Sub Menu 1</a> <ul> <li class="first"><a href="#">Sub Menu 1, Item 1</a></li> <li><a href="#">Sub Menu 1, Item 2</a></li> <li><a href="#">Sub Menu 1, Item 3</a></li> <li><a href="#">Sub Menu 1, Item 4</a></li> </ul> </li> <li><a href="#">Link3</a></li> <li class="submenu"><a href="javascript:void(0);">Sub Menu 2</a> <ul> <li class="first"><a href="#">Sub Menu 2, Item 1</a></li> <li><a href="#">Sub Menu 2, Item 2</a></li> </ul> </li> <li><a href="#">Link4</a></li> </ul>
The first block of code creates the JavaScript building blocks that are required to transform this simple bulleted list into a convenient navigational menu. The second block of code is the actual bulleted list - the foundation and structure of the menu are defined by adding and removing <li> and <ul> elements as necessary. We put it together in a simple document structure, with the bulleted list inside the body of the document and the JavaScript inside the header. The result is a really nice menu. The CSS used in that example is lengthy, so you can simply view the source of the example to access that portion of the code.

About Jason Miller:

I am a JavaScript developer from Waterloo, Ontario, Canada. When I am not typing green code onto a black screen, you might find me at the nearest coffee pub checking out the brew. I run a internet firm called developIT and maintain blogs and web apps when I can.
Author's Note: this code is not well-written, overwrites mouse events and uses eval() implicitly via String parameters passed to setTimeout. There are numerous alternate solutions available, however, the general concept implemented here could still be of value. Therefore, I cannot recommended this for "copy & paste" use in its present state.
Leave a Comment

Post Comment