DHTML Lab: Cross-Browser Hierarchical Menus; User Interface
Cross-Browser Hierarchical Menus
| |||
Open the menus above to remind yourself that this is a technique worth learning. In longer script listings, cross-browser code is blue, Navigator-specific code is red, and Explorer code is green. |
The HTML LinksRecall that we placed links with onMouseOver and onMouseOut handlers, wherever we want our menus to appear on our page. The links in the left column, for example, have this HTML: <P><A HREF="/" onMouseOver = "popUp('elMenu1',event)" onMouseOut = "popDown('elMenu1')"> Webreference</A></P> <P><A HREF="/index2.html" onMouseOver="popUp('elMenu2',event)" onMouseOut="popDown('elMenu2')"> Contents</A></P> In Explorer, the event object is created and passed implicitly to any function the event handler calls. We therefore do not require the second argument for popUp(), as we do for Navigator. Its inclusion, however, is harmless. Note: Remember to use elMenu1, elMenu2, elMenu3 as the first arguments for popUp() and popDown(). Do not confuse these element identifiers with the array identifiers (arMenu1, arMenu2, etc.). Displaying the Top Level MenuThe only browser-specific code in our popUp() function is the assignment to xPos and yPos of the mouse's x-y coordinates. Explorer prefers event.x and event.y to define them. function popUp(menuName,e) { if (!areCreated) return; hideAll(); currentMenu = eval(menuName); xPos = (NS4) ? e.pageX : event.x; yPos = (NS4) ? e.pageY : event.y; currentMenu.moveTo(xPos,yPos); currentMenu.keepInWindow(); currentMenu.isOn = true; currentMenu.showIt(true); } Keeping the Menus in the Client WindowThe keepInWindow() function is primarily concerned with element and window measurement, and element positioning. Unfortunately, the two browsers don't agree on the properties used. The logic is exactly the same, just the property names differ. All the properties have been discussed and used before many times. It is a simple procedure to create a cross-browser function, but it involves a lot of ifs. To minimize them, we have used just one if...else statement to contain browser-specific code. This leads to quicker execution and easier reading, but more typing, since some statements are repeated. function keepInWindow() { scrBars = 20; if (NS4) { winRight = (keep with next line) (window.pageXOffset + window.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 = (keep with next line) (window.pageYOffset + window.innerHeight) - scrBars; botPos = this.top + this.fullHeight; if (botPos > winBot) { dif = botPos - winBot; this.top -= dif; } } else { winRight = (keep with next line) (document.body.scrollLeft + document.body.clientWidth) - srcBars; 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 = (keep with next line) (document.body.scrollTop + document.body.clientHeight) - scrBars; botPos = this.style.pixelTop + this.fullHeight; if (botPos > winBot) { dif = botPos - winBot; this.style.pixelTop -= dif; } } } The logic of keepInWindow() was, of course, discussed in our previous column. You may see the result by mousing over these right-aligned links: The showIt() Visibility ToggleSince our elements are dynamically created, Navigator insists on show/hide values for its visibility property. Explorer accepts the CSS-compliant visible/hidden values. function showIt(on) { if (NS4) {this.visibility = (on) ? "show" : "hide"} else {this.style.visibility = (on) ? "visible" : "hidden"} } Hiding All MenusOur hideAll() function is the same for both browsers: function hideAll(){ for(i=1; i<topCount; i++) { temp = eval("elMenu" + i); temp.isOn = false; if (temp.hasChildVisible) temp.hideChildren(); temp.showIt(false); } } onMouseOutThe function called when we mouse out of a link, popDown() is also the same for both browsers:function popDown(menuName){ if (!areCreated) return; whichEl = eval(menuName); whichEl.isOn = false; whichEl.hideTop(); } The boring stuff is over. The remaining pages will introduce a few new properties. |
Produced by Peter Belesis and
All Rights Reserved. Legal Notices.Created: Feb. 27, 1998
Revised: Feb. 27, 1998
URL: https://www.webreference.com/dhtml/column15/menu2Start.html