After some thorough research (i.e. a few Google searches), I hadn’t come up with a fully satisfactory explanation of why IE6 mishandled the z-index attribute. So, here’s a concise survival guide if you intend to use this attribute in IE6.
First, let’s revisit the intended properties of z-index:
Well, of course IE6 violates the CSS specification and starts handing out z-index values willy-nilly, even when it’s not assigned. Let’s see some examples:
#redbox {
border:1px solid black;
background:red;
width:100px;
height:100px;
position:relative;
top:0px;
left:50px;
z-index:1;
}
#bluebox {
border:1px solid black;
color:white;
background:blue;
width:100px;
height:100px;
position:relative;
top:-50px;
left:100px;
z-index:2;
}
So far, so good! Of course, there’s not a lot here to screw up, as it’s all pretty explicit. Now, I will blow things up by adding a parent element to #bluebox:
#parent {
position:relative;
}
Well, exactly what wasn’t supposed to happen did. According to CSS specs, nothing should have changed here. Instead, IE6 seems to generate a new stacking context for #bluebox based on its parent, despite the fact that the parent doesn’t even have a z-index specified. Well, what happens if we do specify one?
#parent {
position:relative;
z-index:1;
}
Oh, so now we’re okay. But, what if the z-index of the parent element is less than that of #redbox? Let’s make #parent’s z-index 2 and #redbox’s 3. According to CSS, this should establish a local stacking context where the stack level is ‘0′.
Phew; it works. I guess that means that if we set the parent z-index to 4, #bluebox will jump to the top again.
From this, we can deduct that IE6’s main fault is the ill-advised assignment of child z-index values when CSS specifically states that parent elements with no z-index value should not influence the stacking contexts of its children.
So, to be safe, make sure to set a z-index for all your positioned containers to avoid this bug. Or, when possible, simply eliminate the positioning of your parent containers:
#parent {
}
It didn’t take me long to realize that jQuery’s AJAX functions don’t trigger the $(document).ready() event. But then, it wouldn’t really make any sense if they did. Naturally, this event fires just once and naturally, AJAX leaves it alone. Therefore, it becomes necessary to supply event handlers to the AJAX callback functions, even if it means duplicating handlers in the DOM.
In my scenario, I had a styled table using the tablesorter plugin (id #tablesort).
Initial code sample:
$(document).ready(function() {
$("#tablesort").tablesorter({
widgets:['zebra'],
sortInitialOrder: 'asc'
});
$("#tablesort tr").hover(function(){
$(this).addClass("over");
},function(){
$(this).removeClass("over");
});
$("#tablesort tbody").hover(function() {
$(this).css({overflow-y: "auto"});
}, function() {
$(this).css({overflow-y: "hidden"});
});
});
With the inclusion of the AJAX function, each record in the data table would contain a link to generate further detail in a new table, for which I also wanted to apply the tablesorter styles (another id #tablesort.) This looked something like:
$("input.more").click(function() {
$("#ajax_div").html("Retrieving data...");
$.post("./include/ajax_table.php", {sql: $(this).val() }, function(data){
$("#ajax_div").html(data);
});
});
While this is enough to generate and display a second #tablesort, the new table lacks the same styles that jQuery applied to the first #tablesort on $(document).ready(). So, my first instinct was to simply copy & paste the event handlers into my jQuery callback function, like so:
$("input.more").click(function() {
$("#ajax_div").html("Retrieving data...");
$.post("./include/ajax_table.php", {sql: $(this).val() }, function(data){
$("#ajax_div").html(data);
$("#ajax_div tablesort").tablesorter({
widgets:['zebra'],
sortInitialOrder: 'asc'
});
$("#ajax_div tablesort tr").hover(function(){
$(this).addClass("over");
},function(){
$(this).removeClass("over");
});
$("#ajax_div tablesort tbody").hover(function() {
$(this).css({overflow-y: "auto"});
}, function() {
$(this).css({overflow-y: "hidden"});
});
});
});
Now, I had what I wanted — two #tablesort tables with identical styles. However, I also had a bunch of redundant and messy code at the top of my page. To fix this, I simply stored a function in an external file to handle the styling of all my #tablesort tables. Utilizing the find() function, this was even easier to do:
function tablesortStyles(jthis) {
jthis.find("#tablesort").tablesorter({
widgets:['zebra'],
sortInitialOrder: 'asc'
});
jthis.find("#tablesort tr").hover(function(){
$(this).addClass("over");
},function(){
$(this).removeClass("over");
});
jthis.find("#tablesort tbody").hover(function() {
$(this).css({overflow-y: "auto"});
}, function() {
$(this).css({overflow-y: "hidden"});
});
return true;
}
Now, I only needed to use two lines in my source file to style my tables:
$(document).ready(function() {
tablesortStyles($(document));
$("input.more").click(function() {
$("#ajax_div").html("Retrieving data...");
$.post("./include/ajax_table.php", {sql: $(this).val() }, function(data){
$("#ajax_div").html(data);
tablesortStyles($("#ajax_div"));
});
});
});
Here’s a tip from a few years ago. I was working in C# on an ASP.Net application and needed to run some Javascript code from the server side. That’s when I ran into the error.
I was trying to run something similar to the following code…
(more…)
© wkm. Powered by WordPress using the wkm Theme.