| home | community | downloads | matrix | search | news | join | members: 4802 |
|
Tue, 2007-01-16 15:17
You have just finished creating or installing a killer CSS Drop menu for your website. There is only one problem, in IE6 the menu disappears where HTML form elements and Flash layers appear. Form elements in IE will always cover DHTML layers. That means if you have a DIV that pops up or floats on the page and it crosses with a form element such as the common SELECT box, the form element will bleed through the CSS menu no matter what zIndex you have set. An example of this happening could be seen a Hiveminds.co.uk if not for the fix used. The initial solution adopted by most developers is dynamically hide a form controls by having them lose display when the CSS menu drops. Though doing this may seem to be strange and blinky it is better than not trying to fix the problem. But site vistors might be bothered a bit by things dancing around on the webpage. It is distracting and may be a cause for dozens of emails to the webmaster. As luck would have it had the idea for a solution comes from reading an article about this. Unfortunately the article contained no real life usage of the possibilities. But we will fix that here. iframeThe IFRAME control has a unique nature in IE 5.5+. It can exist in both the zIndex of windowed controls and the zIndex of regular HTML elements. Simply put, you can shim an IFRAME under your DIV and the IFRAME will block out the windowed control. Setting up your IFRAME: $contentStr .= '<IFRAME name = "shim" id = "shim" style="DISPLAY:none;LEFT: 0px; POSITION: absolute; TOP: 0px;width:160px;height:10px;" src="javascript:false;" frameBorder="1" scrolling="no"></IFRAME>'; The src attribute is set with a useless JavaScript statement so that the IFRAME does not try to load a page (which you won't notice it doing, but it will be the cause for tripping the "Unsecured Items" message if you use it on a HTTPS page). You can code your IFRAME as a static element on the page, or if you are going to be using more than one of them you may want to dynamically create them as required. I did not explore the latter alternative as in most cases I am using a CMS template so there is no need for it. Now, all that is needed is to size the IFRAME according to the dimensions of your DIV, position it, place it one layer beneath the DIV in the zIndex order and make it "visible". The IFRAME's style object will allow you to do these tasks: iframe.style.top What about transparency?If the DIV has transparent areas, you'll want those areas to punch through the IFRAME to the page background. There are two ways you can make an IFRAME transparent. The one that works for this situation is to set the style object's filter property: iframe.style.filter='progid:DXImageTransform.Microsoft.Alpha(style=0,opacity=0)'; This in effect makes the entire IFRAME transparent, but it will still block out the windowed controls. The other technique, which uses the IFRAME element's ALLOWTRANSPARENCY attribute, actually pertains to making the interior page background of the IFRAME transparent, so that any content inside the IFRAME can have transparency. However, this mode changes the nature of the IFRAME and it no longer serves our purpose for blocking out windowed controls. The theory is seems to be solid and the necessary tools are available. So now let's do it live. I wanted to use drop menus on the Hiveminds Magazine website and needed neat and compact script. What I wanted was:
The dynamicdrive.com Anylink menu suited the job perfectly because I did not want a full blown cascading menu. The only problem was that it suffered from the above discussed bug. I did not notice it at first because Firefox and IE7 do not have this problem. Since IE6 still has 50% of the web browser user market I do use it once or twice a week. When I did visit this website in IE I was greeted by a mess that had to be fixed. I started by placing an iframe in the source of the template file. Then I changed the Anylink.js code to the following. $contentStr .= '<IFRAME name = "shim" id = "shim" style="DISPLAY:none;LEFT: 0px; POSITION: absolute; TOP: 0px;width:160px;height:10px;" src="javascript:false;" frameBorder="1" scrolling="no"></IFRAME>';
/***********************************************
* AnyLink Vertical Menu- © Dynamic Drive (www.dynamicdrive.com)
* This notice MUST stay intact for legal use
* Visit http://www.dynamicdrive.com/ for full source code
***********************************************/
var disappeardelay=250 //menu disappear speed onMouseout (in miliseconds)
var enableanchorlink=0 //Enable or disable the anchor link when clicked on? (1=e, 0=d)
var hidemenu_onclick=1 //hide menu when user clicks within menu? (1=yes, 0=no)
var horizontaloffset=-10 //horizontal offset of menu from default location. (0-5 is a good value)
var spaceoffset=4
/////No further editting needed
var ie5=document.all
var ns6=document.getElementById&&!document.all
function getposOffset(what, offsettype){
var totaloffset=(offsettype=="left")? what.offsetLeft : what.offsetTop;
var parentEl=what.offsetParent;
while (parentEl!=null){
totaloffset=(offsettype=="left")? totaloffset+parentEl.offsetLeft : totaloffset+parentEl.offsetTop;
parentEl=parentEl.offsetParent;
}
return totaloffset;
}
function showhide(obj, e, visible, hidden){
if (ie5||ns6)
dropmenuobj.style.left=dropmenuobj.style.top=-500
if (e.type=="click" && obj.visibility==hidden || e.type=="mouseover")
obj.visibility=visible
else if (e.type=="click")
obj.visibility=hidden
}
function iecompattest(){
return (document.compatMode && document.compatMode!="BackCompat")? document.documentElement : document.body
}
function clearbrowseredge(obj, whichedge){
var edgeoffset=0
if (whichedge=="rightedge"){
var windowedge=ie5 && !window.opera? iecompattest().scrollLeft+iecompattest().clientWidth-15 : window.pageXOffset+window.innerWidth-15
dropmenuobj.contentmeasure=dropmenuobj.offsetWidth
if (windowedge-dropmenuobj.x-obj.offsetWidth < dropmenuobj.contentmeasure)
edgeoffset=dropmenuobj.contentmeasure+obj.offsetWidth+(horizontaloffset*2) //no space to the right of page? Move menu over to the left
}
else{
var topedge=ie5 && !window.opera? iecompattest().scrollTop : window.pageYOffset
var windowedge=ie5 && !window.opera? iecompattest().scrollTop+iecompattest().clientHeight-15 : window.pageYOffset+window.innerHeight-18
dropmenuobj.contentmeasure=dropmenuobj.offsetHeight
if (windowedge-dropmenuobj.y < dropmenuobj.contentmeasure){ //move menu up?
edgeoffset=dropmenuobj.contentmeasure-obj.offsetHeight
if ((dropmenuobj.y-topedge)<dropmenuobj.contentmeasure) //up no good either? (position at top of viewable window then)
edgeoffset=dropmenuobj.y
}
}
return edgeoffset
}
function dropdownmenu(obj, e, dropmenuID,shimW,shimH){
if (window.event) event.cancelBubble=true
else if (e.stopPropagation) e.stopPropagation()
if (typeof dropmenuobj!="undefined") //hide previous menu
dropmenuobj.style.visibility="hidden"
clearhidemenu()
if (ie5||ns6){
obj.onmouseout=delayhidemenu
dropmenuobj=document.getElementById(dropmenuID)
shimobj=document.getElementById("shim")
shimobj.x=getposOffset(obj, "left")
shimobj.y=getposOffset(obj, "top")
//menu to the right code
//shimobj.style.left=shimobj.x-clearbrowseredge(obj, "rightedge")+obj.offsetWidth+horizontaloffset+"px"
//shimobj.style.top=shimobj.y-clearbrowseredge(obj, "bottomedge")+"px"
shimobj.style.left=shimobj.x-clearbrowseredge(obj, "rightedge")+"px"
shimobj.style.top=shimobj.y-clearbrowseredge(obj, "bottomedge")+obj.offsetHeight + spaceoffset +"px"
shimobj.style.width=shimW
shimobj.style.height=dropmenuobj.offsetHeight
shimobj.style.zIndex=99
shimobj.style.border=0
shimobj.style.display='block'
shimobj.style.filter='progid:DXImageTransform.Microsoft.Alpha(style=0,opacity=0)'
if (hidemenu_onclick) dropmenuobj.onclick=function(){dropmenuobj.style.visibility='hidden'}
dropmenuobj.onmouseover=clearhidemenu
dropmenuobj.onmouseout=ie5? function(){ dynamichide(event)} : function(event){ dynamichide(event)}
showhide(dropmenuobj.style, e, "visible", "hidden")
dropmenuobj.x=getposOffset(obj, "left")
dropmenuobj.y=getposOffset(obj, "top")
// menu to the right code
//dropmenuobj.style.left=dropmenuobj.x-clearbrowseredge(obj, "rightedge")+obj.offsetWidth+horizontaloffset+"px"
//dropmenuobj.style.top=dropmenuobj.y-clearbrowseredge(obj, "bottomedge")+"px"
dropmenuobj.style.left=dropmenuobj.x-clearbrowseredge(obj, "rightedge")+"px"
dropmenuobj.style.top=dropmenuobj.y-clearbrowseredge(obj, "bottomedge")+obj.offsetHeight+spaceoffset+"px"
}
return clickreturnvalue()
}
function clickreturnvalue(){
if ((ie5||ns6) && !enableanchorlink) return false
else return true
}
function contains_ns6(a, b) {
while (b.parentNode)
if ((b = b.parentNode) == a)
return true;
return false;
}
function dynamichide(e){
if (ie5&&!dropmenuobj.contains(e.toElement))
delayhidemenu()
else if (ns6&&e.currentTarget!= e.relatedTarget&& !contains_ns6(e.currentTarget, e.relatedTarget))
delayhidemenu()
}
function delayhidemenu(){
shimobj=document.getElementById("shim")
shimhide=setTimeout("shimobj.style.display='none'",disappeardelay)
delayhide=setTimeout("dropmenuobj.style.visibility='hidden'",disappeardelay)
}
function clearhidemenu(){
if (typeof delayhide!="undefined")
clearTimeout(delayhide)
if (typeof shimhide!="undefined")
clearTimeout(shimhide)
}
About FlashThe solution works fine for IE but does not work in Firefox or Opera. These browser seem to do somethng else with an iFrame when faced with a collision with Flash. To get a CSS menu to appear above a Flash movie in Firefox or Opera the Flash movies properties need to be changed. Set the parameter wmode="transparent". This is also the solution for IE7. That's pretty much it. You can see how things worked out by looking at the top of the front page and clicking on a menu. The CSS layers look like they cover the login form, sIFR flash headlines and the select menus for the jumpboxes. I am not going to post all of the small code bits for the CSS divs. One because using the menu is slighty different for each situation and I can't cover them all. Two because doing so might break the license user agreement for the code. I am going to contact dynamicdrive and see about updating their scripts with this fix. Until then you can visit them to get instructions on use and just substitute our code after things are setup.
Tags: Tutorials This article brought to you by the
Hiveminds Magazine - Staff. Contact us if you want to post an article or announcement anonymously |
|
NewsletterGet updates on Hiveminds services, articles and downloads by signing up for the newsletter. |
Editor's choiceSome of the better articles, stories and tutorials found at Hiveminds. |
Find moreFind more of Hiveminds articles, stories, tutorials and user comments by searching. |
Picked linksHand picked websites and articles from around the web that provide quality reading. |