Reputation: 5974
I have a list of draggables than can be dropped inside a droppable and when this happens, the draggables are cloned and converted to droppables.
This new droppables are greedy but when they receive a draggable, both drop events are fired (the drop event from the draggable and the drop event from the droppable area)
What I'm doing wrong? I need the event to fire only once (from the new droppable)
Here's a fiddle: drag and drop an item into the red area, then drag another item and drop it into the item you already dropped. See the console log.
HTML
<div id="main_droppable"></div>
<ul>
<li class="item" data-id="1">1</li>
<li class="item" data-id="2">2</li>
<li class="item" data-id="3">3</li>
<li class="item" data-id="4">4</li>
<li class="item" data-id="5">5</li>
</ul>
JS
$(".item").data("active", false);
$(".item").draggable({
helper: "clone",
appendTo: "#main_droppable",
scroll: false,
start: function(event, ui)
{
if($(this).data("active") == false)
{
$(this).fadeTo(100, 0.2);
}
else
{
return false;
}
},
revert: function(is_valid_drop)
{
if(!is_valid_drop)
{
$(this).fadeTo(100, 1).data("active", false);
return true;
}
else
{
$(this).data("active", true);
}
}
});
$("#main_droppable").droppable({
drop: function(event, ui)
{
console.log("drop main");
addNewItem(ui.helper);
return false;
}
});
function addNewItem($oldItem)
{
var $newItem = $oldItem.clone(false).fadeTo(100, 1).data("active", true);
$oldItem.remove();
$newItem.draggable({
containment: "parent",
});
$newItem.droppable({
greedy: true,
drop: function(event, ui)
{
console.log("drop item");
$(this).fadeTo(100, 0, function()
{
var $originalItem = $("ul").find(".item[data-id=" + $(this).data("id") + "]");
$originalItem.fadeTo(100, 1).data("active", false);
$("#main_droppable").find(".item[data-id=" + $originalItem.data("id") + "]").remove();
});
addNewItem(ui.helper);
}
});
$("#main_droppable").append($newItem);
}
CSS
#main_droppable
{
border: 1px solid red;
min-height: 50px;
}
.item
{
display: inline-block;
border: 1px solid blue;
width: 25px;
height: 25px;
}
Upvotes: 3
Views: 431
Reputation: 5974
Well...it had to do with a particular class...
When I dropped the draggable and cloned it, the ui-draggable-dragging
class stayed in place. So in order to make it work I had to remove it, then everything worked as expected.
I change this line:
var $newItem = $oldItem.clone(false).fadeTo(100, 1).data("active", true);
Into this one:
var $newItem = $oldItem.clone(false).fadeTo(100, 1).data("active", true).removeClass("ui-draggable-dragging");
updated fiddle: https://jsfiddle.net/3118zjg1/1/
Upvotes: 2
Reputation: 1179
I think the dragables actually become greedy but the #main_droppable
event still gets triggered because:
When you place another .item
element on top of another, the intended action for dropping a .item
into another .item
gets triggered.
$newItem.droppable({
greedy: true,
drop: function(event, ui)
{
console.log("drop item");
...
but this original element gets removed further down the code anyway..
$(this).fadeTo(100, 0, function()
{
var $originalItem = $("ul").find(".item[data-id=" + $(this).data("id") + "]");
$originalItem.fadeTo(100, 1).data("active", false);
$("#main_droppable").find(".item[data-id=" + $originalItem.data("id") + "]").remove();
...
You're effectively replacing the original item with the new one hence the #main_droppable
event getting triggered.
I can't say I know how to fix the unintentional side effect without changing your intended behaviour, but hopefully you have a better clue as to why the greedy
attribute seems to not work.
Upvotes: -1