Prevent drop event to propagate to the parent if an inner droppable does not accept the draggable
I have a droppable div#space
and a collection of draggable li.element
. When I drag an li.element
in the div#space
a new ul.group
is created, the li.element
is appended to the ul.group
and finally the ul.group
is made droppable.
Given
I would like these elements to behave as follows:
- when an
li.element
is dropped in theul.group
that does not contain it, theli.element
will be added to theul.group
- when an
li.element
is dropped 开发者_如何学运维in theul.group
that does contain it, theli.element
will be reverted to it's original position - when an
li.element
is dropped in thediv#space
(outside aul.group
) an new group is created as mentioned above.
The problem is that when an element is dropped on an ul.group
that does not accept it the parent div#space
will catch the event and will create a new group.
The ul.grpup
has an accept function that checks if the droppable is an element and if it's not already been dropped.
newULGroup.droppable({
drop: ...
accept: function(ui)
{
var isElement = ui.hasClass('element')
var elementId = '.' + ui.data().id
var isAlreadyPresent = $(this).find(elementId).length > 0
return isElement && (!isAlreadyPresent)
},
greedy: true
});
How would you implement this behaviour if not by accepting everything and ignoring things in the drop handler? (I haven't tried but I guess that would work)
Edit
An attempt to fix it
I patched the jquery-ui-1.8.4.js to pass the event to the accept function. Now I can stop the propagation with $(event).stopPropagation()
, but I have to animate manually the draggable helper back to its original position to simulate the revert, then remove it from the dom.
accept: function(ui, event)
{
var isCriteria = ui.hasClass('criteria')
var criteriaId = '.' + ui.data().id
var isAlreadyPresent = $(this).find(criteriaId).length > 0
var accepted = isCriteria && (!isAlreadyPresent)
if (event && !accepted)
{
$(event.target).animate(ui.offset(), {complete: function() {$(this).remove()}})
$(event).stopPropagation()
}
return accepted
}
Unfortunately it seems to destroy the draggable behaviour from the original element as well. Why, oh why?
I managed to achieve similar behavior, although using undocumented jQuery.ui feature.
If you look into the jquery.ui.draggable
implementation (at least for v1.8.16) the revert
option can also be a function. It has this
being the draggable element, single parameter which is the droppable who accepted the drop, and return value is a boolean
to indicate whether to revert the draggable or not.
So in your case you need to
- have your
div#space
andul.group
always accept drops and be greedy - do the check in the ul.group
drop
handler and processes item only if it's not in the group yet - do similar check in the draggable
revert
function and revert itself if it's already in the group.
精彩评论