views:

62

answers:

2

I Want to create a stack type control where a series of stacked sub-divs can be re-ordered within a container div.

The sub-div 'views' would be the same size and absolutely positioned on top of each other.

The z-index css property seems to apply z-order at the document level, which makes no sense to me- How can an element in a given div have a higher z-order than something that is placed after that div? It just ignores the nested div heirarchy?

So the question is: Is there a way to manipulate relative z-order within a given div?

Thanks, Yarin

A: 

How can an element in a given div have a higher z-order than something that is placed after that div? It just ignores the nested div heirarchy?

Z-index only modifies the "layer" (imagine Photoshop) that the element is displayed on. Structurally, the box-model is not changed. Visually, it appears to be, but only if the positioning for the elements have been modified (through CSS) so that the z-index actually means something. Here's an example; notice how B appears above A and C event though C has the greatest z-index.

To modify the z-index of elements, relative to the container div that they are contained in, you have to make sure that the lowest z-index in the container is greater than the greatest z-index outside of the container. Then, you adjust the other z-indexes to offset them. This function (uses jQuery) gets the element with the greatest z-index, from the passed elements:

function getTopElement(elems){
    // Store the greates z-index that has been seen so far
    var maxZ = 0;
    // Stores a reference to the element that has the greatest z-index so far
    var maxElem;
    elems.each(function(){
        var z = parseInt($(this).css("z-index"), 10);
        // Ignore z-index of auto
        if (!isNaN(z)){
            if (parseInt($(this).css("z-index"), 10) > maxZ) {
                maxElem = $(this);
                maxZ = parseInt($(this).css("z-index"), 10);
                alert (maxZ);
            }
        }
    });
    return maxElem;
};

Use:

var topDiv = getTopElement($("div"));
var topZIndex = topDiv.css("z-index");

That should get you started.

Edit:

To fill in missing z-indexes, use this code:

var elements = $("div");
var newZ = parseInt(getTopElement(elements).css("z-index"), 10);

elements.each(function(){
    if (isNaN(parseInt($(this).css("z-index"),10))){
        $(this).css("z-index", ++newZ);
    }

});

What it does is it changes elements with a z-index of auto to one-plus whatever the greatest z-index is in the collection (elements);

To see what I mean, check out this demo.

SimpleCoder
@SimpleCoder- Thanks, but your example link is incomplete- there's no 'C' element, and so I can't understand your explanation there. Would you mind fixing it?
Yarin
@Yarin- I have fixed it, now try the link
SimpleCoder
Thanks, still working through this- first question: What happens when an element's z-index = "auto" in the getTopElement function you provide?
Yarin
First of all, I just fixed a small bug in the function (see edit). To answer your question, `$(element).css("z-index");` on an element with a `z-index` of `auto` will return the string `auto`. This is problematic with my function because it can't parse this as an integer. The function has been changed to ignore `z-index`es of `auto`.
SimpleCoder
To fill in missing "`auto`" `z-index`es, see my edit.
SimpleCoder
Here, check out this demo: http://jsfiddle.net/6t3BW/3/
SimpleCoder
A: 

If you want only one div to be visible then change its opacity to 1 in Firefox and 100 in IE and set the others to 0. Here's a slide show example that does just that. I would imagine yours wouldn't be based on a timer so you would need some other method to switch them.

curt