|
||
| Inside Technique : Popup Menus in IE 5.5 : Implementing a Popup Menu Armed with this knowledge, we set out to create a simple menu-system that would work anywhere including in a small frame. While we were eventually sucessful this turned out to be much more challenging than we expected. Our hope was to simply set the innerHTML to the menu text, display it, and let the user select the link having the new page display. This was unfortunately much simpler said than done. So as we continue, keep in mind how cool and exciting the end-result is even though we had to go through a few hoops to get there. Based on our simple assumptions and from reading the documentation, we hoped to define the menu as an invisible HTML fragment on the page and then copy this fragment to the popup window to be displayed. Below is our original failed attempt to accomplish this:
<STYLE>
.menu {display: none}
</STYLE>
<A HREF="#" ONCLICK="showMenu(this,submenu)">Go</A>
<!-- These define the menus.
They are invisible in the current page -->
<TABLE CLASS=menu ID=submenu>
<TR><TD NOWRAP>
<A HREF="/home.asp" TARGET="content">Home</A>
</TD></TR>
<TR><TD NOWRAP>
<A HREF="/jobs/home.asp" TARGET="content">Jobs</A>
</TD></TR>
<TR><TD NOWRAP>...</TD></TR>
</TABLE>
<SCRIPT LANGUAGE="JScript">
function showMenu(e,menu) {
var oPopup = window.createPopup();
var oPopupBody = oPopup.document.body;
oPopupBody.style.border = "1px black solid"
oPopupBody.innerHTML = menu.outerHTML
// null not supported - see below
oPopup.show(0, e.offsetHeight, null, null, e)
}
</SCRIPT>
Unfortunately, this did not work. The first problem was with the required width and height arguments of the show() method. One of the characteristics of HTML is that you usually do not need to know the size of your content - with HTML the content just flows. In our menu system, we did not know the height nor the width of our contents. We wanted to let the content define the flow hence our illegal use of null in the show() method. At a minimum, I would have hoped the height attribute was optional (width is questionable as it defines when the content should wrap). Our work-around is to render the popup menu offscreen so we can retrieve the content's actual width and height. To make sure the popup menu stays invisible we position it way offscreen in the negative coordinate space. We need to position the element offscreen rather than just hide the element because hidden elements have no size. We changed the style definition and our use of the show() method.
<STYLE>
.menu {position: absolute; top: -1000; left: -1000}
</STYLE>
<A HREF="#" ONCLICK="showMenu(this,sub)">Go</A>
<!-- These define the menus. They are invisible in the frameset -->
<TABLE CLASS=menu ID=sub>
<TR><TD NOWRAP><A HREF="/home.asp" TARGET="content">Home</A></TD></TR>
<TR><TD NOWRAP><A HREF="/jobs/home.asp" TARGET="content">Jobs</TD></TR>
<TR><TD NOWRAP>...</TD></TR>
</TABLE>
<SCRIPT LANGUAGE="JScript">
function showMenu(e,menu) {
var oPopup = window.createPopup();
var oPopupBody = oPopup.document.body;
oPopupBody.style.border = "1px black solid"
oPopupBody.innerHTML = menu.outerHTML
oPopup.show(0, e.offsetHeight, menu.offsetWidth, menu.offsetHeight, e)
}
</SCRIPT>
With this fix we should have been all set. However, there apparently is a problem where we could not get links to work. The href attribute has no effect. We were determined not to let this stop us so we decided to try and script around this issue. First we tried a very simple solution which involved adding inline onclick handlers to each link <A HREF="/home.asp" ONCLICK="location=this.href; return false" TARGET="content">Home </A> Unfortunately this did not work. The location object cannot be manipulated from the popup nor could we find an easy way to reference the source window. This did not seem like a big deal as we also know to use function pointers to assign event handlers. We decided to assign the onclick handler of the popup's body element to a function in the originating document. With this we can take advantage of event bubbling to detect clicks on any link but process the click in the context of the originating window. This becomes clearer when you see the script. Before showing the popup window, we assign a function reference to the popup's body element in the showMenu() function. oPopupBody.onclick = doClick The doClick function is defined in the same script block as the showMenu() function. This function is fairly simple. It determines if the user clicked on an A element in the popup and then assigns the HREF property of the link to the location of the current window:
function doClick() {
// Get the event object of the popup window
var ev = this.document.parentWindow.event
// If a link, set the location of the current window
// (not the popup)
if (ev.srcElement.tagName=="A")
self.location = ev.srcElement.href
}
Since this function exists
in the document that opens the popup, the Finally, getting back to our original goal, below is the complete script for doing the popup window:
<A HREF="#" ONCLICK="showMenu(this,submenu)">Main Menu</A>
<TABLE CLASS=menu ID=submenu>
<TR><TD NOWRAP>
<A HREF="/home.asp" TARGET="content">Home</A>
</TD></TR>
<TR><TD NOWRAP>
<A HREF="/jobs/home.asp" TARGET="content">Jobs</A>
</TD></TR>
<TR><TD NOWRAP>...</TD></TR>
</TABLE>
<SCRIPT>
var oPopup = window.createPopup();
function getA(el) {
while (el!=null) {
if (el.tagName=="A") return el
el = el.parentElement
}
return null
}
function doClick() {
// Get the event object of the popup window
var ev = this.document.parentWindow.event
// If a link, set the location of the current window
// We use a smart test that looks for a link anywhere
// above the clicked item. This allows additional
// formatting tags within the link. (eg., B, I, etc.)
var el = getA(ev.srcElement)
if (el)
self.location = el.href
}
function showMenu(e,menu) {
var oPopupBody = oPopup.document.body;
oPopupBody.style.border = "1px black solid"
oPopupBody.innerHTML = menu.outerHTML
oPopupBody.onclick = doClick
oPopup.show(0, e.offsetHeight, menu.offsetWidth, menu.offsetHeight,e)
}
</SCRIPT>
We have finally achieved our original goal - to create a popup menu that can extend beyond the boundaries of the document window. If you are running Internet Explorer 5.5, go to the top of this page and click on "Main Menu" in the upper-left corner. This displays our popup menu. If you make sure your browser window is fairly small you will see the menu extend beyond the window's boundaries. Page 1:Popup Menus in IE 5.5 © 1997-2000 InsideDHTML.com, LLC. All rights reserved. |