Search code examples
jquery-uijquery-ui-draggablejquery-ui-droppable

Filter drop areas in jQuery drag and drop


I have a list of draggable elements (.item) and drop areas (.droparea).

<div class="sortable">
    <div class="droparea" id="div0">Drop area 0</div>
    <div class="item" id="item1">Item 1</div>
    <div class="droparea" id="div1">Drop area 1</div>
    <div class="item" id="item2">Item 2</div>
    <div class="droparea" id="div2">Drop area 2</div>
    <div class="item" id="item3">Item 3</div>
    <div class="droparea" id="div3">Drop area 3</div>
</div>

My goal is to allow an element to be dropped in drop areas, excluding its surrounding areas (for example, #item1 can be dropped in #div2 and #div3 but not in #div0 and #div1).

I've tried to reject drops with the draggable revert option. Everytime a drop occurs, I compare the current dropping area with the drop areas surrounding the dragged element (stored when dragging begins). If a match occurs, the drop is rejected, else it's accepted.

revert: function(valid)
{
    if(valid) 
    {
        // compare dropping area with forbidden areas
        if(dropped==prevDrop || dropped==nextDrop)
        {
            console.log('invalid drop');
            return true;
        }
        else
        {
            console.log('valid drop ' + dropped.attr('id'));
            return false;
        }
    }
    else
    {
        return true;
    }
}

Fiddle

Unfortunately, it doesn't work: drops are always accepted. Any ideas?


Solution

  • You have done a great work and a minor change is required for actually making this code work ,

    Just change the comparison method in revert to ,

    if(dropped.prop("id")==prevDrop.prop("id") || dropped.prop("id")==nextDrop.prop("id"))
    

    You were using object comparison here, But result of these values when i drop Item1 to div0 ,

    console.log(dropped);
    console.log(prevDrop);
    console.log(nextDrop);
    

    Looks ,

    enter image description here

    It seems using dropped = $(this); in droppable results adding context: div#div0.droparea.ui-droppable which differs from that of draggable. Hence causing the problem in comparison.

    Here is the working fiddle.