Restrict jQuery draggable items from overlapping/colliding with sibling elements

22,092

Solution 1

Edit: New Solution

I found a plugin for this called JQuery UI Draggable Collision. Using this, implementing your desired functionality becomes trivial. See the following jsFiddle example: http://jsfiddle.net/q3x8w03y/1/ (This uses version 1.0.2 of JQuery UI Draggable Collision, along with JQuery 1.7.2 and JQueryUI 1.1.18.)

Here is the code:

$("#dragMe").draggable({
    obstacle: "#butNotHere",
    preventCollision: true,
    containment: "#moveInHere"
});

Old Solution

The following should work. It has a glitch, though. Once the divs collide, you have to "regrab" the div you are dragging, which can be a little annoying. Perhaps someone else will know how to fix this this. You can see my jsFiddle example here: http://jsfiddle.net/MrAdE/8/

var prevOffset, curOffset;
$("#dragMe").draggable({
    drag: function(e,ui) {
        prevOffset= curOffset;
        curOffset= $.extend({},ui.offset);
        return true;
    }
});

$("#butNotHere").droppable({
    greedy: true,
    over: function(e,ui) {
        ui.helper.offset(curOffset= prevOffset).trigger("mouseup");
    },
    tolerance: "touch"
});​

Solution 2

This took me quite a bit of fiddling. Basically I created a droppable on the element you want to avoid, then set a boolean when the drag is over it. I then use that in an undocumented revert function override to cancel the drop. It only works if #dragMe is fully over #butNotHere:

$(document).ready(function(){
    var shouldCancel = false;
    $('#dragMe').draggable({
        containment: '#moveInHere',
        revert: function(){
            if (shouldCancel) {
                shouldCancel = false;
                return true;
            } else {
                return false;
            }
        }
    });
    $('#butNotHere').droppable({
        over: function(){
            shouldCancel = true;
        },
        out: function(){
            shouldCancel = false;
        }
    });
});

Check out the working demo and feel free to play with it: http://jsfiddle.net/H59Nb/31/

Share:
22,092
vaclav_o
Author by

vaclav_o

Updated on December 22, 2020

Comments

  • vaclav_o
    vaclav_o over 3 years

    I need to use jQuery UI to restrict the containment area for draggable object with some additional restriction. I need prevent the draggable element from overlapping with other elements within the same container. I need to allow movement in "moveInHere" area but not "butNotHere" area. Is it possible?

    <div id="moveInHere">
    
        <div id="dragMe"> </div>
    
        <div id="butNotHere"> </div>
    
    </div>
    
    
    <script type="text/javascript">
    
        $("#dragMe").draggable({
            containment: "#moveInHere"
        });
    
    </script>
    
  • TJ VanToll
    TJ VanToll almost 12 years
    +1 Clever to use droppable's over event to trigger a mouseup.
  • THE JOATMON
    THE JOATMON almost 11 years
    Do you know if your new solution is compatible with JQuery 1.10? I'm getting errors.
  • Kukeltje
    Kukeltje over 8 years
    This jsfiddle does not work anymore. Answer should be updated with the details of versions etc
  • ihake
    ihake over 8 years
    @Kukeltje JSFiddle removed the third party files I'd uploaded for the example. Looks like you can't upload third part files any more, so I embedded them in the JavaScript section. Here's the new example: jsfiddle.net/q3x8w03y/1 I'll update the answer with versions.
  • Daniel Kobe
    Daniel Kobe about 8 years
    New solution will not work with jQuery UI 1.10 and greater
  • Amar Singh
    Amar Singh almost 8 years
    in old solution ,, is there anything we can do in out method ......because it stucks after it touches the obstacle