From ffab89e9bee97cf7cc74249b6e4ce9dd798013c9 Mon Sep 17 00:00:00 2001 From: Andrei Picus Date: Tue, 29 Oct 2013 15:48:51 +0200 Subject: [PATCH] Droppable: update ddmanager when scope changes through setOption. Fixed #9287 - droppable: Scope option cannot be changed after initialization. --- tests/unit/droppable/droppable_options.js | 46 +++++++++++++++++++++-- ui/jquery.ui.droppable.js | 26 ++++++++++--- 2 files changed, 62 insertions(+), 10 deletions(-) diff --git a/tests/unit/droppable/droppable_options.js b/tests/unit/droppable/droppable_options.js index c2ecdcfda..1d8f95da9 100644 --- a/tests/unit/droppable/droppable_options.js +++ b/tests/unit/droppable/droppable_options.js @@ -35,6 +35,48 @@ test("{ addClasses: false }", function() { ok(!el.is(".ui-droppable"), "'ui-droppable' class not added"); el.droppable("destroy"); }); + +test( "scope", function() { + expect( 4 ); + var droppableOffset, draggableOffset, oldDraggableOffset, dx, dy, + draggable1 = $("
").appendTo( "#qunit-fixture" ).draggable({ revert: "invalid" }), + draggable2 = $("
").appendTo( "#qunit-fixture" ).droppable(), + droppable = $("
").appendTo( "#qunit-fixture" ).droppable(), + newScope = "test"; + + draggable1.draggable( "option", "scope", newScope ); + droppable.droppable( "option", "scope", newScope ); + + // Test that droppable accepts draggable with new scope. + droppableOffset = droppable.offset(); + draggableOffset = draggable1.offset(); + dx = droppableOffset.left - draggableOffset.left; + dy = droppableOffset.top - draggableOffset.top; + + draggable1.simulate( "drag", { + dx: dx, + dy: dy + }); + + draggableOffset = draggable1.offset(); + equal( draggableOffset.left, droppableOffset.left ); + equal( draggableOffset.top, droppableOffset.top ); + + // Test that droppable doesn't accept draggable with old scope. + draggableOffset = draggable2.offset(); + dx = droppableOffset.left - draggableOffset.left; + dy = droppableOffset.top - draggableOffset.top; + oldDraggableOffset = draggableOffset; + + draggable2.simulate( "drag", { + dx: dx, + dy: dy + }); + + draggableOffset = draggable2.offset(); + equal( draggableOffset.left, oldDraggableOffset.left ); + equal( draggableOffset.top, oldDraggableOffset.top ); +}); /* test("greedy", function() { ok(false, 'missing test - untested code is broken code'); @@ -44,10 +86,6 @@ test("hoverClass", function() { ok(false, 'missing test - untested code is broken code'); }); -test("scope", function() { - ok(false, 'missing test - untested code is broken code'); -}); - test("tolerance, fit", function() { ok(false, 'missing test - untested code is broken code'); }); diff --git a/ui/jquery.ui.droppable.js b/ui/jquery.ui.droppable.js index d21d1790a..0e4b65cc4 100644 --- a/ui/jquery.ui.droppable.js +++ b/ui/jquery.ui.droppable.js @@ -63,23 +63,31 @@ $.widget( "ui.droppable", { } }; - // Add the reference and positions to the manager - $.ui.ddmanager.droppables[ o.scope ] = $.ui.ddmanager.droppables[ o.scope ] || []; - $.ui.ddmanager.droppables[ o.scope ].push( this ); + this._addToManager( o.scope ); o.addClasses && this.element.addClass( "ui-droppable" ); }, - _destroy: function() { - var i = 0, - drop = $.ui.ddmanager.droppables[ this.options.scope ]; + _addToManager: function( scope ) { + // Add the reference and positions to the manager + $.ui.ddmanager.droppables[ scope ] = $.ui.ddmanager.droppables[ scope ] || []; + $.ui.ddmanager.droppables[ scope ].push( this ); + }, + _splice: function( drop ) { + var i = 0; for ( ; i < drop.length; i++ ) { if ( drop[ i ] === this ) { drop.splice( i, 1 ); } } + }, + + _destroy: function() { + var drop = $.ui.ddmanager.droppables[ this.options.scope ]; + + this._splice( drop ); this.element.removeClass( "ui-droppable ui-droppable-disabled" ); }, @@ -90,7 +98,13 @@ $.widget( "ui.droppable", { this.accept = $.isFunction( value ) ? value : function( d ) { return d.is( value ); }; + } else if ( key === "scope" ) { + var drop = $.ui.ddmanager.droppables[ this.options.scope ]; + + this._splice( drop ); + this._addToManager( value ); } + this._super( key, value ); },