From a3e79eafb02e019b0d3db7038a1fe86d6208cccd Mon Sep 17 00:00:00 2001 From: Will Holley Date: Tue, 21 May 2013 15:19:14 +0100 Subject: [PATCH] Droppable: fix #4977 - Droppable: tolerance, pointer - bug when pointer outside draggable Credit for this patch should go to Kevin Wells. This commit updates his previous patch to work against the current master. --- tests/unit/droppable/droppable_events.js | 46 ++++++++++++++++++++++++ ui/jquery.ui.droppable.js | 12 +++---- 2 files changed, 52 insertions(+), 6 deletions(-) diff --git a/tests/unit/droppable/droppable_events.js b/tests/unit/droppable/droppable_events.js index 4b8fe5acd2c..37e3540c088 100644 --- a/tests/unit/droppable/droppable_events.js +++ b/tests/unit/droppable/droppable_events.js @@ -60,4 +60,50 @@ test("drop", function() { }); */ + + test("#4977: tolerance, pointer - when pointer outside draggable", function() { + expect(1); + + var draggable1 = $("#draggable1"); + var droppable1 = $("#droppable1"); + var isDropped = false; + + droppable1.droppable({ + tolerance: 'pointer', + drop: function() { isDropped = true; } + }); + + // Contain draggable so only its bottom half can be dragged + // over the droppable. + draggable1.draggable({ containment: [ + draggable1.offset().left, + draggable1.offset().top, + droppable1.offset().left + droppable1.width(), + droppable1.offset().top - Math.round(draggable1.height() / 2) + ]}); + + // Pointer starts out over "top of draggable" + draggable1.simulate("mousedown", { + clientX: draggable1.offset().left + draggable1.width() / 2, + clientY: draggable1.offset().top + 1 // draggable1.height() - 1 + }); + + // Pointer ends up below bottom of draggable: + // + // * Top of draggable is *not* inside droppable. + // * Bottom of draggable *is* inside droppable. + // * Pointer *is* inside droppable, and outside droppable. + var pos = { + clientX: droppable1.offset().left + droppable1.width() / 2, + clientY: droppable1.offset().top + draggable1.height() + }; + draggable1.simulate("mousemove", pos); + draggable1.simulate("mouseup", pos); + + draggable1.draggable("destroy"); + droppable1.droppable("destroy"); + + ok(isDropped, "tolerance, pointer - when pointer outside draggable"); + }); + })( jQuery ); diff --git a/ui/jquery.ui.droppable.js b/ui/jquery.ui.droppable.js index 6bc4b594de5..b78ab2f096f 100644 --- a/ui/jquery.ui.droppable.js +++ b/ui/jquery.ui.droppable.js @@ -158,7 +158,7 @@ $.widget("ui.droppable", { !inst.options.disabled && inst.options.scope === draggable.options.scope && inst.accept.call(inst.element[0], (draggable.currentItem || draggable.element)) && - $.ui.intersect(draggable, $.extend(inst, { offset: inst.element.offset() }), inst.options.tolerance) + $.ui.intersect(draggable, $.extend(inst, { offset: inst.element.offset() }), inst.options.tolerance, event) ) { childrenIntersection = true; return false; } }); if(childrenIntersection) { @@ -191,7 +191,7 @@ $.widget("ui.droppable", { }); -$.ui.intersect = function(draggable, droppable, toleranceMode) { +$.ui.intersect = function(draggable, droppable, toleranceMode, event) { if (!droppable.offset) { return false; @@ -212,8 +212,8 @@ $.ui.intersect = function(draggable, droppable, toleranceMode) { t < y1 + (draggable.helperProportions.height / 2) && // Bottom Half y2 - (draggable.helperProportions.height / 2) < b ); // Top Half case "pointer": - draggableLeft = ((draggable.positionAbs || draggable.position.absolute).left + (draggable.clickOffset || draggable.offset.click).left); - draggableTop = ((draggable.positionAbs || draggable.position.absolute).top + (draggable.clickOffset || draggable.offset.click).top); + draggableLeft = event.pageX; + draggableTop = event.pageY; return isOverAxis( draggableTop, t, droppable.proportions.height ) && isOverAxis( draggableLeft, l, droppable.proportions.width ); case "touch": return ( @@ -284,7 +284,7 @@ $.ui.ddmanager = { if(!this.options) { return; } - if (!this.options.disabled && this.visible && $.ui.intersect(draggable, this, this.options.tolerance)) { + if (!this.options.disabled && this.visible && $.ui.intersect(draggable, this, this.options.tolerance, event)) { dropped = this._drop.call(this, event) || dropped; } @@ -321,7 +321,7 @@ $.ui.ddmanager = { } var parentInstance, scope, parent, - intersects = $.ui.intersect(draggable, this, this.options.tolerance), + intersects = $.ui.intersect(draggable, this, this.options.tolerance, event), c = !intersects && this.isover ? "isout" : (intersects && !this.isover ? "isover" : null); if(!c) { return;