user1121487
user1121487

Reputation: 2680

JavaScript multiple draggable DIV windows, zIndex on focus

I have multiple JavaScript draggable DIV windows. When clicking a DIV, I want the window to get the highest z-index value. I've made a solution by adding/removing classes to the element in focus, BUT, I would like the windows to keep their "layer" -order (as if the entire DIV window node was re-appended to the DOM when being clicked).

Let's say there are five DIV's in the DOM. div1, div2, div3, div4 and div5. -div5 is closest to the front and div1 is in the back and so on.

When clicking div1, -div1 will get focus and put to front, setting div5 back one step. Then clicking div3, -div3 gets closest to front and div1 and div5 are put back one step like this: div2, div4, div5, div1, div3.

Upvotes: 0

Views: 1786

Answers (3)

Treip
Treip

Reputation: 41

If you'd like to do this without re-appending the element, my solution when I wrote something similar a while back was to keep track of the maximum z-index. Every time a window is brought forward, the maximum z-index is incremented and the element's z-index is set to the new value. Of course, if someone messes with the windows enough, they might end up having very large z-index values, so this isn't always the best solution.

var maximumZIndex = 1;
var bringForward = function (element) {
    maximumZIndex += 1;
    element.style.zIndex = maximumZIndex;
}

Upvotes: 0

Julian D.
Julian D.

Reputation: 5463

The first and most likely easiest approach: simply increase the maximum z-index every time a div gets selected. Since the z-index value can become pretty large (2147483647 if I remember correctly) you most likely will never run out of levels...

The following snippets use some jQuery:

var frontmostWindow = null;
var topZIndex = 10;    

$('div').click(function() {
     if (this != frontmostWindow) {
         frontmostWindow = this;
         topZIndex++;
         $(this).css('zLevel', topZIndex);

         // anything else needed to acticate your div
         // ...
     }
});

If you have restrictions on the z-indices you can use, you will need to re-assign levels every time a different div gets selected, e.g. like this:

// store z-index-ordered divs in an array 
var divs = $('div').toArray().sort(function(a, b) {
     return parseInt($(a).css('zIndex'), 10) - parseInt($(b).css('zIndex'), 10);
});

// store available z-indices
var zIndices = [];
for (var i = 0; i < divs.length; ++i) {
    zIndices.push($(divs[i]).css('zIndex'));
}

// Event listener for clicks
$('div').click(function() {
    alert("heyya " + this.id);
    var element = this;

    var index = divs.indexOf(element);
    // check if clicked element is not already the frontmost
    if (index < divs.length - 1) {
        // remove div from array and insert again at end
        divs.splice(index, 1);
        divs.push(this);

        // re-assign stored z-indices for new div order
        for (var i = 0; i < divs.length; ++i) {
            $(divs[i]).css('zIndex', zIndices[i]);
        }

        // anything else needed to acticate your div
        // ...
    }
});

Upvotes: 0

Luca
Luca

Reputation: 1100

If you don't want to loop through all your divs and don't want to mess up with z-index you can just append again that div to the parent element (the body?) before dragging.

function stepUpNode(elementDragged){
    var parentNode = elementDragged.parentNode;
    parentNode.appendChild(elementDragged);
}

Upvotes: 1

Related Questions