34

I am trying to set the z-index on draggable elements using jQuery. You can see what I am talking about and what I have so far here:

http://jsfiddle.net/sushik/LQ4JT/1/

It is very primitive and there are problems with it. Any ideas on how I would make the last clicked element have the highest z-index and rather than resetting all of the rest to a base z-index, have them step, so the 2nd to last clicked has the second highest z-index, etc..

Another problem I am having with it is that it only works on a full click event but the draggable functionality works by clicking and holding down. How could I have the class applied on that initial click down and not wait for the event of releasing the click?

Hussein
  • 42,480
  • 25
  • 113
  • 143
Zac
  • 12,637
  • 21
  • 74
  • 122

6 Answers6

58

All you need to do is use draggable({stack: "div"}) Now when you drag a div it will automatically come to the top.

Check working example at http://jsfiddle.net/LQ4JT/8/

Hussein
  • 42,480
  • 25
  • 113
  • 143
  • but this will work only when dragging, not on clicking. right? – Mahesh Mar 07 '11 at 09:15
  • 1
    You have to drag it for stacking to work. That's the whole point behind dragging stack. If z-index is done by clicking then it can get really annoying specially when you have other behaviors binded to a click but don't want to bring the div to front. All you have to do with when using stack is drag the div 1 pixel and it will bring it to the front. – Hussein Mar 07 '11 at 09:30
  • Yes. But actually we need both the functionality. If this feature exists then it will be nice in Jquery UI. I have requested this feature to the Jquery UI dev team. Hope someday this will be there. draggable({stack: "div", stackOption: "both"}) – Mahesh Mar 07 '11 at 10:02
  • hmm... i just got mail from Jquery UI dev team. In jquery-ui-1.9 even "stack" option will be removed. – Mahesh Mar 07 '11 at 13:07
  • any reason why they will be removing it in 1.9. – Hussein Mar 07 '11 at 18:10
  • this is the response i got from the team. "Because it's not a core feature. We're redesigning the API for all existing plugins to regain sanity in their APIs. We're trying to simplify the APIs, not complicate them." – Mahesh Mar 08 '11 at 06:07
  • I don't understand how that's not core functionality. – Adam Grant Aug 03 '12 at 13:50
  • I noticed in version [jQuery UI Draggable 1.8.11] they have a zIndex option so that will also work. – Andre Oct 04 '12 at 23:33
  • 2
    I can confirm that "stack" is still working in 1.11. Currently using it. – razorsyntax Nov 26 '14 at 22:40
  • 2
    In response to the question of making elements also snap to front on click without drag, simply include this additional parameter: `distance: 0` – Keyslinger Apr 14 '15 at 04:01
27

I have updated your CSS and Javascript. Don't use "!important" in css unless you are that much desperate.

http://jsfiddle.net/LQ4JT/7/

    $(document).ready(function() {
        var a = 3;
        $('#box1,#box2,#box3,#box4').draggable({
            start: function(event, ui) { $(this).css("z-index", a++); }
        });
    $('#dragZone div').click(function() {
        $(this).addClass('top').removeClass('bottom');
        $(this).siblings().removeClass('top').addClass('bottom');
        $(this).css("z-index", a++);
    });

});​

Though this answer works it has the limitation of max number of 2^31−1 in javascript. refer What is JavaScript's highest integer value that a Number can go to without losing precision? for more info.

Community
  • 1
  • 1
Mahesh
  • 2,186
  • 16
  • 17
7

The easiest way I found to solve this problem was to use the appendTo and zIndex options.

$('#box1,#box2,#box3,#box4').draggable({
  appendTo: "body",
  zIndex: 10000
});
Caedmon
  • 667
  • 7
  • 11
6

Following code will fulfill your requirements. You need to stack your divs instead of setting z-indexes and secondly you need to show the div at top after simply clicking it not dragging it.

So for stacking you need stack: "div" and for showing the div element on the top by simply click, you need to use distance: 0.

By default the value is distance: 10 which means until you don't drag it 10 pixels, it won't show up on the top. By setting the value to distance: 0 makes it show on the top after a simple click.

Try the following code.

$('#box1,#box2,#box3,#box4').draggable({
    stack: "div",
    distance: 0
});

Working JSFiddle Here.


Edit:

Click the Run code snippet button below to execute this embedded code snippet.

$(document).ready(function() {

  $('#box1,#box2,#box3,#box4').draggable({
    stack: "div",
    distance: 0
  });

  $('#dragZone div').click(function() {
    $(this).addClass('top').removeClass('bottom');
    $(this).siblings().removeClass('top').addClass('bottom');

  });
});
#box1 {
  width: 150px;
  height: 150px;
  background-color: red;
  position: absolute;
  top: 0px;
  left: 0px;
  z-index: 0
}

#box2 {
  width: 150px;
  height: 150px;
  background-color: green;
  position: absolute;
  top: 20px;
  left: 50px;
  z-index: 0
}

#box3 {
  width: 150px;
  height: 150px;
  background-color: yellow;
  position: absolute;
  top: 50px;
  left: 100px;
  z-index: 0
}

#box4 {
  width: 150px;
  height: 150px;
  background-color: blue;
  position: absolute;
  top: 70px;
  left: 200px;
  z-index: 0
}

.top {
  z-index: 100!important;
  position: relative
}

.bottom {
  z-index: 10!important;
  position: relative
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
<script src="http://code.jquery.com/ui/1.12.1/jquery-ui.min.js"></script>

<div id="dragZone">
  <div id="box1"></div>
  <div id="box2"></div>
  <div id="box3"></div>
  <div id="box4"></div>
</div>
Community
  • 1
  • 1
Suhaib Janjua
  • 3,538
  • 16
  • 59
  • 73
1

Stack: "div" work on groups of elements too

<style media="screen">
    .box {width: 150px; height: 150px; position: absolute;  z-index: 0;}
    .box:nth-child(1) {background-color: red; top: 0px; left: 0px;}
    .box:nth-child(2) {background-color: green; top: 20px; left: 50px;}
    .box:nth-child(3) {background-color: yellow; top: 50px; left: 100px;}
    .box:nth-child(4) {background-color: blue; top: 80px; left: 150px;}
</style>
<script type="text/javascript">
    $(document).ready(function() {
        $('.box').draggable({stack: "div"});
    });
</script>
<div id="dragZone">
    <div class="box" id="box1"></div>
    <div class="box" id="box2"></div>
    <div class="box" id="box3"></div>
    <div class="box" id="box4"></div>
</div>
James Cole
  • 11
  • 1
0

Here is a greatly simplified version of Mahesh's answer:

$(document).ready(function() {
  var a = 1;
  $('#box1,#box2,#box3,#box4,#box5,#box6,#box7').draggable({
    start: function(event, ui) { $(this).css("z-index", a++); }
  });
});

http://jsfiddle.net/LQ4JT/713/

Still seems to work well, unless I am missing something.

Jehan
  • 2,701
  • 2
  • 23
  • 28
  • That works when dragging the element, but not simply clicking it. Mahesh's answer is more complete. – pmont Jan 15 '14 at 16:07