menu bar navigator
hey all,
I would like to have a pull down menu bar in java script that works both on IEx and on netscape. what i hope it can do is be a menu similar to the menu bar in windows, ie: click on a catagory and a few options pop down, and then that can be used to navigate the visitor around the site.
here is a code that only works in IE:
<head>
<!-- Begin
var isDOM = false, isNS4 = false;
if (document.all) var isDOM = true, docObj = 'document.all.', styObj = '.style';
else if (document.layers) var isNS4 = true, docObj = 'document.', styObj = '';
// Hide timeout
var popTimer = 0;
var litNow = new Array();
function popOver(menuNum, itemNum) {
clearTimeout(popTimer);
hideAllBut(menuNum);
litNow = getTree(menuNum, itemNum);
changeCol(litNow, true);
targetNum = menu[menuNum][itemNum].target;
if (targetNum > 0) {
targetName = menu[targetNum][0].id;
menuName = menu[menuNum][0].id;
menuRef = eval(docObj + menuName + styObj);
thisX = parseInt(menuRef.left);
thisY = parseInt(menuRef.top);
// Add onto this the position of the trigger item within the menu
itemPath = docObj;
if (isNS4) itemPath += menuName + '.document.';
itemRef = eval(itemPath + menuName + itemNum.toString() + styObj);
thisX += parseInt(itemRef.left);
thisY += parseInt(itemRef.top);
// Add those to the target's offset to set the target's position, show it.
with (eval(docObj + targetName + styObj)) {
left = parseInt(thisX + menu[targetNum][0].x);
top = parseInt(thisY + menu[targetNum][0].y);
visibility = 'visible';
}
}
}
function popOut(menuNum, itemNum) {
// Hide menu in 1/2 sec, *UNLESS* another mouseover clears the timeout!
popTimer = setTimeout('hideAllBut(0)', 500);
}
function getTree(menuNum, itemNum) {
// Array index is the menu number. The contents are null (if that menu is not a parent)
// or the item number in that menu that is an ancestor (to light it up).
itemArray = new Array(menu.length);
while(1) {
itemArray[menuNum] = itemNum;
if (menuNum == 0) return itemArray;
itemNum = menu[menuNum][0].parentItem;
menuNum = menu[menuNum][0].parentMenu;
}
}
// Pass an array and a boolean to specify colour change, true = over colour.
function changeCol(changeArray, isOver) {
for (menuCount = 0; menuCount < changeArray.length; menuCount++) {
if (changeArray[menuCount]) {
thisMenu = menu[menuCount][0].id;
thisItem = thisMenu + changeArray[menuCount].toString();
newCol = isOver ? menu[menuCount][0].overCol : menu[menuCount][0].backCol;
if (isDOM) document.all[thisItem].style.backgroundColor = newCol;
if (isNS4) document[thisMenu].document[thisItem].bgColor = newCol;
}
}
}
function hideAllBut(menuNum) {
var keepMenus = getTree(menuNum, 1);
for (count = 0; count < menu.length; count++)
if (!keepMenus[count])
eval(docObj + menu[count][0].id + styObj + '.visibility = "hidden"');
changeCol(litNow, false);
}
// *** MENU CONSTRUCTION FUNCTIONS ***
// Variable to end a div or layer based on browser.
var endDL = isDOM ? '</div>' : '</layer>';
function Menu(id, x, y, width, overCol, backCol, borderCol) {
this.id = id;
this.x = x;
this.y = y;
this.width = width;
// Colours of menu and items.
this.overCol = overCol;
this.backCol = backCol;
this.borderCol = borderCol;
// Parent menu and item numbers, indexed later.
this.parentMenu = null;
this.parentItem = null;
}
function Item(text, href, height, target) {
this.text = text;
this.href = href;
this.height = height;
this.target = target;
}
function startDL(id, x, y, width, height, vis, back, border, zIndex, extraProps) {
// Write a div in IE that resembles a layer's settings, or a layer in NS.
if (isDOM) {
str = '<div id="' + id + '" style="position: absolute; left: ' + x + '; top: ' + y +
'; width: ' + width + '; height: ' + height + '; visibility: ' + vis + '; ';
if (back) str += 'background: ' + back + '; ';
if (border) str += 'padding: 3px; border: 1px solid ' + border + '; ';
if (zIndex) str += 'z-index: ' + zIndex + '; ';
// End style declaration.
str += '" ';
}
if (isNS4) {
str = '<layer id="' + id + '" left="' + x + '" top="' + y + '" width="' + width +
'" height="' + height + '" visibility="' + vis + '" ';
if (back) str += 'bgcolor="' + back + '" ';
if (border) str += 'style="border: 1px solid ' + border + '" ';
if (zIndex) str += 'z-index="' + zIndex + '" ';
}
return str + extraProps + '>';
}
function mouseProps(currMenu, currItem) {
return 'onMouseOver="popOver(' + currMenu + ',' + currItem + ')" onMouseOut="popOut(' + currMenu + ',' + currItem + ')"';
}
function writeMenus(customRoot, popInd) {
for (currMenu = 0; currMenu < menu.length; currMenu++) {
showMenu = true;
if ((currMenu == 0) && customRoot) {
document.write(customRoot);
showMenu = false;
}
with (menu[currMenu][0]) {
// Start generating a div with position offset - no dimensions, colours, mouseovers.
// This position is only relevant for root menu anyway as all others are altered later.
menuHTML = startDL(id, x, y, 0, 0, 'hidden', null, null, 100, '');
// Width is less padding (3 left & right) and border (1 left & right).
var back = backCol, bord = borderCol, currWidth = width - 8;
}
// Y-position of next item, increase if you want a menu header.
itemPos = 0;
// Remember, items start from 1 in the array (0 is menu object itself, above).
for (currItem = 1; currItem < menu[currMenu].length; currItem++) {
// Auto-generate ID's in numerical sequence.
trigID = menu[currMenu][0].id + currItem.toString();
// Now, work with properties of individual menu items.
with (menu[currMenu][currItem]) {
// Start a menu item positioned vertically, with mouse events and colours.
menuHTML += startDL(trigID, 0, itemPos, 0, 0, 'inherit', back, bord, 100, mouseProps(currMenu, currItem)) + '<table width="' + currWidth + '" border="0" cellspacing="0" cellpadding="0"><tr>' + '<td align="left"><a class="Item" href="' + href + '">' + text + '</a></td>' + '<td class="Item" align="right">' + (target ? popInd : '') + '</td></tr></table>' + endDL;
if (target > 0) {
// Set target's parents to this and offset it by the current position.
menu[target][0].parentMenu = currMenu;
menu[target][0].parentItem = currItem;
}
// Move next item position down by this item's height.
itemPos += height;
}
}
// Write this menu to the document.
if (showMenu) document.write(menuHTML + endDL);
litNow[currMenu] = null;
}
}
// End -->
</script>
<style>
<!--
.Item { text-decoration: none; color: #FFFFFF; font: 12px Arial, Helvetica }
-->
</style>
</HEAD>
<!-- Begin
/* Syntaxes:
*
* menu[menuNumber][0] = new Menu('menu ID', left, top, width, 'mouseover colour',
*'background colour', 'border colour');
* Left and Top are measured on-the-fly relative to the top-left corner of its trigger.
*
* menu[menuNumber][itemNumber] = new Item('Text', 'URL', vertical spacing to next item,
*target menu number);
* If no target menu (popout) is desired, set it to 0. All menus must trace back their
* targets to the root menu! That is, every menu must be targeted by one item somewhere.
* Even if you're not writing the root menu, you must still specify its settings here.
*/
var menu = new Array();
// Default colours passed to most menu constructors (just passed to functions, not
// a global variable - makes things easier to change later).
var defOver = '#336699', defBack = '#003366', defBorder = '#000000';
// Default height of menu items - the spacing to the next item, actually.
var defHeight = 22;
// Menu 0 is the special, 'root' menu from which everything else arises.
menu[0] = new Array();
// Pass a few different colours, as an example.
menu[0][0] = new Menu('rootMenu', 0, 0, 80, '#669999', '#006666', defBorder);
// Notice how the targets are all set to nonzero values...
menu[0][1] = new Item('File', '#', defHeight, 1);
menu[0][2] = new Item('Edit', '#', defHeight, 2);
menu[0][3] = new Item('Help', '#', defHeight, 3);
menu[1] = new Array();
// The File menu is positioned 0px across and 22 down from its trigger, and is 80 wide.
menu[1][0] = new Menu('fileMenu', 0, 22, 80, defOver, defBack, defBorder);
menu[1][1] = new Item('Open', '#', defHeight, 0);
menu[1][2] = new Item('Save', '#', defHeight, 0);
// Non-zero target means this will trigger a popup.
menu[1][3] = new Item('Reopen', '#', defHeight, 4);
menu[1][4] = new Item('Exit', '#', defHeight, 0);
menu[2] = new Array();
menu[2][0] = new Menu('editMenu', 0, 22, 80, defOver, defBack, defBorder);
menu[2][1] = new Item('Cut', '#', defHeight, 0);
menu[2][2] = new Item('Copy', '#', defHeight, 0);
menu[2][3] = new Item('Paste', '#', defHeight, 0);
menu[3] = new Array();
menu[3][0] = new Menu('helpMenu', 0, 22, 80, defOver, defBack, defBorder);
menu[3][1] = new Item('Contents', '#', defHeight, 0);
menu[3][2] = new Item('Index', '#', defHeight, 0);
menu[3][3] = new Item('About', '#', defHeight, 5);
menu[4] = new Array();
// This is across but not down... a horizontal popout (with crazy colours :)...
menu[4][0] = new Menu('reopenMenu', 85, 0, 100, '#333366', '#666699', '#663399');
menu[4][1] = new Item('Recent Doc 1:
Schedule', '#', 36, 0);
menu[4][2] = new Item('Recent Doc 2:
Plan', '#', 40, 0);
menu[4][3] = new Item('Etc. etc...', '#', defHeight, 0);
menu[5] = new Array();
// Leftwards popout with a negative x relative to its trigger.
menu[5][0] = new Menu('aboutMenu', -85, -15, 80, defOver, defBack, defBorder);
menu[5][1] = new Item('Leftwards!
And up!', '#', 30, 0);
// Now, this next bit of script will write our own custom root menu -- a horizontal
// one, as the defaults are all vertical with borders. Even if you are writing your
// own root menu, you must still specify the names, colours and targets above -- the
// positions are calculated on the fly and hence are ignored.
// Basically, you must duplicate the output of the writeMenus() function. Just work
// from this example.
// Syntax: startDL('id', x, y, width, height, 'visibility', '#background colour or null
//for transparent', '#border colour or null for no border', 'additional properties');
// It returns a string of HTML text comprising the opening tag of a div or layer.
// mouseProps(menu, item) returns the 'onMouseEvent' properties for a specific menu item,
// passed as 'additional properties' to startDL. Just cut and paste below, or allow the
// script to write its own root menu.
// endDL is a variable containing either '</div>' or '</layer>', so add it afterwards.
newRoot = startDL('rootMenu', 0, 0, '100%', 17, 'hidden', '#006666', null, 100, '');
newRoot += startDL('rootMenu1', 5, 0, 40, 17, 'inherit', '#006666', null, 100, mouseProps(0, 1));
newRoot += '<span class="Item"> File</span>' + endDL;
newRoot += startDL('rootMenu2', 55, 0, 40, 17, 'inherit', '#006666', null, 100, mouseProps(0, 2));
newRoot += '<span class="Item"> Edit</span>' + endDL;
newRoot += startDL('rootMenu3', 105, 0, 40, 17, 'inherit', '#006666', null, 100, mouseProps(0, 3));
newRoot += '<span class="Item"> Help</span>' + endDL;
newRoot += endDL;
// Pass this two strings - the first is HTML to write a custom root menu, or null to
// generate one normally. The second is the popout indicator HTML - try an image...?
// Try writeMenus(null, '<img src="...">'); in your own script.
writeMenus(newRoot, '>');
// This is a quick snippet that captures all clicks on the document and hides the menus
// every time you click. Use if you want.
if (isNS4) document.captureEvents(Event.CLICK);
document.onclick = clickHandle;
function clickHandle(evt) {
if (isNS4) document.routeEvent(evt);
hideAllBut(0);
}
// Show root menu command - place in an onLoad="..." type function if you want.
eval(docObj + menu[0][0].id + styObj + '.visibility = "visible"');
// This is just the moving command for the example.
function moveRoot() {
rM = eval(docObj + menu[0][0].id + styObj);
if (parseInt(rM.top) < 40) rM.top = 40;
else rM.top = 0;
}
// End -->
</script>
</body>
this script was written by:Angus Turnbull
Thanks a lot all for your help.
please sned all help to:
[email protected]
Justin S posted this at 18:11 — 29th March 2001.
They have: 2,076 posts
Joined: Jun 1999
Raven,
I hope you don't mind, but I edited your post and added the vB CODE tags around the code, so it's a little easier to read.
So what exactly do you want to know? How to make it work in NS? What errors are you getting in NS?
Justin Stayton - [email] [icq]
Jack Michaelson posted this at 11:02 — 30th March 2001.
He has: 1,733 posts
Joined: Dec 1999
for crossbrowser menus check:
dynamicdrive.com
webreference.com
BTW: this must be the widest thread ever!
Want to join the discussion? Create an account or log in if you already have one. Joining is fast, free and painless! We’ll even whisk you back here when you’ve finished.