Opened 13 years ago
Last modified 5 years ago
#6259 open bug
Droppable: drop event incorrectly triggered when dragging a draggable over a droppable onto a sortable
Reported by: | avuori | Owned by: | |
---|---|---|---|
Priority: | minor | Milestone: | 2.0.0 |
Component: | ui.droppable | Version: | 1.8.6 |
Keywords: | Cc: | avuori | |
Blocked by: | Blocking: |
Description
When a draggable is connected with a sortable, and there is also a droppable involved, the droppable's drop event is erroneously triggered when the draggable is dragged quickly over the droppable (without ever releasing the mouse).
The example demonstrates the problem. It may not be reproducible instantly, but a few down/up drag movements should do it. An alert is shown when the droppable event is triggered.
The problem seems to be present only when the draggeble's helper is "clone".
<html> <head> <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.js" type="text/javascript"></script> <script src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.6/jquery-ui.js"></script> </head> <body> <script> $(function() { $("tbody.sortable").sortable({}); $(".draggable").draggable({ helper: "clone", connectToSortable: "tbody.sortable" }); $(".droppable") .droppable({drop: function () { alert("dropped"); } }); $("td").disableSelection(); }); </script> <table> <tbody> <tr class="draggable ui-state-highlight"><td>Drag me down above the sortable, then quickly drag me up directly over and past the droppable</td></tr> <tr class="droppable ui-state-highlight"><td>Droppable</td></tr> </tbody> <tbody class="sortable"> <tr class="ui-state-default"><td>Item 1</td></tr> <tr class="ui-state-default"><td>Item 2</td></tr> <tr class="ui-state-default"><td>Item 3</td></tr> <tr class="ui-state-default"><td>Item 4</td></tr> <tr class="ui-state-default"><td>Item 5</td></tr> </tbody> </table> </body> </html>
Attachments (1)
Change History (14)
Changed 13 years ago by
Attachment: | example.html added |
---|
comment:1 Changed 13 years ago by
comment:2 Changed 13 years ago by
I had the same issue on my site with very different markup. Was also using clone.
comment:3 follow-up: 4 Changed 13 years ago by
$(".droppable") .droppable({drop: function () { if (!$(event.srcElement).hasClass("ui-draggable-dragging")) { return; } alert("dropped"); } });
will be solve your problem
comment:4 Changed 13 years ago by
comment:5 Changed 11 years ago by
Milestone: | TBD → 2.0.0 |
---|
comment:6 Changed 11 years ago by
Status: | new → open |
---|---|
Summary: | Droppable's drop event triggered when dragging a draggable over the droppable → Droppable: drop event incorrectly triggered when dragging a draggable over a droppable onto a sortable |
confirmed on latest: http://jsfiddle.net/2aJh9/
comment:7 Changed 10 years ago by
Because I needed the droppable to be droppable I fixed it by handling the drop event in the draggable:
var draggableOnDroppable; .droppable({ over: function(event,ui) { draggableOnDroppable = true; }, out: function(event, ui) { draggableOnDroppable = false; }); .draggable({ stop: function (event, ui) { if (draggableOnDroppable) //do something with draggable } });
comment:8 Changed 10 years ago by
Is there a known workaround? Is there an alternative to using clone helper?
comment:9 Changed 10 years ago by
Is there a known workaround?
Is there an alternative to using clone helper?
comment:10 follow-up: 11 Changed 10 years ago by
Hello, the solution is simple. The drop can't be effective if you don't release the left mouse, so just detect the state of it, and bloc any action in droppable if you don't have left mouse released :
var leftButtonDown; $(document).mousedown(function(e){ if(e.which === 1) leftButtonDown = true; }); $(document).mouseup(function(e){ if(e.which === 1) leftButtonDown = false; }); .droppable({ drop:function(e,ui){ if(leftButtonDown) return false; // Here code when really drop });
comment:11 Changed 9 years ago by
Replying to paulf66:
Hello, the solution is simple. The drop can't be effective if you don't release the left mouse, so just detect the state of it, and bloc any action in droppable if you don't have left mouse released :
...
This work-around works perfectly for FF & Chrome but IE10 triggers drop event first and then mouseup will get fire. So again this will not work on IE10.
comment:12 Changed 8 years ago by
I was able to find a quick workaround for those who are still interested.
Basically the problem occurs only when during the drag over the sortable your draggable is in the position when its both over the droppable and sortable (highlighting both).
Feel free to add a quick data() or just a flag to your ui.helper during the out() of the sortable which could be removed during the over() of the droppable. PS Make sure you don't allow your drop() on droppable to execute first time after the sortable out()!
Example:
self.contentTemplate.sortable({ ... bla bla bla ... out: function (event, ui) { // workaround for bug http://bugs.jqueryui.com/ticket/6259 ui.helper.data('overSortable', true); }, ... bla bla bla ... }); template.droppable({ ... bla bla bla ... over: function (event, ui) { // workaround for bug http://bugs.jqueryui.com/ticket/6259 ui.helper.removeData('overSortable'); }, drop: function (event, ui) { // workaround for bug http://bugs.jqueryui.com/ticket/6259 if (ui.helper.data('overSortable') != null) { ui.helper.removeData('overSortable'); return; } ... bla bla bla ... DO THE STUFF }, ... bla bla bla ... });
comment:13 Changed 8 years ago by
I think I've pieced together which bits of code are interacting to cause this, plus also for "deactivate" to be triggered on droppables when you just drag a draggable back out of a connected sortable. The "drag" handler of the draggable's "connectToSortable" plugin has a bit which says:
// If it doesn't intersect with the sortable, and it intersected before, // we fake the drag stop of the sortable, but make sure it doesn't remove // the helper by using cancelHelperRemoval.
When you drag a draggable into a sortable and then out again as you drag out of the sortable that bit of code triggers and part of it calls:
sortable._mouseStop( event, true );
The _mouseStop of sortable then in turn runs this bit of code:
//If we are using droppables, inform the manager about the drop if ($.ui.ddmanager && !this.options.dropBehaviour) { $.ui.ddmanager.drop(this, event); }
So it will call drop on the ddmanager, which doesn't seem desirable and can have two side effects.
The first is the one mentioned on this ticket - if your draggable happens to have moved over a droppable as you've moved out of the sortable then you'll see the drop event trigger (ddmanager.drop will check if the draggable intersects with a droppable and only call drop if it has).
The second one is one which prompted me to dig into this stuff which is that dragging a draggable into a sortable and then out of a sortable again will result in _deactivate being called on any droppables on the page:
this._deactivate.call( this, event );
I spotted this because I was using the activeClass option of a droppable to highlight it where my draggable was also connected to a sortable. I was finding that dragging the droppable into and out of the sortable was causing the highlighting to go off.
This fiddle demonstrates:
http://jsfiddle.net/k0w71yb1/2/
On that fiddle drag the draggable downwards slowly and you'll see the drop area will highlight as you begin to drag. Continue to drag the draggable down through the sortable list and then out below the sortable list. You'll see that the highlighting of the drop area will cease and a "deactivate" will be logged to the console. Then stop dragging (let go of the mouse button) and you'll see a second "deactivate" will be logged to the console.
I would guess the fix could be for _mouseStop to be told that it's a fake drag stop and know to not trigger the "drop" event on the droppables in this circumstance, but I don't know enough about why the code is doing what it's doing to be sure!
Tested with Chrome and Firefox 3.6.