Skip to main content

Search and Top Navigation

#13024 new bug ()

Opened June 05, 2015 12:54PM UTC

Last modified September 29, 2016 10:31AM UTC

draggable with connectToSortable not compatible with clone helper

Reported by: esion Owned by:
Priority: minor Milestone: none
Component: ui.sortable Version: 1.11.4
Keywords: Cc:
Blocked by: Blocking:

The dragged item is not removed from DOM when sortable use helper clone

how to reproduce :

1. Move an item from 3rd list (draggable) to any position

2. move an item from 1rst list to the second one

the old item is frozen in front at the place it was dropped

''Note: 1rst & 2 nd list are sortables but I also see it on a droppable''

the config used in plnkr :

$(function() {
  $( "#sortable1, #sortable2" ).sortable({
    connectWith: ".connected",
    helper: "clone",
  $("#clonnable1 li").draggable({
    connectToSortable: "#sortable1, #sortable2"

This is due to : sortable.cancelHelperRemoval = true in "stop" callback :

Attachments (0)
Change History (4)

Changed June 05, 2015 01:05PM UTC by esion comment:1

Changed September 16, 2015 08:44PM UTC by scottgonzalez comment:2

component: ui.coreui.sortable

Changed October 07, 2015 09:18AM UTC by jcano comment:3

Is there any progress on this? I can confirm this is happening:

Same steps to reproduce:

1. Drag from the first list (draggable) to any of the sortables

2. Drag from the other sortable to the first sortable.

The helper is not removed, it stays visible at the last position before releasing the mouse button. This is due to how draggable manages dropping on a connected sortable. It sets the variable

to true on the sortable but never returns the value to false, so the sortable from that point on will never remove helpers.

Changed September 29, 2016 10:31AM UTC by matt-hoskins comment:4

This bug is still present in 1.12.1 - I've just hit this same bug myself. I've updated the jsfiddle from jcano to reference 1.12.1:

The cause is still the same.

The issue was introduced in 1.11.2 as a side effect of this commit:

However I don't understand what this setting "this.instance.cancelHelperRemoval = true" is actually achieving (other than introducing this bug). This particular piece of code is called in cases where "sortable.isOver" is not true - which I presume means that the draggable isn't within this connected sortable at this point? In which case even if this draggable had entered that sortable at some point, it must have exited it already and thus connectToSortable's drag event would have already called _mouseStop on the sortable (and _mouseStop is the only place for sortable where cancelHelperRemoval on the sortable is used). The next line after setting this.instance.cancelHelperRemoval = true is to trigger "deactivate" on the sortable which, as far as I can tell, doesn't result in a call on _mouseStop (and _mouseStop won't be called on that sortable because isOver is not true).

The comment in the code says "Prevent this Sortable from removing the helper" - as per my reading of the code noted above I don't believe a sortable with isOver not being true will remove the helper because it's not due to have _mouseStop called by this point.

I believe that cancelHelperRemoval on the sortable is purely for use by connectToSortable's drag, when the draggable is dragged out of a sortable, to signal to that sortable's _mouseStop code that it shouldn't remove the helper (because the drag is still in progress of course). I think the code in connectToSortable's ".stop" to set cancelHelperRemoval is purely to clean up any cancelHelperRemoval values left to true. What should probably happen really is that after connecToSortable's ".drag" calls sortable._mouseStop it should then revert sortable.cancelHelperRemoval back to false to clean up after itself as, as far as I can tell, it doesn't need to be left set to true. If ".drag" did reset cancelHelperRemoval back to false then ".stop" for connectToSortable doesn't need to touch cancelHelperRemoval at all on the sortables - if sortable.isOver is true then the current code allows the sortable to do the helper removal so it can be left as false, and on ones where isOver is false then _mouseStop isn't going to be called on them so they're not going to try remove the helper anyway.

Of course I'm no expert in jqueryui code, this is just me trying to piece together what happens, so maybe I've made a mistake :).