Skip to content

Commit efe3b22

Browse files
mgolborgboyone
andauthored
Sortable: Allow 0-height containers to be sortable as in 1.12.1
Note that container specific events will not fire when the dragged element is interacting with zero height containers. Fixes gh-1998 Closes gh-2008 Co-authored-by: A. Wells <[email protected]>
1 parent 85fba3f commit efe3b22

File tree

2 files changed

+110
-64
lines changed

2 files changed

+110
-64
lines changed

tests/unit/sortable/core.js

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,4 +42,57 @@ QUnit.test( "ui-sortable-handle applied to appropriate element", function( asser
4242
assert.equal( el.find( ".ui-sortable-handle" ).length, 0, "class name removed on destroy" );
4343
} );
4444

45+
// gh-1998
46+
QUnit.test( "drag & drop works with a zero-height container", function( assert ) {
47+
var ready = assert.async();
48+
assert.expect( 3 );
49+
50+
var el = $( "<ul class='list-gh-1998'>\n" +
51+
" <style>" +
52+
" .list-gh-1998 {\n" +
53+
" margin: 0;\n" +
54+
" padding: 0;\n" +
55+
" }\n" +
56+
" .list-item-gh-1998 {\n" +
57+
" float: left;\n" +
58+
" display: block;\n" +
59+
" width: 100px;\n" +
60+
" height: 100px;\n" +
61+
" }\n" +
62+
" </style>\n" +
63+
" <li class='list-item-gh-1998'>Item 1</li>\n" +
64+
" <li class='list-item-gh-1998'>Item 2</li>\n" +
65+
" <li class='list-item-gh-1998'>Item 3</li>\n" +
66+
"</ul>" )
67+
.sortable()
68+
.appendTo( "#qunit-fixture" );
69+
70+
function step1() {
71+
el.find( "li" ).eq( 0 ).simulate( "drag", {
72+
dx: 100,
73+
dy: 3,
74+
moves: 3
75+
} );
76+
setTimeout( step2 );
77+
}
78+
79+
function step2() {
80+
el.find( "li" ).eq( 2 ).simulate( "drag", {
81+
dx: -200,
82+
dy: -3,
83+
moves: 3
84+
} );
85+
setTimeout( step3 );
86+
}
87+
88+
function step3() {
89+
assert.equal( el.find( "li" ).eq( 0 ).text(), "Item 3" );
90+
assert.equal( el.find( "li" ).eq( 1 ).text(), "Item 2" );
91+
assert.equal( el.find( "li" ).eq( 2 ).text(), "Item 1" );
92+
ready();
93+
}
94+
95+
step1();
96+
} );
97+
4598
} );

ui/widgets/sortable.js

