Search code examples
jqueryjquery-uidraggabledroppable

Ui draggable overlay


I need that at the back droppable container would not react if you put dragable on the one which is on the top. http://jsfiddle.net/rA4CB/161/

Hy guys I have been working on a project for some time already and I just now sow this problem and it is realy killing whole project. I cant change structure of this so I was wondering maybe you guys know any "magic trick" to fix this issue.

<div id="draggable" class="ui-widget-content">
    <p>Drag me to my target</p>
</div>

<div class="droppable" class="ui-widget-header droppable">
    <p>Drop here</p>
</div>
<div class="droppable2" class="ui-widget-header droppable">
    <p>Drop here</p>
</div>
$(function() {


$("#draggable").draggable();
  $(".droppable,.droppable2").droppable({
    tolerance: 'pointer',
    drop: function(event, ui) {
      $(this)
        .addClass("ui-state-highlight")
        .find("p")
        .html("Dropped!");
    }
  });
});

extra info: droppable and droppable2 have to work even z-index will be changed. For example droppable is on the top of droppable2 or opposite. Here you can see z-index problem with 2 droppable functions instead of one. Link

Any help would be great !!! thanks in advance.


Solution

  • You can use over and out event on the top one to disable the one on the back. Something like this:

    $(function() {
      $("#draggable").draggable();
      $(".droppable").droppable({
        tolerance: 'pointer',
        drop: function(event, ui) {
          $(this)
            .addClass("ui-state-highlight")
            .find("p")
            .html("Dropped!");
        }
      });
      $(".droppable2").droppable({
        tolerance: 'pointer',
        drop: function(event, ui) {
          $(this)
            .addClass("ui-state-highlight")
            .find("p")
            .html("Dropped!");
        },
        over: function(event, ui) {
          $(".droppable").droppable("disable")
        },
        out: function(event, ui) {
          $(".droppable").droppable("enable")
        }
      });
    });
    

    Note that if you don't want visual feedback on disable, you'll need to change the CSS for disabled-state.

    http://jsfiddle.net/wppykb9a/2/

    If you want it to work with z-index, it's a bit more complex, but one method you could use is document.elementFromPoint(). It returns the top most element at a specific point, so on drop you can put the draggable behind, then check which droppable is the highest at the drop point. Like this:

    $(function() {
      window.a = 10;
    
      $(".droppable,.droppable2").draggable();
    
      $("#draggable").draggable({
        tolerance: 'pointer'
      });
      $(".droppable").droppable({
        accept: "#draggable",
        drop: function(event, ui) {
            var temp = ui.draggable.zIndex();
            ui.draggable.css('z-index', -1000);
            var topDroppable = document.elementFromPoint(event.clientX, event.clientY);
          ui.draggable.css('z-index', temp);
          $(topDroppable)
            .addClass("ui-state-highlight")
            .find("p")
            .html("Dropped!");
        }
      });
    });
    

    http://jsfiddle.net/17xn0zvz/

    see https://developer.mozilla.org/en-US/docs/Web/API/Document/elementFromPoint