Skip to content

Commit 68e5f58

Browse files
New dragleave handler
1 parent dc5d1c7 commit 68e5f58

File tree

3 files changed

+28
-25
lines changed

3 files changed

+28
-25
lines changed

angular-drag-and-drop-lists.js

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -250,7 +250,7 @@
250250
* by creating a child element with dndPlaceholder class.
251251
* - dndDragover Will be added to the list while an element is dragged over the list.
252252
*/
253-
dndLists.directive('dndList', ['$parse', '$timeout', function($parse, $timeout) {
253+
dndLists.directive('dndList', ['$parse', function($parse) {
254254
return function(scope, element, attr) {
255255
// While an element is dragged over the list, this placeholder element is inserted
256256
// at the location where the element would be inserted after dropping.
@@ -413,20 +413,19 @@
413413
/**
414414
* We have to remove the placeholder when the element is no longer dragged over our list. The
415415
* problem is that the dragleave event is not only fired when the element leaves our list,
416-
* but also when it leaves a child element -- so practically it's fired all the time. As a
417-
* workaround we wait a few milliseconds and then check if the dndDragover class was added
418-
* again. If it is there, dragover must have been called in the meantime, i.e. the element
419-
* is still dragging over the list. If you know a better way of doing this, please tell me!
416+
* but also when it leaves a child element. Therefore, we determine whether the mouse cursor
417+
* is still pointing to an element inside the list or not.
420418
*/
421419
element.on('dragleave', function(event) {
422420
event = event.originalEvent || event;
423421

424-
element.removeClass("dndDragover");
425-
$timeout(function() {
426-
if (!element.hasClass("dndDragover")) {
427-
placeholder.remove();
428-
}
429-
}, 100);
422+
var newTarget = document.elementFromPoint(event.clientX, event.clientY);
423+
if (listNode.contains(newTarget) && !event._dndPhShown) {
424+
// Signalize to potential parent lists that a placeholder is already shown.
425+
event._dndPhShown = true;
426+
} else {
427+
stopDragover();
428+
}
430429
});
431430

432431
/**

test/dndListSpec.js

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -359,26 +359,27 @@ describe('dndList', function() {
359359
element.remove();
360360
});
361361

362-
it('removes the dndDragover class', function() {
363-
var rect = element.children()[1].getBoundingClientRect();
364-
dragover.dragleave(element);
362+
it('removes the placeholder and dndDragover class', function() {
363+
var rect = element[0].getBoundingClientRect();
364+
dragover.dragleave(element, {clientX: rect.left - 2, clientY: rect.top - 2});
365365
expect(element.hasClass('dndDragover')).toBe(false);
366+
expect(element.children().length).toBe(3);
366367
});
367368

368-
it('removes the placeholder after a timeout', inject(function($timeout) {
369-
dragover.dragleave(element);
370-
$timeout.flush(50);
371-
expect(element.children().length).toBe(4);
372-
$timeout.flush(50);
369+
it('removes the placeholder and dndDragover if child placeholder is already set', function() {
370+
var rect = element[0].getBoundingClientRect();
371+
dragover.dragleave(element, {clientX: rect.left + 2, clientY: rect.top + 2, phShown: true});
372+
expect(element.hasClass('dndDragover')).toBe(false);
373373
expect(element.children().length).toBe(3);
374-
}));
374+
});
375375

376-
it('does not remove the placeholder if dndDragover was set again', inject(function($timeout) {
377-
dragover.dragleave(element);
378-
element.addClass('dndDragover')
379-
$timeout.flush(200);
376+
it('sets _dndPhShown if mouse is still inside', function() {
377+
var rect = element[0].getBoundingClientRect();
378+
var result = dragover.dragleave(element, {clientX: rect.left + 2, clientY: rect.top + 2});
379+
expect(element.hasClass('dndDragover')).toBe(true);
380380
expect(element.children().length).toBe(4);
381-
}));
381+
expect(result.dndPhShownSet).toBe(true);
382+
});
382383
});
383384

384385
describe('dropEffect', function() {

test/mocks.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,8 @@ class DragEventMock {
7979
get target() { return this.$options.target || undefined; }
8080
get type() { return this.$type; }
8181
get _dndHandle() { return this.$options.dndHandle || undefined; }
82+
get _dndPhShown() { return this.$options.phShown || undefined; }
83+
set _dndPhShown(value) { this.$results.setDndPhShown = value; }
8284

8385
preventDefault() { this.$results.invokedPreventDefault = true; }
8486
stopPropagation() { this.$results.invokedStopPropagation = true; }
@@ -96,6 +98,7 @@ class DragEventResult {
9698

9799
get propagationStopped() { return !!this.$results.invokedStopPropagation; }
98100
get defaultPrevented() { return !!this.$results.invokedPreventDefault; }
101+
get dndPhShownSet() { return this.$results.setDndPhShown || false; }
99102
get returnValue() { return this.$results.returnValue; }
100103
get dropEffect() { return this.$results.dataTransfer.dropEffect; }
101104
get type() { return this.$type; }

0 commit comments

Comments
 (0)