Back to the Web Developer's Journal Main Page
internet.com
side nav bar

Javascript Articles:

HOW DID THEY DO THAT???

Find out in:
Amazing HTML



Site Map

Jobs at webdeveloper.com


Check out our Web-based
Discussion Groups:

Check out and join our email-based Mailing Lists for Web developers.


Developer Channel
FlashKit
Jobs.webdeveloper
JavaScript.com
JavaScriptSource
JustSMIL
ScriptSearch
Streaming Media World
WebDeveloper.com
WebReference
XMLFiles
WDVL
Discussion Groups Book Reviews Software Reviews Download Web Tools

Cascading Menu Script as HTML

Return to Cascading Menu Script Explained
Part 1
Part 2

/******************************************************
* HMenu.js - v. 1.05 000710
* Cascading menu creation system
* by Aaron Prenot
* Copyright (c) 2000 Aaron Prenot
* http://www.redrival.com/aprenot
*
* Published and Documented at
* o www.redrival.com/aprenot
* o www.webdevelopersjournal.com
*
* You may use this code on a public web site only if
* this entire copyright notice appears unchanged.
*
* Please send questions and bug reports to:
* aprenot@hotmail.com
******************************************************/

var menus = new Array();
var activeItem = null;
var IE4 = ((navigator.appName == "Microsoft Internet Explorer") && (parseInt(navigator.appVersion) >= 4 ) && !(navigator.appVersion.indexOf("5") > -1 ));

function Menu(){
this.id = "";
this.subMenus = new Array();
this.items = new Array();
this.hasChildren = false;
this.isChild = false;
this.parentMenu = null;
this.parentItem = null;
}

function Item(){
this.id = "";
this.hasMenu = false;
this.menu = null;
this.parentMenu = null;
}

function initMenu(){
// test for IE4+, it won't work otherwise
if(!document.all) return false;

findMenus();
menuContainer.activeMenu = null;
menuContainer.closeAll = closeAll;
attachMenus();
}

function findMenus(){
var cTag = menuContainer.children;
for(var i=0; i < cTag.length; i++){
tcTag = cTag[i];
if(tcTag.className == "menu"){
var tMenu = findSubMenus(tcTag);
menus[menus.length] = tMenu;
}
}
var tHTML = "<div id=\"menuContainer\">";
for(var i=0; i < menus.length; i++){
var tcTag = menus[i]
tHTML += moveHTML(tcTag);
}
tHTML += "</div>";
menuContainer.outerHTML = "";
document.body.innerHTML += tHTML;
for(var i=0; i < menus.length; i++){
var tcTag = menus[i];
setupMenu(tcTag);
}
}

function findSubMenus(menu){
var cMenu = menu.children;
var tMenu = new Menu();
tMenu.id = menu.id;
for(var i=0; i < cMenu.length; i++){
var tcMenu = new Item();
tcMenu.id = cMenu[i].id;
if(tcMenu.id.indexOf("subMenu") != -1){
++i;
var subMenu = cMenu[i];
tMenu.subMenus[tMenu.subMenus.length] = findSubMenus(subMenu)
tMenu.subMenus[(tMenu.subMenus.length - 1)].isChild = true;
tMenu.subMenus[(tMenu.subMenus.length - 1)].parentMenu = tMenu;
tMenu.subMenus[(tMenu.subMenus.length - 1)].parentItem = tcMenu;
tMenu.hasChildren = true;
tcMenu.hasMenu = true;
tcMenu.menu = tMenu.subMenus[(tMenu.subMenus.length - 1)];
}
tcMenu.parentMenu = tMenu;
tMenu.items[tMenu.items.length] = tcMenu;
}
return tMenu;
}

function moveHTML(menu){
var tHTML = "";
if(menu.hasChildren == true){
for(var i=0; i < menu.subMenus.length; i++){
tHTML += moveHTML(menu.subMenus[i]);
}
}
var tMenu = eval(menu.id);
var tMenuHTML = tMenu.outerHTML;

tMenu.outerHTML = "";
tHTML += tMenuHTML;
return tHTML;
}


function setupMenu(menu){
if(menu.hasChildren == true){
for(var i=0; i < menu.subMenus.length; i++){
setupMenu(menu.subMenus[i]);
}
}

tMenu = eval(menu.id);
tMenu.noWrap = true;
tMenu.hasChildren = menu.hasChildren;
tMenu.hasVisibleChild = false;
tMenu.visibleChild = null;
tMenu.isChild = menu.isChild;
tMenu.onselectstart = returnFalse;
tMenu.onclick = handleMenuClick;
tMenu.currWidth = 0;
tMenu.items = menu.items;

for(var i=0; i < menu.items.length; i++){
setupItem(menu.items[i]);
}
tMenu.style.pixelWidth += 5;

for(var i=0; i < menu.items.length; i++){
var tItem = eval(menu.items[i].id);
if(!IE4){
tItem.style.width = "100%";
if(tItem.hasMenu == true) {
tItem.more.style.position = "absolute";
tItem.more.style.pixelLeft = (tMenu.style.pixelWidth - 17);
}
}
}
if(menu.isChild == true){
tMenu.parentMenu = eval(menu.parentMenu.id);
tMenu.parentItem = eval(menu.parentItem.id);
}
}

