DHTML Lab: Hierarchical Menus Ver. 2 (Cross-Browser/Frames); The Complete Code 3/3

Hierarchical Menus Ver. 2 (Cross-Browser/Frames)
SPECIAL EDITION; the director's cut 3/3
Hierarchical Menus, Version 2: Routines (hierMenus.js)
This file, along with the external array file, may be downloaded in ZIP format.
/*hierMenus.js - Cross-Browser/Full-Window/Frames
* By Peter Belesis. v2.0 980522
* Copyright (c) 2001 Peter Belesis. All Rights Reserved.
* Originally published and documented at http://www.dhtmlab.com/
* Available solely from INT Media Group. Incorporated under exclusive license.
* Contact licensing@internet.com for more information.
*/
loader = (isFrames) ? (NS4) ? parent : parent.document.body : window;
loader.onload = startIt;
if (perCentOver != null) {
childOverlap = (perCentOver/100) * menuWidth
}
mSecsVis = secondsVisible*1000;
imgStr = "<IMG SRC=" + imgSrc + " WIDTH=" + imgSiz + " HEIGHT=" + imgSiz +" BORDER=0 VSPACE=2 ALIGN=RIGHT>"
function initVars() {
topCount = 1;
areCreated = false;
beingCreated = false;
isOverMenu = false;
currentMenu = null;
allTimer = null;
}
initVars();
function startIt() {
if (isFrames) {
menuLoc = eval("parent.frames." + mainFrName);
if (NS4) menuLoc.onunload = initVars;
if (IE4) menuLoc.document.body.onunload = initVars;
}
else {
menuLoc = window;
}
if (NS4) setTimeout("loader.onresize=reDo",100);
makeTop();
}
function makeTop(){
beingCreated = true;
while(eval("window.arMenu" + topCount)) {
makeMenu(false,topCount);
topCount++
}
if (IE4) {
divColl = menuLoc.document.all.tags("DIV");
for (i=0; i<divColl.length; i++) {
if (divColl[i].id.indexOf("elMenu")!=-1) {
divColl[i].fullHeight = divColl[i].lastItem.style.pixelTop + divColl[i].lastItem.scrollHeight + (borWid*2);
divColl[i].style.height = divColl[i].fullHeight;
}
}
}
status = (topCount-1) + " Hierarchical Menu Trees Created"
areCreated = true;
beingCreated = false;
}
function makeMenu(isChild,menuCount,parMenu,parItem) {
menu = makeElement("elMenu" + menuCount);
menu.array = eval("arMenu" + menuCount);
menu.maxItems = menu.array.length / 3;
menu.setup = menuSetup;
menu.itemCount = 0;
while (menu.itemCount < menu.maxItems) {
menu.itemCount++;
status = "Creating Hierarchical Menus: " + menuCount + " / " + menu.itemCount;
prevItem = (menu.itemCount > 1) ? menu.item : null;
itemName = "item" + menuCount + "_" + menu.itemCount;
menu.item = makeElement(itemName,menu);
menu.item.prevItem = prevItem;
menu.item.setup = itemSetup;
menu.item.setup(menu.itemCount,menu.array);
if (menu.item.hasMore) {
makeMenu(true,menuCount + "_" + menu.itemCount,menu,menu.item);
menu = menu.parentMenu;
}
}
menu.lastItem = menu.item;
if (!isChild) parName = parItem = null;
menu.setup(isChild,parMenu,parItem);
}
function makeElement(whichEl,whichContainer) {
if (arguments.length==1) {
whichContainer = (NS4) ? menuLoc : menuLoc.document.body;
if (NS4) elWidth = menuWidth;
}
else {
if (NS4) elWidth = menuWidth-(borWid*2)-(itemPad*2);
}
if (NS4) {
eval(whichEl + "= new Layer(elWidth,whichContainer)");
}
else {
elStr = "<DIV ID=" + whichEl + " STYLE='position:absolute'></DIV>";
whichContainer.insertAdjacentHTML("BeforeEnd",elStr);
if (isFrames) eval(whichEl + "= menuLoc." + whichEl);
}
return eval(whichEl);
}
function itemSetup(whichItem,whichArray) {
this.onmouseover = itemOver;
this.onmouseout = itemOut;
arrayPointer = (whichItem-1)*3;
this.dispText = whichArray[arrayPointer];
this.linkText = whichArray[arrayPointer + 1];
this.hasMore = whichArray[arrayPointer + 2];
if (this.linkText.length > 0) {
if (NS4) {
this.captureEvents(Event.MOUSEUP)
this.onmouseup = linkIt;
}
else {
this.onclick = linkIt;
this.style.cursor = "hand";
}
}
htmStr = (this.hasMore) ? imgStr + this.dispText : this.dispText;
if (NS4) {
if (fntBold) htmStr = htmStr.bold();
if (fntItal) htmStr = htmStr.italics();
htmStr = htmStr.fontcolor(fntCol);
htmStr = "<FONT FACE=" + fntFam + " POINT-SIZE=" + fntSiz + ">" + htmStr+ "</FONT>";
this.document.write(htmStr);
this.document.close();
this.bgColor = backCol;
this.visibility = "inherit";
this.container = this.parentLayer;
if (whichItem == 1) {
this.top = borWid + itemPad;
}
else {
this.top = this.prevItem.top + this.prevItem.clip.height + separator;
}
this.left = borWid + itemPad;
this.clip.top = this.clip.left = -itemPad;
this.clip.bottom += itemPad;
this.clip.right = menuWidth-(borWid*2)-itemPad;
}
else {
with (this.style) {
padding = itemPad;
color = fntCol;
fontSize = fntSiz + "pt";
fontWeight = (fntBold) ? "bold" : "normal";
fontStyle = (fntItal) ? "italic" : "normal";
fontFamily = fntFam;
borderBottomWidth = separator + "px";
borderBottomColor = separatorCol;
borderBottomStyle = "solid";
backgroundColor = backCol;
}
this.innerHTML = htmStr;
this.container = this.offsetParent;
if (whichItem == 1) {
this.style.pixelTop = 0;
}
else {
this.style.pixelTop = this.prevItem.style.pixelTop + this.prevItem.offsetHeight;
}
this.style.pixelLeft = 0;
}
}
function menuSetup(hasParent,openCont,openItem) {
this.onmouseover = menuOver;
this.onmouseout = menuOut;
this.showIt = showIt;
this.keepInWindow = keepInWindow;
this.hideTree = hideTree
this.hideParents = hideParents;
this.hideChildren = hideChildren;
this.hideTop = hideTop;
this.hasChildVisible = false;
this.isOn = false;
this.hideTimer = null;
if (hasParent) {
this.hasParent = true;
this.parentMenu = openCont;
this.parentItem = openItem;
this.parentItem.child = this;
}
else {
this.hasParent = false;
this.hideSelf = hideSelf;
}
if (NS4) {
this.bgColor = borCol;
this.fullHeight = this.lastItem.top + this.lastItem.clip.bottom + borWid;
this.clip.right = menuWidth;
this.clip.bottom = this.fullHeight;
}
else {
with (this.style) {
width = menuWidth;
borderWidth = borWid;
borderColor = borCol;
borderStyle = borSty;
}
this.lastItem.style.border="";
this.showIt(false);
this.onselectstart = cancelSelect;
this.moveTo = moveTo;
this.moveTo(0,0);
}
}
function popUp(menuName,e){
if (beingCreated) return;
if (!beingCreated && !areCreated) startIt();
hideAll();
currentMenu = eval(menuName);
if (!isFrames) {
xPos = (NS4) ? e.pageX : event.x;
yPos = (NS4) ? e.pageY : event.y;
}
else {
if (IE4) menuLocBod = menuLoc.document.body;
switch (navFrLoc) {
case "left":
xPos = (NS4) ? menuLoc.pageXOffset : menuLocBod.scrollLeft;
yPos = (NS4) ? (e.pageY-pageYOffset)+menuLoc.pageYOffset : event.clientY + menuLocBod.scrollTop;
break;
case "top":
xPos = (NS4) ? (e.pageX-pageXOffset)+menuLoc.pageXOffset : event.clientX + menuLocBod.scrollLeft;
yPos = (NS4) ? menuLoc.pageYOffset : menuLocBod.scrollTop;
break;
case "bottom":
xPos = (NS4) ? (e.pageX-pageXOffset)+menuLoc.pageXOffset : event.clientX + menuLocBod.scrollLeft;
yPos = (NS4) ? menuLoc.pageYOffset+menuLoc.innerHeight : menuLocBod.scrollTop + menuLocBod.clientHeight;
break;
case "right":
xPos = (NS4) ? menuLoc.pageXOffset+menuLoc.innerWidth : menuLocBod.scrollLeft+menuLocBod.clientWidth;
yPos = (NS4) ? (e.pageY-pageYOffset)+menuLoc.pageYOffset : event.clientY + menuLocBod.scrollTop;
break;
}
}
currentMenu.moveTo(xPos,yPos);
currentMenu.keepInWindow()
currentMenu.isOn = true;
currentMenu.showIt(true);
}
function menuOver() {
this.isOn = true;
isOverMenu = true;
currentMenu = this;
if (this.hideTimer) clearTimeout(this.hideTimer);
}
function menuOut() {
if (IE4) {
theEvent = menuLoc.event;
if (theEvent.srcElement.contains(theEvent.toElement)) return;
}
this.isOn = false;
isOverMenu = false;
allTimer = setTimeout("currentMenu.hideTree()",10);
}
function itemOver(){
if (IE4) {
theEvent = menuLoc.event;
if (theEvent.srcElement.tagName == "IMG") return;
this.style.backgroundColor = overCol;
this.style.color = overFnt;
}
else {
this.bgColor = overCol;
}
if (this.container.hasChildVisible) {
this.container.hideChildren(this);
}
if (this.hasMore) {
if (NS4) {
this.childX = this.container.left + (menuWidth - childOverlap);
this.childY = this.pageY + childOffset;
}
else {
this.childX = this.container.style.pixelLeft + (menuWidth - childOverlap);
this.childY = this.style.pixelTop + this.container.style.pixelTop + childOffset;
}
this.child.moveTo(this.childX,this.childY);
this.child.keepInWindow();
this.container.hasChildVisible = true;
this.container.visibleChild = this.child;
this.child.showIt(true);
}
}
function itemOut() {
if (IE4) {
theEvent = menuLoc.event;
if (theEvent.srcElement.contains(theEvent.toElement)
|| (theEvent.fromElement.tagName=="IMG" && theEvent.toElement.contains(theEvent.fromElement)))
return;
this.style.backgroundColor = backCol;
this.style.color = fntCol;
}
else {
this.bgColor = backCol;
if (!isOverMenu) {
allTimer = setTimeout("currentMenu.hideTree()",10);
}
}
}
function moveTo(xPos,yPos) {
this.style.pixelLeft = xPos;
this.style.pixelTop = yPos;
}
function showIt(on) {
if (NS4) {this.visibility = (on) ? "show" : "hide"}
else {this.style.visibility = (on) ? "visible" : "hidden"}
}
function keepInWindow() {
scrBars = 20;
if (NS4) {
winRight = (menuLoc.pageXOffset + menuLoc.innerWidth) - scrBars;
rightPos = this.left + menuWidth;
if (rightPos > winRight) {
if (this.hasParent) {
parentLeft = this.parentMenu.left;
newLeft = ((parentLeft-menuWidth) + childOverlap);
this.left = newLeft;
}
else {
dif = rightPos - winRight;
this.left -= dif;
}
}
winBot = (menuLoc.pageYOffset + menuLoc.innerHeight) - scrBars;
botPos = this.top + this.fullHeight;
if (botPos > winBot) {
dif = botPos - winBot;
this.top -= dif;
}
}
else {
winRight = (menuLoc.document.body.scrollLeft + menuLoc.document.body.clientWidth) - scrBars;
rightPos = this.style.pixelLeft + menuWidth;
if (rightPos > winRight) {
if (this.hasParent) {
parentLeft = this.parentMenu.style.pixelLeft;
newLeft = ((parentLeft - menuWidth) + childOverlap);
this.style.pixelLeft = newLeft;
}
else {
dif = rightPos - winRight;
this.style.pixelLeft -= dif;
}
}
winBot = (menuLoc.document.body.scrollTop + menuLoc.document.body.clientHeight) - scrBars;
botPos = this.style.pixelTop + this.fullHeight;
if (botPos > winBot) {
dif = botPos - winBot;
this.style.pixelTop -= dif;
}
}
}
function linkIt() {
menuLoc.location.href = this.linkText;
}
function popDown(menuName){
if (!areCreated) return;
whichEl = eval(menuName);
whichEl.isOn = false;
whichEl.hideTop();
}
function hideAll() {
for(i=1; i<topCount; i++) {
temp = eval("elMenu" + i);
temp.isOn = false;
if (temp.hasChildVisible) temp.hideChildren();
temp.showIt(false);
}
}
function hideTree() {
allTimer = null;
if (isOverMenu) return;
if (this.hasChildVisible) {
this.hideChildren();
}
this.hideParents();
}
function hideTop() {
whichEl = this;
this.hideTimer = setTimeout("whichEl.hideSelf()",mSecsVis);
}
function hideSelf() {
this.hideTimer = null;
if (!this.isOn && !isOverMenu) {
this.showIt(false);
}
}
function hideParents() {
tempMenu = this;
while (tempMenu.hasParent) {
tempMenu.showIt(false);
tempMenu.parentMenu.isOn = false;
tempMenu = tempMenu.parentMenu;
}
tempMenu.hideTop();
}
function hideChildren(item) {
tempMenu = this.visibleChild;
while (tempMenu.hasChildVisible) {
tempMenu.visibleChild.showIt(false);
tempMenu.hasChildVisible = false;
tempMenu = tempMenu.visibleChild;
}
if (!this.isOn || !item.hasMore || this.visibleChild != this.child) {
this.visibleChild.showIt(false);
this.hasChildVisible = false;
}
}
function cancelSelect(){return false}
function reDo(){ initVars(); menuLoc.location.reload() }
Produced by Peter Belesis and
All Rights Reserved. Legal Notices.Created: May. 22, 1998
Revised: May. 22, 1998
URL: http://www.webreference.com/dhtml/column20/allCode3.html


