Portal Menus and Windowed Controlsby Gerald Nunn AbstractIn Internet Explorer (IE), dynamically positioning HTML elements in an overlapping fashion can lead to some elements hiding others. Unfortunately, this can occur in BEA WebLogic Portal 8.1 when multilevel menus are used on a portal page that contains specific HTML entities such as the SELECT element or ActiveX controls. The undesirable result is that the menu is partially hidden. This article shows an HTML technique that eliminates this problem by ensuring that menus are rendered above all other elements on the portal page. IntroductionDynamically displayed menus in HTML are often created by using DHTML effects that selectively show or hide portions of the HTML page. The menus created by WebLogic Portal use this technique by surrounding the menu items in standard HTML <DIV id=‘menu1Title‘ onClick=‘toggle("menu1")‘>File</DIV> <DIV id=‘menu1‘> <DIV id=‘menuItem1‘>Open</DIV> <DIV id=‘menuItem2‘>Close</DIV> <DIV id=‘menuItem3‘>Exit</DIV> </DIV> All of this is quite standard, and generally portal developers do not need to be exposed to this underlying implementation mechanism. But some browsers are notoriously fickle, and the technique outlined above can lead to a problem. While the solution works fine in Mozilla and Firefox, there is an issue with this technique when used with IE due to an IE implementation artifact dealing with windowed controls. Windowed controls is a term used by Windows developers to refer to controls that have a windows handle (HWND, for you Win32 geeks out there). These controls are managed and rendered by the operating system, not by the browser. When Microsoft created IE, it opted to use the existing Windows implementation of a combo box—a windowed control—as the implementation of the HTML For the purposes of this article, you don‘t need to understand handles or Win32 but just realize that since windowed controls are managed by the operating system and not the browser, HTML elements based on windowed controls have characteristics that may be different from regular HTML elements. The ProblemCutting to the chase, windowed controls are the cause of a long-standing problem in IE with dynamically positioning and showing
In the figure, the various selection boxes in the first portlet cover the drop-down menu, resulting in a menu that is effectively unusable. As most HTML developers know, the display of layered HTML elements in a browser is controlled by the This issue is covered in the MSDN documentation of the DHTML A SolutionFixing this problem for IE 5.5 and above is surprisingly simple due to a relatively new JavaScript technique as well as a change in the behavior of the This extra Applying the Shim Technique in WebLogic PortalSo now that we understand the shim technique, we need to apply it to the WebLogic Portal menus. Fortunately for us, the menus in WebLogic Portal are generated in JavaScript, and this makes it extremely easy for us to hook our shim into the menus. We only need to alter one file, The first change we need to make is to add all our new shim functions for creating, displaying, and hiding the shims as needed. Note that because WebLogic Portal displays many menus simultaneously as the user drills down through various child menus, we need to have the ability to create and display multiple shims. Essentially, there is a one-to-one relationship between a shim and each menu. Each shim is created with an id that corresponds to the menu it is associated with. Unfortunately, since The first step is to add some basic JavaScript functions to the file that will be referenced later when opening and closing menus. These functions appear below; simply append these functions at the end of //Opens a shim, if no shim exists for the menu, one is created function openShim(menu,menuItem) { if (menu==null) return; var shim = getShim(menu); if (shim==null) shim = createMenuShim(menu,getShimId(menu)); //Change menu zIndex so shim can work with it menu.style.zIndex = 100; var width = (menu.offsetWidth == 0 ? menuItem.renderedWidth : menu.offsetWidth); var height; if (menu.offsetHeight == 0) { var menus = getMenuItemCount(menu); height = menuItem.renderedHeight * menus; } else { var height = menu.offsetHeight; } shim.style.width = width; shim.style.height = height; shim.style.top = menu.style.top; shim.style.left = menu.style.left; shim.style.zIndex = menu.style.zIndex - 1; shim.style.position = "absolute"; shim.style.display = "block"; } //Closes the shim associated with the menu function closeShim(menu) { if (menu==null) return; var shim = getShim(menu); if (shim!=null) shim.style.display = "none"; } //Creates a new shim for the menu function createMenuShim(menu) { if (menu==null) return null; var shim = document.createElement("<iframe scrolling=‘no‘ frameborder=‘0‘"+ "style=‘position:absolute; top:0px;"+ "left:0px; display:none‘></iframe>"); shim.name = getShimId(menu); shim.id = getShimId(menu); //Unremark this line if you need your menus to be transparent for some reason //shim.style.filter="progid:DXImageTransform.Microsoft.Alpha(style=0,opacity=0)"; if (menu.offsetParent==null || menu.offsetParent.id=="") { window.document.body.appendChild(shim); } else { menu.offsetParent.appendChild(shim); } return shim; } //Creates an id for the shim based on the menu id function getShimId(menu) { if (menu.id==null) return "__shim"; return "__shim"+menu.id; } //Returns the shim for a specific menu function getShim(menu) { return document.getElementById(getShimId(menu)); } function getMenuItemCount(menu) { var count = 0; var child = menu.firstChild; while (child) { if (child.nodeName=="DIV") count = count + 1; child = child.nextSibling; } return count; } After you paste these new functions into the bottom of openShim(menu,menuItem);
Notice that this is a call to one of the functions we added earlier. All this does is ensure a shim gets created and displayed every time a menu is opened. Our next modification is to ensure we close the shim when a menu is closed. To do this, we modify the subMenu.style.display = "none";
Right after this line, add a new line to close the shim: closeShim(subMenu);
Again, this is a call to one of the functions that we pasted in earlier. Congratulations! You have finished the modifications. If you did everything correctly, your WebLogic Portal menus now should work correctly in IE 5.5 and above, as shown in Figure 2.
ConclusionThis article exposed the problem of HTML elements that are sometimes hidden by other DHTML elements when the page is rendered with Internet Explorer. We showed how using an References
Gerald Nunn is a business principal consultant with BEA Systems Professional Services. Return to dev2dev. |
|