Entry
why do select boxes show through popup layers
why do select boxes show through popup layers
Nov 4th, 2003 11:30
Adam Lyons,
http://notnull.org/docs/windowedvswindowless.htm (formatted document
source)
1 Managing WINDOWED ELEMENTS
There are several kinds of page elements on any given html document. A
common property to manage the layering aspect of these layers is the “z-
index” attribute. However, the implementation of the “z-index” is
inconsistent with global depth coordinates. These coordinate values are
segregated between “Windowed” and “Windowless” elements.
1.1 What Elements are What
The following sections have been extracted from Microsoft from this
location.
1.1.1.1 Windowed Elements
· <OBJECT> tag elements
· ActiveX controls
· Plug-ins
· Dynamic HTML (DHTML) Scriptlets
· SELECT elements
· IFRAMEs in Internet Explorer 5.01 and earlier
NOTE ActiveX controls are implemented as windowless and actually fall
into the windowless category. By default, Microsoft Visual Basic and
Microsoft Foundation Class (MFC) controls are windowed, but Active
Template Library (ATL) controls are windowless.
1.1.1.2 Windowless Elements
· Windowless ActiveX controls
· IFRAMEs in Internet Explorer 5.5 and later
· Most DHTML elements, such as hyperlinks or tables
1.2 The common problem and solution
The following screen capture show the problem in a generic sense. If
you wish to display content in a rollover effect (mouseover) and there
are windowed elements “beneth” the popup layer, the windowed elements
will show through, and the z-index property will not be respected. The
result of the interpreted code found in 1.4 looks like figure 1. It is
evident that the select element should not appear through the popup
table.
Figure 1 (example) http://notnull.org/docs/figure1.html
There are only a few ways to effectively handle this scenario depending
on the kind of content you are wishing to display. If the content is
not in a list format, meaning that you require layout control and text
markup features that are not singular to the content being displayed,
then you have but a few options to solve this problem. The first and
simplest option is to ensure that your layout of the document is
compatible with this issue. Simply do not layout and windowed elements
in places where popup content may overlap. If this is not sufficient or
too much time has already been invested in the initial layout and
design, then you could refer the all the popup content in a <IFRAME>.
Using IFRAMES with mouseover events could dampen performance
significantly, especially in complex CGI implementations. The other
possibility is to determine the coordinates (globally) of every
windowed element on a document and determine if the area of the element
is within the coordinates of the popup layer. This could impact the
overall aesthetics of the web page though, and confuse users as to why
portions of the page disappear when mouseover events are triggered! The
most practical method in battling this windowed vs. windowless
challenge is to popup a windowed element, instead of a windowless
element such as a table. All you need to do is populate a select box
with a specified height for read-ability. Figure 2 shows a much more
advanced layout along with the result of this technique.
Figure 2
For the sake of the previous example shown in Figure 1, here is the
modified result in figure 3.
Figure 3 (example) http://notnull.org/docs/figure3.html
Using CSS, you can modify a fair amount of properties to improve the
look of the popup. It is also a good idea to attach additional
javascript to the layer for maintaining the visibility of the popup
when the mouse enters the popup coordinates.
1.3 The complex solution
Using javascript to determine if a popup layer is over the coordinates
of a windowed element can be complex and damage the appearance of the
website. Figure 4 shows this result. The source code is available in
the appendix. This solution could work better if it was possible to set
the clipping regions of any element in a HTML document, however, you
can only set clipping on an image tag.
Figure 4 (example) http://notnull.org/docs/figure4.html
1.4 Appendix
1.4.1 Supporting code for figure 1
1.4.1.1 Style Sheet
<style type="text/css"><!--
.red { color:#ff0000; }
.white { color:#ffffff; }
.relative { position:relative; visibility:hidden; }
.absolute { position:absolute; visibility:hidden; }
.shadetable { background-color:#E6E1D0; cell-spacing:0; }
//--></style>
1.4.1.2 Javascript
<script language="JavaScript"><!--
function showByLink(object,link,x,y) {
if (document.layers && document.layers[object]) {
document.layers[object].left = link.x + x;
document.layers[object].top = link.y + y;
document.layers[object].visibility = 'visible';
}
else if (document.all) {
document.all[object].style.visibility = 'visible';
if (document.all[object].myFlag == null) {
document.all[object].style.posLeft = document.all
[object].offsetLeft + x;
document.all[object].style.posTop = document.all
[object].offsetTop + y;
}
document.all[object].myFlag = true;
}
}
function hide(object) {
if (document.layers && document.layers[object])
document.layers[object].visibility = 'hidden';
else if (document.all)
document.all[object].style.visibility = 'hidden';
}
//--></script>
1.4.1.3 HTML
<hr>
<table width="100%" border="1"><tr><td width="50%">
<center>
<p>
blah blah
<br>
blah blah
<span id="myLayer13" class="absolute" style="width:150;">
<table class="shadetable"><tr><td><div class="color:#ffffff"
height=100>Some popup text <br>Some popup
text<br>Windowless<br><br></div></td></tr></table>
</span>
<a href="nextpage.htm" onMouseover="showByLink('myLayer13',this,0,15)"
onMouseout="hide('myLayer13')">example popup</a>
blah blah
<br>
<select name=foo><option value="">Windowed
</p>
</center>
</td></tr></table>
<hr>
1.4.2 Supporting code for Figure 4
<html>
<script language="Javascript">
var ObjRestore = new Array;
function show() {
document.all.popup.style.visibility = 'visible';
showXY('popup');
var s_object = new ObjCoor();
s_object = setGlobalX('popup', 'popup', s_object)
s_object.name = 'popup';
for(i=0; i<=document.forms[0].elements.length; i++) {
if(document.forms[0].elements[i] !=
null) {
if(document.forms
[0].elements[i].type == 'select-one') {
id =
document.forms[0].elements[i].id;
if(id) {
var test_object = new ObjCoor();
test_object = setGlobalX(id, id, test_object)
test_object.name = id;
//getGlobalX(id, id);
//alert("test " + document.forms[0].elements[i].id);
// Test to see if c_object values are within overlay clip
if(test_object.tl < c_object.tr) {
if(test_object.tr < c_object.tl) {
// the select is clear of the
popup
} else {
// hide the select
//clipper(test_object,
s_object);
if(test_object.top >
c_object.top) {
if
(test_object.bottom < c_object.bottom) {
clipper(test_object, s_object);
}
}
}
} else {
if(test_object.tr < c_object.tl) {
// hide the select
clipper(test_object, s_object);
}
}
}
}
}
}
}
function clipper(test_object, s_object) {
//alert("CLIPPER" + test_object.name + " " +
c_object.name);
clipped = document.getElementById(test_object.name);
//alert(clipped.id);
clipped.style.clip.top = 0;
clipped.style.clip.right = 50;
clipped.style.clip.bottom = 50;
clipped.style.clip.left = 0;
clipped.style.visibility = 'hidden';
ObjRestore.push(id);
// clip:rect(top right bottom left)
}
function hide() {
document.all.popup.style.visibility = 'hidden';
for(i=0; i<= ObjRestore.length; i++) {
id = ObjRestore[i];
if(id) {
clipped = document.getElementById(id);
clipped.style.visibility = 'visible';
}
}
}
function getParent(id) {
var el=document.getElementById(id).offsetParent.id;
Falert('showParent', el);
}
var globalx = 0;
var globaly = 0;
var globalxr = 0;
var c_object = new ObjCoor();
function ObjCoor() {
this.tl = 0;
this.tr = 0;
this.bl = 0;
this.br = 0;
this.top = 0;
this.bottom = 0;
}
function setGlobalX(id, child, object) {
var parent = document.getElementById
(id).offsetParent.id;
globalxr = 0;
if(parent) {
globaly += document.getElementById
(parent).offsetTop;
globalx += document.getElementById
(parent).offsetLeft;
setGlobalX(parent, child, object);
} else {
object.name = document.getElementById
(child).id;
globaly += document.getElementById
(child).offsetTop;
object.top = globaly;
object.bottom = globaly +
document.getElementById(child).offsetHeight;
globalx += document.getElementById
(id).offsetLeft;
object.tl = globalx;
object.tr = globalx +
document.getElementById(child).offsetWidth;
object.bl = document.getElementById
(child).offsetHeight + globalx;
object.br = document.getElementById
(child).offsetHeight + c_object.tr;
globalx = 0;
globaly = 0;
globalxr = 0;
}
return object;
}
function getGlobalX(id, child) {
var parent = document.getElementById
(id).offsetParent.id;
globalxr = 0;
if(parent) {
globaly += document.getElementById
(parent).offsetTop;
globalx += document.getElementById
(parent).offsetLeft;
getGlobalX(parent, child);
} else {
c_object.name = document.getElementById
(child).id;
globaly += document.getElementById
(child).offsetTop;
c_object.top = globaly;
c_object.bottom = globaly +
document.getElementById(child).offsetHeight;
Falert('showY', globaly);
Falert('showB', c_object.bottom);
globalx += document.getElementById
(id).offsetLeft;
c_object.tl = globalx;
Falert('showGlobalTL', c_object.tl);
c_object.tr = globalx +
document.getElementById(child).offsetWidth;
Falert('showGlobalTR', c_object.tr);
c_object.bl = document.getElementById
(child).offsetHeight + globalx;
Falert('showGlobalBL', c_object.bl);
c_object.br = document.getElementById
(child).offsetHeight + c_object.tr;
Falert('showGlobalBR', c_object.br);
globalx = 0;
globaly = 0;
globalxr = 0;
}
}
function showXY(id) {
getLeft(id);
getTop(id);
getWidth(id);
getHeight(id);
getParent(id);
getGlobalX(id, id);
}
function getLeft(id) {
var el=document.getElementById(id).offsetLeft;
Falert('showX', el);
}
function getTop(id) {
var el=document.getElementById(id).offsetTop;
Falert('showY', el);
}
function getWidth(id) {
var el=document.getElementById(id).offsetWidth;
Falert('showW', el);
return(el);
}
function getHeight(id) {
var el=document.getElementById
(id).offsetHeight;
Falert('showH', el);
return(el);
}
function Falert(id, val) {
document.getElementById(id).value = val;
}
</script>
<input id=show type=input name=showX size=4>X (offset)<br>
<input id=show type=input name=showY size=4>Y (offset)<br>
<input id=show type=input name=showB size=4>Bottom (offset)<br>
<input id=show type=input name=showW size=4>Width (offset)<br>
<input id=show type=input name=showH size=4>Height (offset)<br>
<input id=show type=input name=showParent size=4>Parent<br>
<input id=show type=input name=showGlobalTL size=4>X (global top left)
<br>
<input id=show type=input name=showGlobalTR size=4>X Right (global top
right)<br>
<input id=show type=input name=showGlobalBL size=4>X (global bottom
left)<br>
<input id=show type=input name=showGlobalBR size=4>X Right (global
bottom right)<br><br>
<br>
<a href="javascript:void()" onmouseover="javascript:show()"
onmouseout="javascript:hide()">SHOW THE POPUP FLAW</a>
<div style="visibility: hidden; position: absolute" id=popup>
<table border=1>
<tr><td>TEST</td><td>TEST</td><td>TEST</td></tr>
<tr><td>TEST</td><td>TEST</td><td>TEST</td></tr>
<tr><td>TEST</td><td>TEST</td><td>TEST</td></tr>
<tr><td>TEST</td><td>TEST</td><td>TEST</td></tr>
<tr><td>TEST</td><td>TEST</td><td>TEST</td></tr>
<tr><td>TEST</td><td>TEST</td><td>TEST</td></tr>
<tr><td>TEST</td><td>TEST</td><td>TEST</td></tr>
</table>
</div>
<div id=divtag>
<form>
<table border=1 id=table>
<tr>
<td>foo</td>
<td id=col1><select name=select1 onmouseover="javascript:showXY
('select1')"
id=select1><option>one<option>two<option>three<option>four<option>five</
select></td>
<td id=col2><select name=select2 onmouseover="javascript:showXY
('select2')"
id=select2><option>tow<option>two<option>three<option>four<option>five</
select></td>
<td id=col3><select name=select3 onmouseover="javascript:showXY
('select3')"
id=select3><option>three<option>two<option>three<option>four<option>five
</select></td>
<td id=col4><select name=select4 onmouseover="javascript:showXY
('select4')" id=select4>
<option>four<option>two<option>three<option>four<option>five</select></t
d>
<td id=col5><select name=select5 onmouseover="javascript:showXY
('select5')"
id=select5><option>five<option>two<option>three<option>four<option>five<
/select></td>
<td id=col6><select name=select6 onmouseover="javascript:showXY
('select6')"
id=select6><option>six<option>two<option>three<option>four<option>five</
select></td>
</tr>
<tr>
<td>foo</td>
<td id=col7><select name=select7 onmouseover="javascript:showXY
('select7')"
id=select7><option>one<option>two<option>three<option>four<option>five</
select></td>
<td id=col8><select name=select8 onmouseover="javascript:showXY
('select8')"
id=select8><option>tow<option>two<option>three<option>four<option>five</
select></td>
<td id=col9><select name=select9 onmouseover="javascript:showXY
('select9')"
id=select9><option>three<option>two<option>three<option>four<option>five
</select></td>
<td id=col10><select name=select10 onmouseover="javascript:showXY
('select10')" id=select10>
<option>four<option>two<option>three<option>four<option>five</select></t
d>
<td id=col11><select name=select11 onmouseover="javascript:showXY
('select11')"
id=select11><option>five<option>two<option>three<option>four<option>five
</select></td>
<td id=col12><select name=select12 onmouseover="javascript:showXY
('select12')"
id=select12><option>six<option>two<option>three<option>four<option>five<
/select></td>
</tr>
<tr>
<td>foo</td>
<td id=col13><select name=select1 onmouseover="javascript:showXY
('select13')"
id=select13><option>one<option>two<option>three<option>four<option>five<
/select></td>
<td id=col14><select name=select2 onmouseover="javascript:showXY
('select14')"
id=select14><option>tow<option>two<option>three<option>four<option>five<
/select></td>
<td id=col15><select name=select3 onmouseover="javascript:showXY
('select15')"
id=select15><option>three<option>two<option>three<option>four<option>fiv
e</select></td>
<td id=col16><select name=select4 onmouseover="javascript:showXY
('select16')" id=select16>
<option>four<option>two<option>three<option>four<option>five</select></t
d>
<td id=col17><select name=select5 onmouseover="javascript:showXY
('select17')"
id=select17><option>five<option>two<option>three<option>four<option>five
</select></td>
<td id=col18><select name=select6 onmouseover="javascript:showXY
('select18')"
id=select18><option>six<option>two<option>three<option>four<option>five<
/select></td>
</tr>
<tr>
<td>foo</td>
<td id=col19><select name=select1 onmouseover="javascript:showXY
('select19')"
id=select19><option>one<option>two<option>three<option>four<option>five<
/select></td>
<td id=col20><select name=select2 onmouseover="javascript:showXY
('select20')"
id=select20><option>tow<option>two<option>three<option>four<option>five<
/select></td>
<td id=col21><select name=select3 onmouseover="javascript:showXY
('select21')"
id=select21><option>three<option>two<option>three<option>four<option>fiv
e</select></td>
<td id=col22><select name=select4 onmouseover="javascript:showXY
('select22')" id=select22>
<option>four<option>two<option>three<option>four<option>five</select></t
d>
<td id=col23><select name=select5 onmouseover="javascript:showXY
('select23')"
id=select23><option>five<option>two<option>three<option>four<option>five
</select></td>
<td id=col24><select name=select6 onmouseover="javascript:showXY
('select24')"
id=select24><option>six<option>two<option>three<option>four<option>five<
/select></td>
</tr>
<tr>
<td>foo</td>
<td id=col25><select name=select1 onmouseover="javascript:showXY
('select25')"
id=select25><option>one<option>two<option>three<option>four<option>five<
/select></td>
<td id=col26><select name=select2 onmouseover="javascript:showXY
('select26')"
id=select26><option>tow<option>two<option>three<option>four<option>five<
/select></td>
<td id=col27><select name=select3 onmouseover="javascript:showXY
('select27')"
id=select27><option>three<option>two<option>three<option>four<option>fiv
e</select></td>
<td id=col28><select name=select4 onmouseover="javascript:showXY
('select28')" id=select28>
<option>four<option>two<option>three<option>four<option>five</select></t
d>
<td id=col29><select name=select5 onmouseover="javascript:showXY
('select29')"
id=select29><option>five<option>two<option>three<option>four<option>five
</select></td>
<td id=col30><select name=select6 onmouseover="javascript:showXY
('select30')"
id=select30><option>six<option>two<option>three<option>four<option>five<
/select></td>
</tr>
<tr>
<td>foo</td>
<td id=col31><select name=select1 onmouseover="javascript:showXY
('select31')"
id=select31><option>one<option>two<option>three<option>four<option>five<
/select></td>
<td id=col32><select name=select2 onmouseover="javascript:showXY
('select32')"
id=select32><option>tow<option>two<option>three<option>four<option>five<
/select></td>
<td id=col33><select name=select3 onmouseover="javascript:showXY
('select33')"
id=select33><option>three<option>two<option>three<option>four<option>fiv
e</select></td>
<td id=col34><select name=select4 onmouseover="javascript:showXY
('select34')" id=select34>
<option>four<option>two<option>three<option>four<option>five</select></t
d>
<td id=col35><select name=select5 onmouseover="javascript:showXY
('select35')"
id=select35><option>five<option>two<option>three<option>four<option>five
</select></td>
<td id=col36><select name=select6 onmouseover="javascript:showXY
('select36')"
id=select36><option>six<option>two<option>three<option>four<option>five<
/select></td>
</tr>
<tr>
<td>foo</td>
<td id=col37><select name=select1 onmouseover="javascript:showXY
('select37')"
id=select37><option>one<option>two<option>three<option>four<option>five<
/select></td>
<td id=col38><select name=select2 onmouseover="javascript:showXY
('select38')"
id=select38><option>tow<option>two<option>three<option>four<option>five<
/select></td>
<td id=col39><select name=select3 onmouseover="javascript:showXY
('select39')"
id=select39><option>three<option>two<option>three<option>four<option>fiv
e</select></td>
<td id=col40><select name=select4 onmouseover="javascript:showXY
('select40')" id=select40>
<option>four<option>two<option>three<option>four<option>five</select></t
d>
<td id=col41><select name=select5 onmouseover="javascript:showXY
('select41')"
id=select41><option>five<option>two<option>three<option>four<option>five
</select></td>
<td id=col42><select name=select6 onmouseover="javascript:showXY
('select42')"
id=select42><option>six<option>two<option>three<option>four<option>five<
/select></td>
</tr>
<tr>
<td>foo</td>
<td id=col43><select name=select1 onmouseover="javascript:showXY
('select43')"
id=select43><option>one<option>two<option>three<option>four<option>five<
/select></td>
<td id=col44><select name=select2 onmouseover="javascript:showXY
('select44')"
id=select44><option>tow<option>two<option>three<option>four<option>five<
/select></td>
<td id=col45><select name=select3 onmouseover="javascript:showXY
('select45')"
id=select45><option>three<option>two<option>three<option>four<option>fiv
e</select></td>
<td id=col46><select name=select4 onmouseover="javascript:showXY
('select46')" id=select46>
<option>four<option>two<option>three<option>four<option>five</select></t
d>
<td id=col47><select name=select5 onmouseover="javascript:showXY
('select47')"
id=select47><option>five<option>two<option>three<option>four<option>five
</select></td>
<td id=col48><select name=select6 onmouseover="javascript:showXY
('select48')"
id=select48><option>six<option>two<option>three<option>four<option>five<
/select></td>
</tr>
</table>
</form>
</div>
</html>