function setupItem(item){
tItem = eval(item.id);
tItem.highlight = highlight;
tItem.onmouseover = tItem.highlight;
tItem.parentMenu = eval(item.parentMenu.id);
tItem.hasMenu = false;
tItem.menu = null;
tItem.onclick = handleItemClick;
tItem.ondragstart = returnFalse;
tItem.noWrap = true;

if(item.hasMenu == true){
tItem.innerHTML += "<span id=\"" + item.id + "_more\" class=\"more\">4</span>";
tItem.more = eval(item.id + "_more");
tItem.menu = eval(item.menu.id);
tItem.hasMenu = true;
}
if(!IE4) {
tItem.parentMenu.style.pixelWidth = Math.max(tItem.parentMenu.currWidth, tItem.offsetWidth);
}


}

function highlight(){
if(activeItem != null){
if(activeItem != this){
unhighlight(activeItem);
} else {
return;
}
}

event.cancelBubble = true;

this.className = "menuItemOver";
activeItem = this;

// dont open a menu thats already open
if((this.hasMenu == true) && (this.parentMenu.hasVisibleChild == true) && (this.parentMenu.visibleChild == this.menu)) return;

// if there is a menu open, close it
if(this.parentMenu.hasChildVisible == true){
hideMenu(this.parentMenu.visibleChild);
}

// if this item has a menu, show it
if(this.hasMenu){
showMenu(this.menu);
}
}

function unhighlight(menu){
event.cancelBubble = true;
menu.className = "menuItem";
}

function showMenu(menu, x, y){
event.cancelBubble = true;
if(menu){
if(IE4){
for(var i=0; i < menu.items.length; i++){
tItem = eval(menu.items[i].id);
if(tItem.hasMenu == true) {
tItem.more.style.pixelLeft = (menu.offsetWidth - tItem.more.offsetLeft - 17);
}
}
}
if(menu.isChild == true){
menu.style.pixelTop = menu.parentItem.offsetTop + menu.parentMenu.offsetTop + 4;
menu.style.pixelLeft = menu.parentMenu.offsetLeft + menu.parentMenu.offsetWidth - 4;
menu.parentMenu.hasChildVisible = true;
menu.parentMenu.visibleChild = menu;
menu.style.zIndex = menu.parentMenu.style.zIndex + 1;
} else if(x && y){
menu.style.pixelTop = y;
menu.style.pixelLeft = x;
menuContainer.activeMenu = menu;
document.onclick = menuContainer.closeAll;
}
} else {
menu = eval(this.menu);
if(IE4){
for(var i=0; i < menu.items.length; i++){
tItem = eval(menu.items[i].id);
if(tItem.hasMenu == true) {
tItem.more.style.pixelLeft = (menu.offsetWidth - tItem.more.offsetLeft - 17);
}
}
}
menu.style.pixelTop = event.clientY;
menu.style.pixelLeft = event.clientX;
menuContainer.activeMenu = menu;
document.onclick = menuContainer.closeAll;
}
menu.className = "visibleMenu";
return false;
}

function hideMenu(menu){
// to handle the careless child menu hiding down below
if(menu == null) return false;
event.cancelBubble = true;

// i do this kind of carelessly. i was having trouble otherwise
hideMenu(menu.visibleChild);

if(menu.isChild == true){
menu.parentMenu.hasChildVisible = false;
menu.parentMenu.visibleChild = null;
} else {
document.onclick = "";
menuContainer.activeMenu = null;
}
menu.className = "menu";
}

function closeAll(){
hideMenu(menuContainer.activeMenu);
}

// simple function to return false
function returnFalse(){return false;}

// function to be used for later functionality
// for now it just keeps the menu open when it receives a click;
function handleMenuClick(){
event.cancelBubble = true;
return false;

}

// just like the function above, only it closes the menu
function handleItemClick(){
event.cancelBubble = true;
menuContainer.closeAll();
}

// searches the document for elements with a menu paramater
function attachMenus(){
for(var i in document.all){
if(document.all[i].menu){
document.all[i].onclick = showMenu;
}
}
}



Return to Cascading Menu Script Explained
Part 1
Part 2


Back to the Web Developer's Journal
Contact WDJ   •    Suits!   •    Propheads!   •    Ponytails!
Discuss   •    Subscribe   •    Search


internet.com

IT | Developer | Internet News | Small Business | Personal Technology | International | Search internet.com | Advertise | Corporate Info
Newsletters | Tech Jobs | E-mail Offers

internet.commerce
Be a Commerce Partner                                
  


The Network for Technology Professionals

Search:

About Internet.com

Legal Notices, Licensing, Permissions, Privacy Policy.
Advertise | Newsletters | E-mail Offers