<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/tr/xhtml1/DTD/xhtml1-transitional.dtd"> <!-- Example File From "JavaScript and DHTML Cookbook" Published by O'Reilly & Associates Copyright 2003 Danny Goodman --> <html> <head> <title>Recipe 10.8</title> <style id="main" type="text/css"> body {background-color:#eeeeee; font-family:Arial,Helvetica,sans-serif; font-size:12px;} h1 {font-size:2.0em; font-weight:bold} </style> <style rel="stylesheet" type="text/css">
.menuWrapper { position:absolute; width:162px; background-color:#339966; visibility:hidden; border-style:solid; border-width:2px; border-color:#EFEFEF #505050 #505050 #EFEFEF; display:block; padding:3px; } .menuItem { cursor:pointer; font-size:12px; font-family:Arial, Helvetica, sans-serif; border-bottom:1px solid #505050; border-top:1px solid #EFEFEF; padding-left:10px; color:black; background-color:#339966; text-decoration:none; position:absolute; left:0px; width:159px; height:1.4em; display:block; line-height:1.4em } .menuItemOn { cursor:pointer; font-size:12px; font-family:Arial, Helvetica, sans-serif; border-bottom:1px solid #505050; border-top:1px solid #EFEFEF; padding-left:10px; color:#000000; background-color:#33ff00; text-decoration:underline; position:absolute; left:0px; width:159px; height:1.4em; display:block; line-height:1.4em }
</style>
<script language="JavaScript" type="text/javascript"> // global menu state var menuReady = false;
// pre-cache menubar image pairs if (document.images) { var imagesNormal = new Array(); imagesNormal["home"] = new Image(20, 80); imagesNormal["home"].src = "home_off.jpg"; imagesNormal["catalog"] = new Image(20, 80); imagesNormal["catalog"].src = "catalog_off.jpg"; imagesNormal["about"] = new Image(20, 80); imagesNormal["about"].src = "about_off.jpg";
var imagesHilite = new Array(); imagesHilite["home"] = new Image(20, 80); imagesHilite["home"].src = "home_on.jpg"; imagesHilite["catalog"] = new Image(20, 80); imagesHilite["catalog"].src = "catalog_on.jpg"; imagesHilite["about"] = new Image(20, 80); imagesHilite["about"].src = "about_on.jpg"; }
function getElementStyle(elem, IEStyleProp, CSSStyleProp) { if (elem.currentStyle) { return elem.currentStyle[IEStyleProp]; } else if (window.getComputedStyle) { var compStyle = window.getComputedStyle(elem, ""); return compStyle.getPropertyValue(CSSStyleProp); } return ""; }
// carry over some critical menu style sheet attribute values var CSSRuleValues = {menuItemHeight:"18px", menuItemLineHeight:"1.4em", menuWrapperBorderWidth:"2px", menuWrapperPadding:"3px", defaultBodyFontSize:"12px" };
// specifications for menu contents and menubar image associations var menus = new Array(); menus[0] = {mBarImgId:"menuImg_1", mBarImgNormal:imagesNormal["home"], mBarImgHilite:imagesHilite["home"], menuItems:[], elemId:"" }; menus[1] = {mBarImgId:"menuImg_2", mBarImgNormal:imagesNormal["catalog"], mBarImgHilite:imagesHilite["catalog"], menuItems:[ {text:"Deluxe Line", href:"catalog_deluxe.html"}, {text:"Budget Line", href:"catalog_budget.html"}, {text:"Export", href:"catalog_export.html"}, {text:"Order Print Catalog", href:"catalog_order.html"} ], elemId:"" }; menus[2] = {mBarImgId:"menuImg_3", mBarImgNormal:imagesNormal["about"], mBarImgHilite:imagesHilite["about"], menuItems:[ {text:"Press Releases", href:"press.html"}, {text:"Executive Staff", href:"staff.html"}, {text:"Map to Our Offices", href:"map.html"}, {text:"Company History", href:"history.html"}, {text:"Job Postings", href:"jobs.html"}, {text:"Contact Us", href:"contact.html"} ], elemId:"" };
// create hash table-like lookup for menu objects with id string indexes function makeHashes() { for (var i = 0; i < menus.length; i++) { menus[menus[i].elemId] = menus[i]; menus[menus[i].mBarImgId] = menus[i]; } }
// assign menu label image event handlers function assignLabelEvents() { var elem; for (var i = 0; i < menus.length; i++) { elem = document.getElementById(menus[i].mBarImgId); elem.onmouseover = swap; elem.onmouseout = swap; } }
// invoked from init(), generates the menu div elements and their contents. // all this action is invisible to user during construction function makeMenus() { var menuDiv, menuItem, itemLink, mbarImg, textNode, offsetLeft, offsetTop; // determine key adjustment factors for the total height of menu divs var menuItemH = 0; var bodyFontSize = parseInt(getElementStyle(document.body, "fontSize", "font-size")); // test to see if browser's font size has been adjusted by the user // and that the new size registers as an applied style property if (bodyFontSize == parseInt(CSSRuleValues.defaultBodyFontSize)) { menuItemH = (parseFloat(CSSRuleValues.menuItemHeight)); } else { // works nicely in Netscape 7 menuItemH = parseInt(parseFloat(CSSRuleValues.menuItemLineHeight) * bodyFontSize); } var heightAdjust = parseInt(CSSRuleValues.menuWrapperPadding) + parseInt(CSSRuleValues.menuWrapperBorderWidth); if (navigator.appName == "Microsoft Internet Explorer" && navigator.userAgent.indexOf("Win") != -1 && (typeof document.compatMode == "undefined" || document.compatMode == "BackCompat")) { heightAdjust = -heightAdjust; } // use menus array to drive div creation loop for (var i = 0; i < menus.length; i++) { menuDiv = document.createElement("div"); menuDiv.id = "popupmenu" + i; // preserve menu's ID as property of the menus array item menus[i].elemId = "popupmenu" + i; menuDiv.className = "menuWrapper"; if (menus[i].menuItems.length > 0) { menuDiv.style.height = (menuItemH * menus[i].menuItems.length) - heightAdjust + "px"; } else { // don't display any menu div lacking menu items menuDiv.style.display = "none"; } // define event handlers menuDiv.onmouseover = keepMenu; menuDiv.onmouseout = requestHide;
// set stacking order in case other layers are around the page menuDiv.style.zIndex = 1000; // assemble menu item elements for inside menu div for (var j = 0; j < menus[i].menuItems.length; j++) { menuItem = document.createElement("div"); menuItem.id = "popupmenuItem_" + i + "_" + j; menuItem.className = "menuItem"; menuItem.onmouseover = toggleHighlight; menuItem.onmouseout = toggleHighlight; menuItem.onclick = hideMenus; menuItem.style.top = menuItemH * j + "px"; itemLink = document.createElement("a"); itemLink.href = menus[i].menuItems[j].href; itemLink.className = "menuItem"; itemLink.onmouseover = toggleHighlight; itemLink.onmouseout = toggleHighlight; textNode = document.createTextNode(menus[i].menuItems[j].text); itemLink.appendChild(textNode); menuItem.appendChild(itemLink); menuDiv.appendChild(menuItem); } // append each menu div to the body document.body.appendChild(menuDiv); } makeHashes(); assignLabelEvents(); // pre-position menu for (i = 0; i < menus.length; i++) { positionMenu(menus[i].elemId); } menuReady = true; }
// initialize global that helps manage menu hiding var timer;
// invoked from mouseovers inside menus to cancel hide // request from mouseout of menu bar image et al. function keepMenu() { clearTimeout(timer); }
function cancelAll() { keepMenu(); menuReady = false; }
// invoked from mouseouts to request hiding all menus // in 1/4 second, unless cancelled function requestHide() { timer = setTimeout("hideMenus()", 250); }
// "brute force" hiding of all menus and restoration // of normal menu bar images function hideMenus() { for (var i = 0; i < menus.length; i++) { document.getElementById(menus[i].mBarImgId).src = menus[i].mBarImgNormal.src; var menu = document.getElementById(menus[i].elemId) menu.style.visibility = "hidden"; } }
// set menu position just before displaying it function positionMenu(menuId){ // use the menu bar image for position reference of related div var mBarImg = document.getElementById(menus[menuId].mBarImgId); var offsetTrail = mBarImg; var offsetLeft = 0; var offsetTop = 0; while (offsetTrail) { offsetLeft += offsetTrail.offsetLeft; offsetTop += offsetTrail.offsetTop; offsetTrail = offsetTrail.offsetParent; } if (navigator.userAgent.indexOf("Mac") != -1 && typeof document.body.leftMargin != "undefined") { offsetLeft += document.body.leftMargin; offsetTop += document.body.topMargin; } var menuDiv = document.getElementById(menuId); menuDiv.style.left = offsetLeft + "px"; menuDiv.style.top = offsetTop + mBarImg.height + "px"; }
// display a particular menu div function showMenu(menuId) { if (menuReady) { keepMenu(); hideMenus(); positionMenu(menuId); var menu = document.getElementById(menuId); menu.style.visibility = "visible"; } }
// menu bar image swapping, invoked from mouse events in menu bar // swap style sheets for menu items during rollovers function toggleHighlight(evt) { evt = (evt) ? evt : ((event) ? event : null); if (typeof menuReady != "undefined") { if (menuReady && evt) { var elem = (evt.target) ? evt.target : evt.srcElement; if (elem.nodeType == 3) { elem = elem.parentNode; } if (evt.type == "mouseover") { keepMenu(); elem.className ="menuItemOn"; } else { elem.className ="menuItem"; requestHide(); } evt.cancelBubble = true; } } }
function swap(evt) { evt = (evt) ? evt : ((event) ? event : null); if (typeof menuReady != "undefined") { if (evt && (document.getElementById && document.styleSheets) && menuReady) { var elem = (evt.target) ? evt.target : evt.srcElement; if (elem.className == "menuImg") { if (evt.type == "mouseover") { showMenu(menus[elem.id].elemId); elem.src = menus[elem.id].mBarImgHilite.src; } else if (evt.type == "mouseout") { requestHide(); } evt.cancelBubble = true; } } } }
// create menus only if key items are supported function initMenus() { if (document.getElementById && document.styleSheets) { setTimeout("makeMenus()", 5); window.onunload=cancelAll; } }
</script> </head> <body onload="initMenus()"> <h1>Drop-Down Menus</h1> <hr />
<div id="menubar"> <a href="index.html"><img id="menuImg_1" class="menuImg" src="home_off.jpg" border="0" height="20" width="80"></a><a href="catalog.html"><img id="menuImg_2" class="menuImg" src="catalog_off.jpg" border="0" height="20" width="80"></a><a href="about.html"><img id="menuImg_3" class="menuImg" src="about_off.jpg" border="0" height="20" width="80"></a> </div>
</body> </html>
|