Opened 9 years ago

Last modified 5 months 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)

example.html (1.1 KB) - added by avuori 9 years ago.

Download all attachments as: .zip

Change History (14)

Changed 9 years ago by avuori

Attachment: example.html added

comment:1 Changed 9 years ago by avuori

Tested with Chrome and Firefox 3.6.

comment:2 Changed 9 years ago by be.davestein

I had the same issue on my site with very different markup. Was also using clone.

comment:3 Changed 8 years ago by cnr

$(".droppable")
.droppable({drop: function () { 
   if (!$(event.srcElement).hasClass("ui-draggable-dragging")) { return; }

   alert("dropped"); 
} 
});

will be solve your problem

Last edited 5 months ago by Ryan J Ollos (previous) (diff)

comment:4 in reply to:  3 Changed 8 years ago by avuori

Replying to cnr:

... will be solve your problem

Thanks for the tip!

Last edited 5 months ago by Ryan J Ollos (previous) (diff)

comment:5 Changed 7 years ago by Scott González

Milestone: TBD2.0.0

comment:6 Changed 7 years ago by mikesherov

Status: newopen
Summary: Droppable's drop event triggered when dragging a draggable over the droppableDroppable: drop event incorrectly triggered when dragging a draggable over a droppable onto a sortable

confirmed on latest: http://jsfiddle.net/2aJh9/

comment:7 Changed 6 years ago by discy

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 6 years ago by pdore

Is there a known workaround? Is there an alternative to using clone helper?

comment:9 Changed 6 years ago by pdore

Is there a known workaround?
Is there an alternative to using clone helper?

comment:10 Changed 5 years ago by 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 :

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

});
Last edited 5 months ago by Ryan J Ollos (previous) (diff)

comment:11 in reply to:  10 Changed 5 years ago by atulkushwah

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.

Last edited 5 months ago by Ryan J Ollos (previous) (diff)

comment:12 Changed 4 years ago by Morph3y

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 ...
});
Last edited 5 months ago by Ryan J Ollos (previous) (diff)

comment:13 Changed 4 years ago by Skaffen

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!

Note: See TracTickets for help on using tickets.