Lines changed: 57 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -421,79 +421,76 @@ return $.widget( "ui.sortable", $.ui.mouse, {
421421
this.helper[ 0 ].style.top = this.position.top + "px";
422422
}
423423

424-
//Post events to containers
425-
this._contactContainers( event );
426-
427-
if ( this.innermostContainer !== null ) {
428-
429-
//Do scrolling
430-
if ( o.scroll ) {
431-
if ( this._scroll( event ) !== false ) {
424+
//Do scrolling
425+
if ( o.scroll ) {
426+
if ( this._scroll( event ) !== false ) {
432427

433-
//Update item positions used in position checks
434-
this._refreshItemPositions( true );
428+
//Update item positions used in position checks
429+
this._refreshItemPositions( true );
435430

436-
if ( $.ui.ddmanager && !o.dropBehaviour ) {
437-
$.ui.ddmanager.prepareOffsets( this, event );
438-
}
431+
if ( $.ui.ddmanager && !o.dropBehaviour ) {
432+
$.ui.ddmanager.prepareOffsets( this, event );
439433
}
440434
}
435+
}
441436

442-
this.dragDirection = {
443-
vertical: this._getDragVerticalDirection(),
444-
horizontal: this._getDragHorizontalDirection()
445-
};
446-
447-
//Rearrange
448-
for ( i = this.items.length - 1; i >= 0; i-- ) {
449-
450-
//Cache variables and intersection, continue if no intersection
451-
item = this.items[ i ];
452-
itemElement = item.item[ 0 ];
453-
intersection = this._intersectsWithPointer( item );
454-
if ( !intersection ) {
455-
continue;
456-
}
457-
458-
// Only put the placeholder inside the current Container, skip all
459-
// items from other containers. This works because when moving
460-
// an item from one container to another the
461-
// currentContainer is switched before the placeholder is moved.
462-
//
463-
// Without this, moving items in "sub-sortables" can cause
464-
// the placeholder to jitter between the outer and inner container.
465-
if ( item.instance !== this.currentContainer ) {
466-
continue;
467-
}
437+
this.dragDirection = {
438+
vertical: this._getDragVerticalDirection(),
439+
horizontal: this._getDragHorizontalDirection()
440+
};
468441

469-
// Cannot intersect with itself
470-
// no useless actions that have been done before
471-
// no action if the item moved is the parent of the item checked
472-
if ( itemElement !== this.currentItem[ 0 ] &&
473-
this.placeholder[ intersection === 1 ?
474-
"next" : "prev" ]()[ 0 ] !== itemElement &&
475-
!$.contains( this.placeholder[ 0 ], itemElement ) &&
476-
( this.options.type === "semi-dynamic" ?
477-
!$.contains( this.element[ 0 ], itemElement ) :
478-
true
479-
)
480-
) {
442+
//Rearrange
443+
for ( i = this.items.length - 1; i >= 0; i-- ) {
481444

482-
this.direction = intersection === 1 ? "down" : "up";
445+
//Cache variables and intersection, continue if no intersection
446+
item = this.items[ i ];
447+
itemElement = item.item[ 0 ];
448+
intersection = this._intersectsWithPointer( item );
449+
if ( !intersection ) {
450+
continue;
451+
}
483452

484-
if ( this.options.tolerance === "pointer" ||
485-
this._intersectsWithSides( item ) ) {
486-
this._rearrange( event, item );
487-
} else {
488-
break;
489-
}
453+
// Only put the placeholder inside the current Container, skip all
454+
// items from other containers. This works because when moving
455+
// an item from one container to another the
456+
// currentContainer is switched before the placeholder is moved.
457+
//
458+
// Without this, moving items in "sub-sortables" can cause
459+
// the placeholder to jitter between the outer and inner container.
460+
if ( item.instance !== this.currentContainer ) {
461+
continue;
462+
}
490463

491-
this._trigger( "change", event, this._uiHash() );
464+
// Cannot intersect with itself
465+
// no useless actions that have been done before
466+
// no action if the item moved is the parent of the item checked
467+
if ( itemElement !== this.currentItem[ 0 ] &&
468+
this.placeholder[ intersection === 1 ?
469+
"next" : "prev" ]()[ 0 ] !== itemElement &&
470+
!$.contains( this.placeholder[ 0 ], itemElement ) &&
471+
( this.options.type === "semi-dynamic" ?
472+
!$.contains( this.element[ 0 ], itemElement ) :
473+
true
474+
)
475+
) {
476+
477+
this.direction = intersection === 1 ? "down" : "up";
478+
479+
if ( this.options.tolerance === "pointer" ||
480+
this._intersectsWithSides( item ) ) {
481+
this._rearrange( event, item );
482+
} else {
492483
break;
493484
}
485+
486+
this._trigger( "change", event, this._uiHash() );
487+
break;
494488
}
495489
}
496490

491+
//Post events to containers
492+
this._contactContainers( event );
493+
497494
//Interconnect with droppables
498495
if ( $.ui.ddmanager ) {
499496
$.ui.ddmanager.drag( this, event );
@@ -888,9 +885,7 @@ return $.widget( "ui.sortable", $.ui.mouse, {
888885
this.options.axis === "x" || this._isFloating( this.items[ 0 ].item ) :
889886
false;
890887

891-
if ( this.innermostContainer !== null ) {
892-
this._refreshItemPositions( fast );
893-
}
888+
this._refreshItemPositions( fast );
894889

895890
var i, p;
896891

@@ -1038,8 +1033,6 @@ return $.widget( "ui.sortable", $.ui.mouse, {
10381033

10391034
}
10401035

1041-
this.innermostContainer = innermostContainer;
1042-
10431036
// If no intersecting containers found, return
10441037
if ( !innermostContainer ) {
10451038
return;

0 commit comments

Comments
 (0)