Droppable: Changed drop event to loop over a copied array instead of the droppables directly. Fixed #9116 - Droppable: Drop event can cause droppables to remain active if any droppable is created/destroyed in the event handler.

This commit is contained in:
Zaven Muradyan 2013-02-23 21:55:29 -08:00 committed by Scott González
parent e9c04bfa43
commit 1c80735acb
3 changed files with 36 additions and 1 deletions

View File

@ -42,6 +42,7 @@
<div id="draggable1" style="width: 25px; height: 25px;">Draggable</div>
<div id="droppable1" style="width: 100px; height: 100px;">Droppable</div>
<div id="droppable2" style="width: 100px; height: 100px;">Droppable</div>
<div style='width:1000px;height:1000px;'>&nbsp;</div>
</div>

View File

@ -5,6 +5,39 @@
module("droppable: events");
test( "droppable destruction/recreation on drop event", function() {
expect( 1 );
var config = {
activeClass: "active",
drop: function() {
var element = $( this ),
newDroppable = $( "<div>" )
.css({ width: 100, height: 100 })
.text( "Droppable" );
element.after( newDroppable );
element.remove();
newDroppable.droppable( config );
}
},
draggable = $( "#draggable1" ).draggable(),
droppable1 = $( "#droppable1" ).droppable( config ),
droppable2 = $( "#droppable2" ).droppable( config ),
droppableOffset = droppable1.offset(),
draggableOffset = draggable.offset(),
dx = droppableOffset.left - draggableOffset.left,
dy = droppableOffset.top - draggableOffset.top;
draggable.simulate( "drag", {
dx: dx,
dy: dy
});
ok( !droppable2.hasClass( "active" ), "subsequent droppable no longer active" );
});
// this is here to make JSHint pass "unused", and we don't want to
// remove the parameter for when we finally implement
$.noop();

View File

@ -278,7 +278,8 @@ $.ui.ddmanager = {
drop: function(draggable, event) {
var dropped = false;
$.each($.ui.ddmanager.droppables[draggable.options.scope] || [], function() {
// Create a copy of the droppables in case the list changes during the drop (#9116)
$.each(($.ui.ddmanager.droppables[draggable.options.scope] || []).slice(), function() {
if(!this.options) {
return;