diff --git a/dragula.js b/dragula.js
index 4f732311..b99724e7 100644
--- a/dragula.js
+++ b/dragula.js
@@ -99,7 +99,7 @@ function dragula (initialContainers, options) {
if (ignore) {
return; // we only care about honest-to-god left clicks and touch events
}
- var item = e.target;
+ var item = e.target.shadowRoot && e.composedPath()[0] || e.target;
var context = canStart(item);
if (!context) {
return;
@@ -551,16 +551,32 @@ function getElementBehindPoint (point, x, y) {
var state = p.className;
var el;
p.className += ' gu-hide';
- el = doc.elementFromPoint(x, y);
+ el = elementFromPoint(x, y);
p.className = state;
return el;
+
+ // Find the topmost element at point x, y.
+ // Traverses any shadow root to find the deepest element.
+ function elementFromPoint(x, y) {
+ var el = doc.elementFromPoint(x, y);
+ var maybeElem;
+ while (el && el.shadowRoot) {
+ maybeElem = el.shadowRoot.elementFromPoint(x, y);
+ if (maybeElem) {
+ el = maybeElem;
+ } else {
+ return el;
+ }
+ }
+ return el;
+ }
}
function never () { return false; }
function always () { return true; }
function getRectWidth (rect) { return rect.width || (rect.right - rect.left); }
function getRectHeight (rect) { return rect.height || (rect.bottom - rect.top); }
-function getParent (el) { return el.parentNode === doc ? null : el.parentNode; }
+function getParent (el) { return el.parentNode === doc ? null : (el.parentNode || el.host); }
function isInput (el) { return el.tagName === 'INPUT' || el.tagName === 'TEXTAREA' || el.tagName === 'SELECT' || isEditable(el); }
function isEditable (el) {
if (!el) { return false; } // no parents were editable
diff --git a/test/cancel.js b/test/cancel.js
index eaa93fde..4918bf29 100644
--- a/test/cancel.js
+++ b/test/cancel.js
@@ -3,6 +3,23 @@
var test = require('tape');
var dragula = require('..');
+test('with normal DOM', function(t) {
+ domTests(t, document.body);
+ t.end();
+});
+
+test('with nested shadow DOM', function(t) {
+ var div = document.createElement('div');
+ var div2 = document.createElement('div');
+ div.createShadowRoot();
+ div2.createShadowRoot();
+ div.shadowRoot.appendChild(div2);
+ document.body.appendChild(div);
+
+ domTests(t, div2.shadowRoot);
+ t.end();
+});
+
test('cancel does not throw when not dragging', function (t) {
t.test('a single time', function once (st) {
var drake = dragula();
@@ -24,85 +41,88 @@ test('cancel does not throw when not dragging', function (t) {
t.end();
});
-test('when dragging and cancel gets called, nothing happens', function (t) {
- var div = document.createElement('div');
- var item = document.createElement('div');
- var drake = dragula([div]);
- div.appendChild(item);
- document.body.appendChild(div);
- drake.start(item);
- drake.cancel();
- t.equal(div.children.length, 1, 'nothing happens');
- t.equal(drake.dragging, false, 'drake has stopped dragging');
- t.end();
-});
+function domTests(t, root) {
-test('when dragging and cancel gets called, cancel event is emitted', function (t) {
- var div = document.createElement('div');
- var item = document.createElement('div');
- var drake = dragula([div]);
- div.appendChild(item);
- document.body.appendChild(div);
- drake.start(item);
- drake.on('cancel', cancel);
- drake.on('dragend', dragend);
- drake.cancel();
- t.plan(3);
- t.end();
- function dragend () {
- t.pass('dragend got called');
- }
- function cancel (target, container) {
- t.equal(target, item, 'cancel was invoked with item');
- t.equal(container, div, 'cancel was invoked with container');
- }
-});
+ t.test('when dragging and cancel gets called, nothing happens', function (t) {
+ var div = document.createElement('div');
+ var item = document.createElement('div');
+ var drake = dragula([div]);
+ div.appendChild(item);
+ root.appendChild(div);
+ drake.start(item);
+ drake.cancel();
+ t.equal(div.children.length, 1, 'nothing happens');
+ t.equal(drake.dragging, false, 'drake has stopped dragging');
+ t.end();
+ });
-test('when dragging a copy and cancel gets called, default does not revert', function (t) {
- var div = document.createElement('div');
- var div2 = document.createElement('div');
- var item = document.createElement('div');
- var drake = dragula([div, div2]);
- div.appendChild(item);
- document.body.appendChild(div);
- document.body.appendChild(div2);
- drake.start(item);
- div2.appendChild(item);
- drake.on('drop', drop);
- drake.on('dragend', dragend);
- drake.cancel();
- t.plan(4);
- t.end();
- function dragend () {
- t.pass('dragend got called');
- }
- function drop (target, parent, source) {
- t.equal(target, item, 'drop was invoked with item');
- t.equal(parent, div2, 'drop was invoked with final container');
- t.equal(source, div, 'drop was invoked with source container');
- }
-});
+ t.test('when dragging and cancel gets called, cancel event is emitted', function (t) {
+ var div = document.createElement('div');
+ var item = document.createElement('div');
+ var drake = dragula([div]);
+ div.appendChild(item);
+ root.appendChild(div);
+ drake.start(item);
+ drake.on('cancel', cancel);
+ drake.on('dragend', dragend);
+ drake.cancel();
+ t.plan(3);
+ t.end();
+ function dragend () {
+ t.pass('dragend got called');
+ }
+ function cancel (target, container) {
+ t.equal(target, item, 'cancel was invoked with item');
+ t.equal(container, div, 'cancel was invoked with container');
+ }
+ });
-test('when dragging a copy and cancel gets called, revert is executed', function (t) {
- var div = document.createElement('div');
- var div2 = document.createElement('div');
- var item = document.createElement('div');
- var drake = dragula([div, div2]);
- div.appendChild(item);
- document.body.appendChild(div);
- document.body.appendChild(div2);
- drake.start(item);
- div2.appendChild(item);
- drake.on('cancel', cancel);
- drake.on('dragend', dragend);
- drake.cancel(true);
- t.plan(3);
- t.end();
- function dragend () {
- t.pass('dragend got called');
- }
- function cancel (target, container) {
- t.equal(target, item, 'cancel was invoked with item');
- t.equal(container, div, 'cancel was invoked with container');
- }
-});
+ t.test('when dragging a copy and cancel gets called, default does not revert', function (t) {
+ var div = document.createElement('div');
+ var div2 = document.createElement('div');
+ var item = document.createElement('div');
+ var drake = dragula([div, div2]);
+ div.appendChild(item);
+ root.appendChild(div);
+ root.appendChild(div2);
+ drake.start(item);
+ div2.appendChild(item);
+ drake.on('drop', drop);
+ drake.on('dragend', dragend);
+ drake.cancel();
+ t.plan(4);
+ t.end();
+ function dragend () {
+ t.pass('dragend got called');
+ }
+ function drop (target, parent, source) {
+ t.equal(target, item, 'drop was invoked with item');
+ t.equal(parent, div2, 'drop was invoked with final container');
+ t.equal(source, div, 'drop was invoked with source container');
+ }
+ });
+
+ t.test('when dragging a copy and cancel gets called, revert is executed', function (t) {
+ var div = document.createElement('div');
+ var div2 = document.createElement('div');
+ var item = document.createElement('div');
+ var drake = dragula([div, div2]);
+ div.appendChild(item);
+ root.appendChild(div);
+ root.appendChild(div2);
+ drake.start(item);
+ div2.appendChild(item);
+ drake.on('cancel', cancel);
+ drake.on('dragend', dragend);
+ drake.cancel(true);
+ t.plan(3);
+ t.end();
+ function dragend () {
+ t.pass('dragend got called');
+ }
+ function cancel (target, container) {
+ t.equal(target, item, 'cancel was invoked with item');
+ t.equal(container, div, 'cancel was invoked with container');
+ }
+ });
+}
diff --git a/test/destroy.js b/test/destroy.js
index 1fcf178c..3f56261e 100644
--- a/test/destroy.js
+++ b/test/destroy.js
@@ -2,6 +2,22 @@
var test = require('tape');
var dragula = require('..');
+test('with normal DOM', function(t) {
+ domTests(t, document.body);
+ t.end();
+});
+
+test('with nested shadow DOM', function(t) {
+ var div = document.createElement('div');
+ var div2 = document.createElement('div');
+ div.createShadowRoot();
+ div2.createShadowRoot();
+ div.shadowRoot.appendChild(div2);
+ document.body.appendChild(div);
+
+ domTests(t, div2.shadowRoot);
+ t.end();
+});
test('destroy does not throw when not dragging, destroyed, or whatever', function (t) {
t.test('a single time', function once (st) {
@@ -24,80 +40,83 @@ test('destroy does not throw when not dragging, destroyed, or whatever', functio
t.end();
});
-test('when dragging and destroy gets called, nothing happens', function (t) {
- var div = document.createElement('div');
- var item = document.createElement('div');
- var drake = dragula([div]);
- div.appendChild(item);
- document.body.appendChild(div);
- drake.start(item);
- drake.destroy();
- t.equal(div.children.length, 1, 'nothing happens');
- t.equal(drake.dragging, false, 'drake has stopped dragging');
- t.end();
-});
+function domTests(t, root) {
+
+ t.test('when dragging and destroy gets called, nothing happens', function (t) {
+ var div = document.createElement('div');
+ var item = document.createElement('div');
+ var drake = dragula([div]);
+ div.appendChild(item);
+ root.appendChild(div);
+ drake.start(item);
+ drake.destroy();
+ t.equal(div.children.length, 1, 'nothing happens');
+ t.equal(drake.dragging, false, 'drake has stopped dragging');
+ t.end();
+ });
-test('when dragging and destroy gets called, dragend event is emitted gracefully', function (t) {
- var div = document.createElement('div');
- var item = document.createElement('div');
- var drake = dragula([div]);
- div.appendChild(item);
- document.body.appendChild(div);
- drake.start(item);
- drake.on('dragend', dragend);
- drake.destroy();
- t.plan(1);
- t.end();
- function dragend () {
- t.pass('dragend got called');
- }
-});
+ t.test('when dragging and destroy gets called, dragend event is emitted gracefully', function (t) {
+ var div = document.createElement('div');
+ var item = document.createElement('div');
+ var drake = dragula([div]);
+ div.appendChild(item);
+ root.appendChild(div);
+ drake.start(item);
+ drake.on('dragend', dragend);
+ drake.destroy();
+ t.plan(1);
+ t.end();
+ function dragend () {
+ t.pass('dragend got called');
+ }
+ });
-test('when dragging a copy and destroy gets called, default does not revert', function (t) {
- var div = document.createElement('div');
- var div2 = document.createElement('div');
- var item = document.createElement('div');
- var drake = dragula([div, div2]);
- div.appendChild(item);
- document.body.appendChild(div);
- document.body.appendChild(div2);
- drake.start(item);
- div2.appendChild(item);
- drake.on('drop', drop);
- drake.on('dragend', dragend);
- drake.destroy();
- t.plan(4);
- t.end();
- function dragend () {
- t.pass('dragend got called');
- }
- function drop (target, parent, source) {
- t.equal(target, item, 'drop was invoked with item');
- t.equal(parent, div2, 'drop was invoked with final container');
- t.equal(source, div, 'drop was invoked with source container');
- }
-});
+ t.test('when dragging a copy and destroy gets called, default does not revert', function (t) {
+ var div = document.createElement('div');
+ var div2 = document.createElement('div');
+ var item = document.createElement('div');
+ var drake = dragula([div, div2]);
+ div.appendChild(item);
+ root.appendChild(div);
+ root.appendChild(div2);
+ drake.start(item);
+ div2.appendChild(item);
+ drake.on('drop', drop);
+ drake.on('dragend', dragend);
+ drake.destroy();
+ t.plan(4);
+ t.end();
+ function dragend () {
+ t.pass('dragend got called');
+ }
+ function drop (target, parent, source) {
+ t.equal(target, item, 'drop was invoked with item');
+ t.equal(parent, div2, 'drop was invoked with final container');
+ t.equal(source, div, 'drop was invoked with source container');
+ }
+ });
-test('when dragging a copy and destroy gets called, revert is executed', function (t) {
- var div = document.createElement('div');
- var div2 = document.createElement('div');
- var item = document.createElement('div');
- var drake = dragula([div, div2], { revertOnSpill: true });
- div.appendChild(item);
- document.body.appendChild(div);
- document.body.appendChild(div2);
- drake.start(item);
- div2.appendChild(item);
- drake.on('cancel', cancel);
- drake.on('dragend', dragend);
- drake.destroy();
- t.plan(3);
- t.end();
- function dragend () {
- t.pass('dragend got called');
- }
- function cancel (target, container) {
- t.equal(target, item, 'cancel was invoked with item');
- t.equal(container, div, 'cancel was invoked with container');
- }
-});
+ t.test('when dragging a copy and destroy gets called, revert is executed', function (t) {
+ var div = document.createElement('div');
+ var div2 = document.createElement('div');
+ var item = document.createElement('div');
+ var drake = dragula([div, div2], { revertOnSpill: true });
+ div.appendChild(item);
+ root.appendChild(div);
+ root.appendChild(div2);
+ drake.start(item);
+ div2.appendChild(item);
+ drake.on('cancel', cancel);
+ drake.on('dragend', dragend);
+ drake.destroy();
+ t.plan(3);
+ t.end();
+ function dragend () {
+ t.pass('dragend got called');
+ }
+ function cancel (target, container) {
+ t.equal(target, item, 'cancel was invoked with item');
+ t.equal(container, div, 'cancel was invoked with container');
+ }
+ });
+}
diff --git a/test/drag.js b/test/drag.js
index baea9182..ba92309e 100644
--- a/test/drag.js
+++ b/test/drag.js
@@ -4,253 +4,272 @@ var test = require('tape');
var events = require('./lib/events');
var dragula = require('..');
-test('drag event gets emitted when clicking an item', function (t) {
- testCase('works for left clicks', { which: 1 });
- testCase('works for wheel clicks', { which: 1 });
- testCase('works when clicking buttons by default', { which: 1 }, { tag: 'button', passes: true });
- testCase('works when clicking anchors by default', { which: 1 }, { tag: 'a', passes: true });
- testCase('fails for right clicks', { which: 2 }, { passes: false });
- testCase('fails for meta-clicks', { which: 1, metaKey: true }, { passes: false });
- testCase('fails for ctrl-clicks', { which: 1, ctrlKey: true }, { passes: false });
- testCase('fails when clicking containers', { which: 1 }, { containerClick: true, passes: false });
- testCase('fails whenever invalid returns true', { which: 1 }, { passes: false, dragulaOpts: { invalid: always } });
- testCase('fails whenever moves returns false', { which: 1 }, { passes: false, dragulaOpts: { moves: never } });
+test('with normal DOM', function(t) {
+ domTests(t, document.body);
t.end();
- function testCase (desc, eventOptions, options) {
- t.test(desc, function subtest (st) {
- var o = options || {};
- var div = document.createElement('div');
- var item = document.createElement(o.tag || 'div');
- var passes = o.passes !== false;
- var drake = dragula([div], o.dragulaOpts);
- div.appendChild(item);
- document.body.appendChild(div);
- drake.on('drag', drag);
- events.raise(o.containerClick ? div : item, 'mousedown', eventOptions);
- events.raise(o.containerClick ? div : item, 'mousemove');
- st.plan(passes ? 4 : 1);
- st.equal(drake.dragging, passes, desc + ': final state is drake is ' + (passes ? '' : 'not ') + 'dragging');
- st.end();
- function drag (target, container) {
- st[passes ? 'pass' : 'fail'](desc + ': drag event was emitted synchronously');
- st.equal(target, item, desc + ': first argument is selected item');
- st.equal(container, div, desc + ': second argument is container');
- }
- });
- }
});
-test('when already dragging, mousedown/mousemove ends (cancels) previous drag', function (t) {
- var div = document.createElement('div');
- var item1 = document.createElement('div');
- var item2 = document.createElement('div');
- var drake = dragula([div]);
- div.appendChild(item1);
- div.appendChild(item2);
- document.body.appendChild(div);
- drake.start(item1);
- drake.on('dragend', end);
- drake.on('cancel', cancel);
- drake.on('drag', drag);
- events.raise(item2, 'mousedown', { which: 1 });
- events.raise(item2, 'mousemove', { which: 1 });
- t.plan(7);
- t.equal(drake.dragging, true, 'final state is drake is dragging');
- t.end();
- function end (item) {
- t.equal(item, item1, 'dragend invoked with correct item');
- }
- function cancel (item, source) {
- t.equal(item, item1, 'cancel invoked with correct item');
- t.equal(source, div, 'cancel invoked with correct source');
- }
- function drag (item, container) {
- t.pass('drag event was emitted synchronously');
- t.equal(item, item2, 'first argument is selected item');
- t.equal(container, div, 'second argument is container');
- }
-});
-
-test('when already dragged, ends (drops) previous drag', function (t) {
+test('with nested shadow DOM', function(t) {
var div = document.createElement('div');
var div2 = document.createElement('div');
- var item1 = document.createElement('div');
- var item2 = document.createElement('div');
- var drake = dragula([div, div2]);
- div.appendChild(item1);
- div.appendChild(item2);
+ div.createShadowRoot();
+ div2.createShadowRoot();
+ div.shadowRoot.appendChild(div2);
document.body.appendChild(div);
- document.body.appendChild(div2);
- drake.start(item1);
- div2.appendChild(item1);
- drake.on('dragend', end);
- drake.on('drop', drop);
- drake.on('drag', drag);
- events.raise(item2, 'mousedown', { which: 1 });
- events.raise(item2, 'mousemove', { which: 1 });
- t.plan(8);
- t.equal(drake.dragging, true, 'final state is drake is dragging');
+
+ domTests(t, div2.shadowRoot);
t.end();
- function end (item) {
- t.equal(item, item1, 'dragend invoked with correct item');
- }
- function drop (item, target, source) {
- t.equal(item, item1, 'drop invoked with correct item');
- t.equal(source, div, 'drop invoked with correct source');
- t.equal(target, div2, 'drop invoked with correct target');
- }
- function drag (item, container) {
- t.pass('drag event was emitted synchronously');
- t.equal(item, item2, 'first argument is selected item');
- t.equal(container, div, 'second argument is container');
- }
});
-test('when copying, emits cloned with the copy', function (t) {
- var div = document.createElement('div');
- var item1 = document.createElement('div');
- var item2 = document.createElement('span');
- var drake = dragula([div], { copy: true });
- item2.innerHTML = 'the force is with this one';
- div.appendChild(item1);
- div.appendChild(item2);
- document.body.appendChild(div);
- drake.start(item1);
- drake.on('cloned', cloned);
- drake.on('drag', drag);
- events.raise(item2, 'mousedown', { which: 1 });
- events.raise(item2, 'mousemove', { which: 1 });
- t.plan(12);
- t.equal(drake.dragging, true, 'final state is drake is dragging');
- t.end();
- function cloned (copy, item) {
- t.notEqual(copy, item2, 'first argument is not exactly the target');
- t.equal(copy.tagName, item2.tagName, 'first argument has same tag as target');
- t.equal(copy.innerHTML, item2.innerHTML, 'first argument has same inner html as target');
- t.equal(item, item2, 'second argument is clicked item');
- }
- function drag (item, container) {
- t.pass('drag event was emitted synchronously');
- t.equal(item, item2, 'first argument is selected item');
- t.equal(container, div, 'second argument is container');
- }
-});
+function domTests(t, root) {
+ t.test('drag event gets emitted when clicking an item', function (t) {
+ testCase('works for left clicks', { which: 1 });
+ testCase('works for wheel clicks', { which: 1 });
+ testCase('works when clicking buttons by default', { which: 1 }, { tag: 'button', passes: true });
+ testCase('works when clicking anchors by default', { which: 1 }, { tag: 'a', passes: true });
+ testCase('fails for right clicks', { which: 2 }, { passes: false });
+ testCase('fails for meta-clicks', { which: 1, metaKey: true }, { passes: false });
+ testCase('fails for ctrl-clicks', { which: 1, ctrlKey: true }, { passes: false });
+ testCase('fails when clicking containers', { which: 1 }, { containerClick: true, passes: false });
+ testCase('fails whenever invalid returns true', { which: 1 }, { passes: false, dragulaOpts: { invalid: always } });
+ testCase('fails whenever moves returns false', { which: 1 }, { passes: false, dragulaOpts: { moves: never } });
+ t.end();
+ function testCase (desc, eventOptions, options) {
+ t.test(desc, function subtest (st) {
+ var o = options || {};
+ var div = document.createElement('div');
+ var item = document.createElement(o.tag || 'div');
+ var passes = o.passes !== false;
+ var drake = dragula([div], o.dragulaOpts);
+ div.appendChild(item);
+ root.appendChild(div);
+ drake.on('drag', drag);
+ events.raise(o.containerClick ? div : item, 'mousedown', eventOptions);
+ events.raise(o.containerClick ? div : item, 'mousemove');
+ st.plan(passes ? 4 : 1);
+ st.equal(drake.dragging, passes, desc + ': final state is drake is ' + (passes ? '' : 'not ') + 'dragging');
+ st.end();
+ function drag (target, container) {
+ st[passes ? 'pass' : 'fail'](desc + ': drag event was emitted synchronously');
+ st.equal(target, item, desc + ': first argument is selected item');
+ st.equal(container, div, desc + ': second argument is container');
+ }
+ });
+ }
+ });
-test('when dragging, element gets gu-transit class', function (t) {
- var div = document.createElement('div');
- var item = document.createElement('div');
- dragula([div]);
- div.appendChild(item);
- document.body.appendChild(div);
- events.raise(item, 'mousedown', { which: 1 });
- events.raise(item, 'mousemove', { which: 1 });
- t.equal(item.className, 'gu-transit', 'item has gu-transit class');
- t.end();
-});
+ t.test('when already dragging, mousedown/mousemove ends (cancels) previous drag', function (t) {
+ var div = document.createElement('div');
+ var item1 = document.createElement('div');
+ var item2 = document.createElement('div');
+ var drake = dragula([div]);
+ div.appendChild(item1);
+ div.appendChild(item2);
+ root.appendChild(div);
+ drake.start(item1);
+ drake.on('dragend', end);
+ drake.on('cancel', cancel);
+ drake.on('drag', drag);
+ events.raise(item2, 'mousedown', { which: 1 });
+ events.raise(item2, 'mousemove', { which: 1 });
+ t.plan(7);
+ t.equal(drake.dragging, true, 'final state is drake is dragging');
+ t.end();
+ function end (item) {
+ t.equal(item, item1, 'dragend invoked with correct item');
+ }
+ function cancel (item, source) {
+ t.equal(item, item1, 'cancel invoked with correct item');
+ t.equal(source, div, 'cancel invoked with correct source');
+ }
+ function drag (item, container) {
+ t.pass('drag event was emitted synchronously');
+ t.equal(item, item2, 'first argument is selected item');
+ t.equal(container, div, 'second argument is container');
+ }
+ });
-test('when dragging, body gets gu-unselectable class', function (t) {
- var div = document.createElement('div');
- var item = document.createElement('div');
- dragula([div]);
- div.appendChild(item);
- document.body.appendChild(div);
- events.raise(item, 'mousedown', { which: 1 });
- events.raise(item, 'mousemove', { which: 1 });
- t.equal(document.body.className, 'gu-unselectable', 'body has gu-unselectable class');
- t.end();
-});
+ t.test('when already dragged, ends (drops) previous drag', function (t) {
+ var div = document.createElement('div');
+ var div2 = document.createElement('div');
+ var item1 = document.createElement('div');
+ var item2 = document.createElement('div');
+ var drake = dragula([div, div2]);
+ div.appendChild(item1);
+ div.appendChild(item2);
+ root.appendChild(div);
+ root.appendChild(div2);
+ drake.start(item1);
+ div2.appendChild(item1);
+ drake.on('dragend', end);
+ drake.on('drop', drop);
+ drake.on('drag', drag);
+ events.raise(item2, 'mousedown', { which: 1 });
+ events.raise(item2, 'mousemove', { which: 1 });
+ t.plan(8);
+ t.equal(drake.dragging, true, 'final state is drake is dragging');
+ t.end();
+ function end (item) {
+ t.equal(item, item1, 'dragend invoked with correct item');
+ }
+ function drop (item, target, source) {
+ t.equal(item, item1, 'drop invoked with correct item');
+ t.equal(source, div, 'drop invoked with correct source');
+ t.equal(target, div2, 'drop invoked with correct target');
+ }
+ function drag (item, container) {
+ t.pass('drag event was emitted synchronously');
+ t.equal(item, item2, 'first argument is selected item');
+ t.equal(container, div, 'second argument is container');
+ }
+ });
-test('when dragging, element gets a mirror image for show', function (t) {
- var div = document.createElement('div');
- var item = document.createElement('div');
- var drake = dragula([div]);
- item.innerHTML = 'the force is with this one';
- div.appendChild(item);
- document.body.appendChild(div);
- drake.on('cloned', cloned);
- events.raise(item, 'mousedown', { which: 1 });
- events.raise(item, 'mousemove', { which: 1 });
- t.plan(4);
- t.end();
- function cloned (mirror, target) {
- t.equal(item.className, 'gu-transit', 'item does not have gu-mirror class');
- t.equal(mirror.className, 'gu-mirror', 'mirror only has gu-mirror class');
- t.equal(mirror.innerHTML, item.innerHTML, 'mirror is passed to \'cloned\' event');
- t.equal(target, item, 'cloned lets you know that the mirror is a clone of `item`');
- }
-});
+ t.test('when copying, emits cloned with the copy', function (t) {
+ var div = document.createElement('div');
+ var item1 = document.createElement('div');
+ var item2 = document.createElement('span');
+ var drake = dragula([div], { copy: true });
+ item2.innerHTML = 'the force is with this one';
+ div.appendChild(item1);
+ div.appendChild(item2);
+ root.appendChild(div);
+ drake.start(item1);
+ drake.on('cloned', cloned);
+ drake.on('drag', drag);
+ events.raise(item2, 'mousedown', { which: 1 });
+ events.raise(item2, 'mousemove', { which: 1 });
+ t.plan(12);
+ t.equal(drake.dragging, true, 'final state is drake is dragging');
+ t.end();
+ function cloned (copy, item) {
+ t.notEqual(copy, item2, 'first argument is not exactly the target');
+ t.equal(copy.tagName, item2.tagName, 'first argument has same tag as target');
+ t.equal(copy.innerHTML, item2.innerHTML, 'first argument has same inner html as target');
+ t.equal(item, item2, 'second argument is clicked item');
+ }
+ function drag (item, container) {
+ t.pass('drag event was emitted synchronously');
+ t.equal(item, item2, 'first argument is selected item');
+ t.equal(container, div, 'second argument is container');
+ }
+ });
-test('when dragging, mirror element gets appended to configured mirrorContainer', function (t) {
- var mirrorContainer = document.createElement('div');
- var div = document.createElement('div');
- var item = document.createElement('div');
- var drake = dragula([div], {
- 'mirrorContainer': mirrorContainer
+ t.test('when dragging, element gets gu-transit class', function (t) {
+ var div = document.createElement('div');
+ var item = document.createElement('div');
+ dragula([div]);
+ div.appendChild(item);
+ root.appendChild(div);
+ events.raise(item, 'mousedown', { which: 1 });
+ events.raise(item, 'mousemove', { which: 1 });
+ t.equal(item.className, 'gu-transit', 'item has gu-transit class');
+ t.end();
});
- item.innerHTML = 'the force is with this one';
- div.appendChild(item);
- document.body.appendChild(div);
- drake.on('cloned', cloned);
- events.raise(item, 'mousedown', { which: 1 });
- events.raise(item, 'mousemove', { which: 1 });
- t.plan(1);
- t.end();
- function cloned (mirror) {
- t.equal(mirror.parentNode, mirrorContainer, 'mirrors parent is the configured mirrorContainer');
- }
-});
-test('when dragging stops, element gets gu-transit class removed', function (t) {
- var div = document.createElement('div');
- var item = document.createElement('div');
- var drake = dragula([div]);
- div.appendChild(item);
- document.body.appendChild(div);
- events.raise(item, 'mousedown', { which: 1 });
- events.raise(item, 'mousemove', { which: 1 });
- t.equal(item.className, 'gu-transit', 'item has gu-transit class');
- drake.end();
- t.equal(item.className, '', 'item has gu-transit class removed');
- t.end();
-});
+ t.test('when dragging, body gets gu-unselectable class', function (t) {
+ var div = document.createElement('div');
+ var item = document.createElement('div');
+ dragula([div]);
+ div.appendChild(item);
+ root.appendChild(div);
+ events.raise(item, 'mousedown', { which: 1 });
+ events.raise(item, 'mousemove', { which: 1 });
+ t.equal(document.body.className, 'gu-unselectable', 'body has gu-unselectable class');
+ t.end();
+ });
-test('when dragging stops, body becomes selectable again', function (t) {
- var div = document.createElement('div');
- var item = document.createElement('div');
- var drake = dragula([div]);
- div.appendChild(item);
- document.body.appendChild(div);
- events.raise(item, 'mousedown', { which: 1 });
- events.raise(item, 'mousemove', { which: 1 });
- t.equal(document.body.className, 'gu-unselectable', 'body has gu-unselectable class');
- drake.end();
- t.equal(document.body.className, '', 'body got gu-unselectable class removed');
- t.end();
-});
+ t.test('when dragging, element gets a mirror image for show', function (t) {
+ var div = document.createElement('div');
+ var item = document.createElement('div');
+ var drake = dragula([div]);
+ item.innerHTML = 'the force is with this one';
+ div.appendChild(item);
+ root.appendChild(div);
+ drake.on('cloned', cloned);
+ events.raise(item, 'mousedown', { which: 1 });
+ events.raise(item, 'mousemove', { which: 1 });
+ t.plan(4);
+ t.end();
+ function cloned (mirror, target) {
+ t.equal(item.className, 'gu-transit', 'item does not have gu-mirror class');
+ t.equal(mirror.className, 'gu-mirror', 'mirror only has gu-mirror class');
+ t.equal(mirror.innerHTML, item.innerHTML, 'mirror is passed to \'cloned\' event');
+ t.equal(target, item, 'cloned lets you know that the mirror is a clone of `item`');
+ }
+ });
-test('when drag begins, check for copy option', function (t) {
- var div = document.createElement('div');
- var item = document.createElement('div');
- item.className = 'copyable';
- div.className = 'contains';
- var drake = dragula([div], {
- copy: checkCondition
+ t.test('when dragging, mirror element gets appended to configured mirrorContainer', function (t) {
+ var mirrorContainer = document.createElement('div');
+ var div = document.createElement('div');
+ var item = document.createElement('div');
+ var drake = dragula([div], {
+ 'mirrorContainer': mirrorContainer
+ });
+ item.innerHTML = 'the force is with this one';
+ div.appendChild(item);
+ root.appendChild(div);
+ drake.on('cloned', cloned);
+ events.raise(item, 'mousedown', { which: 1 });
+ events.raise(item, 'mousemove', { which: 1 });
+ t.plan(1);
+ t.end();
+ function cloned (mirror) {
+ t.equal(mirror.parentNode, mirrorContainer, 'mirrors parent is the configured mirrorContainer');
+ }
+ });
+
+ t.test('when dragging stops, element gets gu-transit class removed', function (t) {
+ var div = document.createElement('div');
+ var item = document.createElement('div');
+ var drake = dragula([div]);
+ div.appendChild(item);
+ root.appendChild(div);
+ events.raise(item, 'mousedown', { which: 1 });
+ events.raise(item, 'mousemove', { which: 1 });
+ t.equal(item.className, 'gu-transit', 'item has gu-transit class');
+ drake.end();
+ t.equal(item.className, '', 'item has gu-transit class removed');
+ t.end();
+ });
+
+ t.test('when dragging stops, body becomes selectable again', function (t) {
+ var div = document.createElement('div');
+ var item = document.createElement('div');
+ var drake = dragula([div]);
+ div.appendChild(item);
+ root.appendChild(div);
+ events.raise(item, 'mousedown', { which: 1 });
+ events.raise(item, 'mousemove', { which: 1 });
+ t.equal(document.body.className, 'gu-unselectable', 'body has gu-unselectable class');
+ drake.end();
+ t.equal(document.body.className, '', 'body got gu-unselectable class removed');
+ t.end();
+ });
+
+ t.test('when drag begins, check for copy option', function (t) {
+ var div = document.createElement('div');
+ var item = document.createElement('div');
+ item.className = 'copyable';
+ div.className = 'contains';
+ var drake = dragula([div], {
+ copy: checkCondition
+ });
+ item.innerHTML = 'the force is with this one';
+ div.appendChild(item);
+ root.appendChild(div);
+ events.raise(item, 'mousedown', { which: 1 });
+ events.raise(item, 'mousemove', { which: 1 });
+ events.raise(item, 'mousemove', { which: 1 }); // ensure the copy method condition is only asserted once
+ t.plan(2);
+ t.end();
+ function checkCondition (el, source) {
+ t.equal(el.className, 'copyable', 'dragged element classname is copyable');
+ t.equal(source.className, 'contains', 'source container classname is contains');
+ return true;
+ }
+ drake.end();
});
- item.innerHTML = 'the force is with this one';
- div.appendChild(item);
- document.body.appendChild(div);
- events.raise(item, 'mousedown', { which: 1 });
- events.raise(item, 'mousemove', { which: 1 });
- events.raise(item, 'mousemove', { which: 1 }); // ensure the copy method condition is only asserted once
- t.plan(2);
- t.end();
- function checkCondition (el, source) {
- t.equal(el.className, 'copyable', 'dragged element classname is copyable');
- t.equal(source.className, 'contains', 'source container classname is contains');
- return true;
- }
- drake.end();
-});
-function always () { return true; }
-function never () { return false; }
+ function always () { return true; }
+ function never () { return false; }
+}
diff --git a/test/end.js b/test/end.js
index bd19805a..173b74b7 100644
--- a/test/end.js
+++ b/test/end.js
@@ -2,6 +2,22 @@
var test = require('tape');
var dragula = require('..');
+test('with normal DOM', function(t) {
+ domTests(t, document.body);
+ t.end();
+});
+
+test('with nested shadow DOM', function(t) {
+ var div = document.createElement('div');
+ var div2 = document.createElement('div');
+ div.createShadowRoot();
+ div2.createShadowRoot();
+ div.shadowRoot.appendChild(div2);
+ document.body.appendChild(div);
+
+ domTests(t, div2.shadowRoot);
+ t.end();
+});
test('end does not throw when not dragging', function (t) {
t.test('a single time', function once (st) {
@@ -24,54 +40,56 @@ test('end does not throw when not dragging', function (t) {
t.end();
});
-test('when already dragging, .end() ends (cancels) previous drag', function (t) {
- var div = document.createElement('div');
- var item1 = document.createElement('div');
- var item2 = document.createElement('div');
- var drake = dragula([div]);
- div.appendChild(item1);
- div.appendChild(item2);
- document.body.appendChild(div);
- drake.start(item1);
- drake.on('dragend', end);
- drake.on('cancel', cancel);
- drake.end();
- t.plan(4);
- t.equal(drake.dragging, false, 'final state is: drake is not dragging');
- t.end();
- function end (item) {
- t.equal(item, item1, 'dragend invoked with correct item');
- }
- function cancel (item, source) {
- t.equal(item, item1, 'cancel invoked with correct item');
- t.equal(source, div, 'cancel invoked with correct source');
- }
-});
+function domTests(t, root) {
+ t.test('when already dragging, .end() ends (cancels) previous drag', function (t) {
+ var div = document.createElement('div');
+ var item1 = document.createElement('div');
+ var item2 = document.createElement('div');
+ var drake = dragula([div]);
+ div.appendChild(item1);
+ div.appendChild(item2);
+ root.appendChild(div);
+ drake.start(item1);
+ drake.on('dragend', end);
+ drake.on('cancel', cancel);
+ drake.end();
+ t.plan(4);
+ t.equal(drake.dragging, false, 'final state is: drake is not dragging');
+ t.end();
+ function end (item) {
+ t.equal(item, item1, 'dragend invoked with correct item');
+ }
+ function cancel (item, source) {
+ t.equal(item, item1, 'cancel invoked with correct item');
+ t.equal(source, div, 'cancel invoked with correct source');
+ }
+ });
-test('when already dragged, ends (drops) previous drag', function (t) {
- var div = document.createElement('div');
- var div2 = document.createElement('div');
- var item1 = document.createElement('div');
- var item2 = document.createElement('div');
- var drake = dragula([div, div2]);
- div.appendChild(item1);
- div.appendChild(item2);
- document.body.appendChild(div);
- document.body.appendChild(div2);
- drake.start(item1);
- div2.appendChild(item1);
- drake.on('dragend', end);
- drake.on('drop', drop);
- drake.end();
- t.plan(5);
- t.equal(drake.dragging, false, 'final state is: drake is not dragging');
- t.end();
- function end (item) {
- t.equal(item, item1, 'dragend invoked with correct item');
- }
- function drop (item, target, source) {
- t.equal(item, item1, 'drop invoked with correct item');
- t.equal(source, div, 'drop invoked with correct source');
- t.equal(target, div2, 'drop invoked with correct target');
- }
-});
+ t.test('when already dragged, ends (drops) previous drag', function (t) {
+ var div = document.createElement('div');
+ var div2 = document.createElement('div');
+ var item1 = document.createElement('div');
+ var item2 = document.createElement('div');
+ var drake = dragula([div, div2]);
+ div.appendChild(item1);
+ div.appendChild(item2);
+ root.appendChild(div);
+ root.appendChild(div2);
+ drake.start(item1);
+ div2.appendChild(item1);
+ drake.on('dragend', end);
+ drake.on('drop', drop);
+ drake.end();
+ t.plan(5);
+ t.equal(drake.dragging, false, 'final state is: drake is not dragging');
+ t.end();
+ function end (item) {
+ t.equal(item, item1, 'dragend invoked with correct item');
+ }
+ function drop (item, target, source) {
+ t.equal(item, item1, 'drop invoked with correct item');
+ t.equal(source, div, 'drop invoked with correct source');
+ t.equal(target, div2, 'drop invoked with correct target');
+ }
+ });
+}
diff --git a/test/events.js b/test/events.js
index 23125d30..d32fdd22 100644
--- a/test/events.js
+++ b/test/events.js
@@ -4,260 +4,280 @@ var test = require('tape');
var events = require('./lib/events');
var dragula = require('..');
-test('.start() emits "cloned" for copies', function (t) {
- var div = document.createElement('div');
- var item = document.createElement('div');
- var drake = dragula([div], { copy: true });
- div.appendChild(item);
- document.body.appendChild(div);
- drake.on('cloned', cloned);
- drake.start(item);
- t.plan(3);
- t.end();
- function cloned (copy, original, type) {
- if (type === 'copy') {
- t.notEqual(copy, item, 'copy is not a reference to item');
- t.equal(copy.nodeType, item.nodeType, 'copy of original is provided');
- t.equal(original, item, 'original item is provided');
- }
- }
-});
-
-test('.start() emits "drag" for items', function (t) {
- var div = document.createElement('div');
- var item = document.createElement('div');
- var drake = dragula([div]);
- div.appendChild(item);
- document.body.appendChild(div);
- drake.on('drag', drag);
- drake.start(item);
- t.plan(2);
+test('with normal DOM', function(t) {
+ domTests(t, document.body);
t.end();
- function drag (original, container) {
- t.equal(original, item, 'item is a reference to moving target');
- t.equal(container, div, 'container matches expected div');
- }
});
-test('.end() emits "cancel" when not moved', function (t) {
- var div = document.createElement('div');
- var item = document.createElement('div');
- var drake = dragula([div]);
- div.appendChild(item);
- document.body.appendChild(div);
- drake.on('dragend', dragend);
- drake.on('cancel', cancel);
- events.raise(item, 'mousedown', { which: 1 });
- events.raise(item, 'mousemove', { which: 1 });
- drake.end();
- t.plan(3);
- t.end();
- function dragend (original) {
- t.equal(original, item, 'item is a reference to moving target');
- }
- function cancel (original, container) {
- t.equal(original, item, 'item is a reference to moving target');
- t.equal(container, div, 'container matches expected div');
- }
-});
-
-test('.end() emits "drop" when moved', function (t) {
+test('with nested shadow DOM', function(t) {
var div = document.createElement('div');
var div2 = document.createElement('div');
- var item = document.createElement('div');
- var drake = dragula([div, div2]);
- div.appendChild(item);
+ div.createShadowRoot();
+ div2.createShadowRoot();
+ div.shadowRoot.appendChild(div2);
document.body.appendChild(div);
- document.body.appendChild(div2);
- drake.on('dragend', dragend);
- drake.on('drop', drop);
- events.raise(item, 'mousedown', { which: 1 });
- events.raise(item, 'mousemove', { which: 1 });
- div2.appendChild(item);
- drake.end();
- t.plan(4);
- t.end();
- function dragend (original) {
- t.equal(original, item, 'item is a reference to moving target');
- }
- function drop (original, target, container) {
- t.equal(original, item, 'item is a reference to moving target');
- t.equal(target, div2, 'target matches expected div');
- t.equal(container, div, 'container matches expected div');
- }
-});
-test('.remove() emits "remove" for items', function (t) {
- var div = document.createElement('div');
- var item = document.createElement('div');
- var drake = dragula([div]);
- div.appendChild(item);
- document.body.appendChild(div);
- drake.on('dragend', dragend);
- drake.on('remove', remove);
- events.raise(item, 'mousedown', { which: 1 });
- events.raise(item, 'mousemove', { which: 1 });
- drake.remove();
- t.plan(3);
+ domTests(t, div2.shadowRoot);
t.end();
- function dragend (original) {
- t.equal(original, item, 'item is a reference to moving target');
- }
- function remove (original, container) {
- t.equal(original, item, 'item is a reference to moving target');
- t.equal(container, div, 'container matches expected div');
- }
});
-test('.remove() emits "cancel" for copies', function (t) {
- var div = document.createElement('div');
- var item = document.createElement('div');
- var drake = dragula([div], { copy: true });
- div.appendChild(item);
- document.body.appendChild(div);
- drake.on('dragend', dragend);
- drake.on('cancel', cancel);
- events.raise(item, 'mousedown', { which: 1 });
- events.raise(item, 'mousemove', { which: 1 });
- drake.remove();
- t.plan(4);
- t.end();
- function dragend () {
- t.pass('dragend got invoked');
- }
- function cancel (copy, container) {
- t.notEqual(copy, item, 'copy is not a reference to item');
- t.equal(copy.nodeType, item.nodeType, 'item is a copy of item');
- t.equal(container, null, 'container matches expectation');
- }
-});
+function domTests(t, root) {
+ t.test('.start() emits "cloned" for copies', function (t) {
+ var div = document.createElement('div');
+ var item = document.createElement('div');
+ var drake = dragula([div], { copy: true });
+ div.appendChild(item);
+ root.appendChild(div);
+ drake.on('cloned', cloned);
+ drake.start(item);
+ t.plan(3);
+ t.end();
+ function cloned (copy, original, type) {
+ if (type === 'copy') {
+ t.notEqual(copy, item, 'copy is not a reference to item');
+ t.equal(copy.nodeType, item.nodeType, 'copy of original is provided');
+ t.equal(original, item, 'original item is provided');
+ }
+ }
+ });
-test('.cancel() emits "cancel" when not moved', function (t) {
- var div = document.createElement('div');
- var item = document.createElement('div');
- var drake = dragula([div]);
- div.appendChild(item);
- document.body.appendChild(div);
- drake.on('dragend', dragend);
- drake.on('cancel', cancel);
- events.raise(item, 'mousedown', { which: 1 });
- events.raise(item, 'mousemove', { which: 1 });
- drake.cancel();
- t.plan(3);
- t.end();
- function dragend (original) {
- t.equal(original, item, 'item is a reference to moving target');
- }
- function cancel (original, container) {
- t.equal(original, item, 'item is a reference to moving target');
- t.equal(container, div, 'container matches expected div');
- }
-});
+ t.test('.start() emits "drag" for items', function (t) {
+ var div = document.createElement('div');
+ var item = document.createElement('div');
+ var drake = dragula([div]);
+ div.appendChild(item);
+ root.appendChild(div);
+ drake.on('drag', drag);
+ drake.start(item);
+ t.plan(2);
+ t.end();
+ function drag (original, container) {
+ t.equal(original, item, 'item is a reference to moving target');
+ t.equal(container, div, 'container matches expected div');
+ }
+ });
-test('.cancel() emits "drop" when not reverted', function (t) {
- var div = document.createElement('div');
- var div2 = document.createElement('div');
- var item = document.createElement('div');
- var drake = dragula([div]);
- div.appendChild(item);
- document.body.appendChild(div);
- document.body.appendChild(div2);
- drake.on('dragend', dragend);
- drake.on('drop', drop);
- events.raise(item, 'mousedown', { which: 1 });
- events.raise(item, 'mousemove', { which: 1 });
- div2.appendChild(item);
- drake.cancel();
- t.plan(4);
- t.end();
- function dragend (original) {
- t.equal(original, item, 'item is a reference to moving target');
- }
- function drop (original, parent, container) {
- t.equal(original, item, 'item is a reference to moving target');
- t.equal(parent, div2, 'parent matches expected div');
- t.equal(container, div, 'container matches expected div');
- }
-});
+ t.test('.end() emits "cancel" when not moved', function (t) {
+ var div = document.createElement('div');
+ var item = document.createElement('div');
+ var drake = dragula([div]);
+ div.appendChild(item);
+ root.appendChild(div);
+ drake.on('dragend', dragend);
+ drake.on('cancel', cancel);
+ events.raise(item, 'mousedown', { which: 1 });
+ events.raise(item, 'mousemove', { which: 1 });
+ drake.end();
+ t.plan(3);
+ t.end();
+ function dragend (original) {
+ t.equal(original, item, 'item is a reference to moving target');
+ }
+ function cancel (original, container) {
+ t.equal(original, item, 'item is a reference to moving target');
+ t.equal(container, div, 'container matches expected div');
+ }
+ });
-test('.cancel() emits "cancel" when reverts', function (t) {
- var div = document.createElement('div');
- var div2 = document.createElement('div');
- var item = document.createElement('div');
- var drake = dragula([div], { revertOnSpill: true });
- div.appendChild(item);
- document.body.appendChild(div);
- document.body.appendChild(div2);
- drake.on('dragend', dragend);
- drake.on('cancel', cancel);
- events.raise(item, 'mousedown', { which: 1 });
- events.raise(item, 'mousemove', { which: 1 });
- div2.appendChild(item);
- drake.cancel();
- t.plan(3);
- t.end();
- function dragend (original) {
- t.equal(original, item, 'item is a reference to moving target');
- }
- function cancel (original, container) {
- t.equal(original, item, 'item is a reference to moving target');
- t.equal(container, div, 'container matches expected div');
- }
-});
+ t.test('.end() emits "drop" when moved', function (t) {
+ var div = document.createElement('div');
+ var div2 = document.createElement('div');
+ var item = document.createElement('div');
+ var drake = dragula([div, div2]);
+ div.appendChild(item);
+ root.appendChild(div);
+ root.appendChild(div2);
+ drake.on('dragend', dragend);
+ drake.on('drop', drop);
+ events.raise(item, 'mousedown', { which: 1 });
+ events.raise(item, 'mousemove', { which: 1 });
+ div2.appendChild(item);
+ drake.end();
+ t.plan(4);
+ t.end();
+ function dragend (original) {
+ t.equal(original, item, 'item is a reference to moving target');
+ }
+ function drop (original, target, container) {
+ t.equal(original, item, 'item is a reference to moving target');
+ t.equal(target, div2, 'target matches expected div');
+ t.equal(container, div, 'container matches expected div');
+ }
+ });
-test('mousedown emits "cloned" for mirrors', function (t) {
- var div = document.createElement('div');
- var item = document.createElement('div');
- var drake = dragula([div]);
- div.appendChild(item);
- document.body.appendChild(div);
- drake.on('cloned', cloned);
- events.raise(item, 'mousedown', { which: 1 });
- events.raise(item, 'mousemove', { which: 1 });
- t.plan(3);
- t.end();
- function cloned (copy, original, type) {
- if (type === 'mirror') {
- t.notEqual(copy, item, 'mirror is not a reference to item');
- t.equal(copy.nodeType, item.nodeType, 'mirror of original is provided');
- t.equal(original, item, 'original item is provided');
+ t.test('.remove() emits "remove" for items', function (t) {
+ var div = document.createElement('div');
+ var item = document.createElement('div');
+ var drake = dragula([div]);
+ div.appendChild(item);
+ root.appendChild(div);
+ drake.on('dragend', dragend);
+ drake.on('remove', remove);
+ events.raise(item, 'mousedown', { which: 1 });
+ events.raise(item, 'mousemove', { which: 1 });
+ drake.remove();
+ t.plan(3);
+ t.end();
+ function dragend (original) {
+ t.equal(original, item, 'item is a reference to moving target');
}
- }
-});
+ function remove (original, container) {
+ t.equal(original, item, 'item is a reference to moving target');
+ t.equal(container, div, 'container matches expected div');
+ }
+ });
-test('mousedown emits "cloned" for copies', function (t) {
- var div = document.createElement('div');
- var item = document.createElement('div');
- var drake = dragula([div], { copy: true });
- div.appendChild(item);
- document.body.appendChild(div);
- drake.on('cloned', cloned);
- events.raise(item, 'mousedown', { which: 1 });
- events.raise(item, 'mousemove', { which: 1 });
- t.plan(3);
- t.end();
- function cloned (copy, original, type) {
- if (type === 'copy') {
+ t.test('.remove() emits "cancel" for copies', function (t) {
+ var div = document.createElement('div');
+ var item = document.createElement('div');
+ var drake = dragula([div], { copy: true });
+ div.appendChild(item);
+ root.appendChild(div);
+ drake.on('dragend', dragend);
+ drake.on('cancel', cancel);
+ events.raise(item, 'mousedown', { which: 1 });
+ events.raise(item, 'mousemove', { which: 1 });
+ drake.remove();
+ t.plan(4);
+ t.end();
+ function dragend () {
+ t.pass('dragend got invoked');
+ }
+ function cancel (copy, container) {
t.notEqual(copy, item, 'copy is not a reference to item');
- t.equal(copy.nodeType, item.nodeType, 'copy of original is provided');
- t.equal(original, item, 'original item is provided');
+ t.equal(copy.nodeType, item.nodeType, 'item is a copy of item');
+ t.equal(container, undefined, 'container matches expectation');
}
- }
-});
+ });
-test('mousedown emits "drag" for items', function (t) {
- var div = document.createElement('div');
- var item = document.createElement('div');
- var drake = dragula([div]);
- div.appendChild(item);
- document.body.appendChild(div);
- drake.on('drag', drag);
- events.raise(item, 'mousedown', { which: 1 });
- events.raise(item, 'mousemove', { which: 1 });
- t.plan(2);
- t.end();
- function drag (original, container) {
- t.equal(original, item, 'item is a reference to moving target');
- t.equal(container, div, 'container matches expected div');
- }
-});
+ t.test('.cancel() emits "cancel" when not moved', function (t) {
+ var div = document.createElement('div');
+ var item = document.createElement('div');
+ var drake = dragula([div]);
+ div.appendChild(item);
+ root.appendChild(div);
+ drake.on('dragend', dragend);
+ drake.on('cancel', cancel);
+ events.raise(item, 'mousedown', { which: 1 });
+ events.raise(item, 'mousemove', { which: 1 });
+ drake.cancel();
+ t.plan(3);
+ t.end();
+ function dragend (original) {
+ t.equal(original, item, 'item is a reference to moving target');
+ }
+ function cancel (original, container) {
+ t.equal(original, item, 'item is a reference to moving target');
+ t.equal(container, div, 'container matches expected div');
+ }
+ });
+
+ t.test('.cancel() emits "drop" when not reverted', function (t) {
+ var div = document.createElement('div');
+ var div2 = document.createElement('div');
+ var item = document.createElement('div');
+ var drake = dragula([div]);
+ div.appendChild(item);
+ root.appendChild(div);
+ root.appendChild(div2);
+ drake.on('dragend', dragend);
+ drake.on('drop', drop);
+ events.raise(item, 'mousedown', { which: 1 });
+ events.raise(item, 'mousemove', { which: 1 });
+ div2.appendChild(item);
+ drake.cancel();
+ t.plan(4);
+ t.end();
+ function dragend (original) {
+ t.equal(original, item, 'item is a reference to moving target');
+ }
+ function drop (original, parent, container) {
+ t.equal(original, item, 'item is a reference to moving target');
+ t.equal(parent, div2, 'parent matches expected div');
+ t.equal(container, div, 'container matches expected div');
+ }
+ });
+
+ t.test('.cancel() emits "cancel" when reverts', function (t) {
+ var div = document.createElement('div');
+ var div2 = document.createElement('div');
+ var item = document.createElement('div');
+ var drake = dragula([div], { revertOnSpill: true });
+ div.appendChild(item);
+ root.appendChild(div);
+ root.appendChild(div2);
+ drake.on('dragend', dragend);
+ drake.on('cancel', cancel);
+ events.raise(item, 'mousedown', { which: 1 });
+ events.raise(item, 'mousemove', { which: 1 });
+ div2.appendChild(item);
+ drake.cancel();
+ t.plan(3);
+ t.end();
+ function dragend (original) {
+ t.equal(original, item, 'item is a reference to moving target');
+ }
+ function cancel (original, container) {
+ t.equal(original, item, 'item is a reference to moving target');
+ t.equal(container, div, 'container matches expected div');
+ }
+ });
+
+ t.test('mousedown emits "cloned" for mirrors', function (t) {
+ var div = document.createElement('div');
+ var item = document.createElement('div');
+ var drake = dragula([div]);
+ div.appendChild(item);
+ root.appendChild(div);
+ drake.on('cloned', cloned);
+ events.raise(item, 'mousedown', { which: 1 });
+ events.raise(item, 'mousemove', { which: 1 });
+ t.plan(3);
+ t.end();
+ function cloned (copy, original, type) {
+ if (type === 'mirror') {
+ t.notEqual(copy, item, 'mirror is not a reference to item');
+ t.equal(copy.nodeType, item.nodeType, 'mirror of original is provided');
+ t.equal(original, item, 'original item is provided');
+ }
+ }
+ });
+
+ t.test('mousedown emits "cloned" for copies', function (t) {
+ var div = document.createElement('div');
+ var item = document.createElement('div');
+ var drake = dragula([div], { copy: true });
+ div.appendChild(item);
+ root.appendChild(div);
+ drake.on('cloned', cloned);
+ events.raise(item, 'mousedown', { which: 1 });
+ events.raise(item, 'mousemove', { which: 1 });
+ t.plan(3);
+ t.end();
+ function cloned (copy, original, type) {
+ if (type === 'copy') {
+ t.notEqual(copy, item, 'copy is not a reference to item');
+ t.equal(copy.nodeType, item.nodeType, 'copy of original is provided');
+ t.equal(original, item, 'original item is provided');
+ }
+ }
+ });
+
+ t.test('mousedown emits "drag" for items', function (t) {
+ var div = document.createElement('div');
+ var item = document.createElement('div');
+ var drake = dragula([div]);
+ div.appendChild(item);
+ root.appendChild(div);
+ drake.on('drag', drag);
+ events.raise(item, 'mousedown', { which: 1 });
+ events.raise(item, 'mousemove', { which: 1 });
+ t.plan(2);
+ t.end();
+ function drag (original, container) {
+ t.equal(original, item, 'item is a reference to moving target');
+ t.equal(container, div, 'container matches expected div');
+ }
+ });
+
+}
diff --git a/test/remove.js b/test/remove.js
index 035cdf53..597430c6 100644
--- a/test/remove.js
+++ b/test/remove.js
@@ -4,6 +4,23 @@ var test = require('tape');
var events = require('./lib/events');
var dragula = require('..');
+test('with normal DOM', function(t) {
+ domTests(t, document.body);
+ t.end();
+});
+
+test('with nested shadow DOM', function(t) {
+ var div = document.createElement('div');
+ var div2 = document.createElement('div');
+ div.createShadowRoot();
+ div2.createShadowRoot();
+ div.shadowRoot.appendChild(div2);
+ document.body.appendChild(div);
+
+ domTests(t, div2.shadowRoot);
+ t.end();
+});
+
test('remove does not throw when not dragging', function (t) {
t.test('a single time', function once (st) {
var drake = dragula();
@@ -25,59 +42,62 @@ test('remove does not throw when not dragging', function (t) {
t.end();
});
-test('when dragging and remove gets called, element is removed', function (t) {
- var div = document.createElement('div');
- var item = document.createElement('div');
- var drake = dragula([div]);
- div.appendChild(item);
- document.body.appendChild(div);
- drake.start(item);
- drake.remove();
- t.equal(div.children.length, 0, 'item got removed from container');
- t.equal(drake.dragging, false, 'drake has stopped dragging');
- t.end();
-});
+function domTests(t, root) {
-test('when dragging and remove gets called, remove event is emitted', function (t) {
- var div = document.createElement('div');
- var item = document.createElement('div');
- var drake = dragula([div]);
- div.appendChild(item);
- document.body.appendChild(div);
- drake.start(item);
- drake.on('remove', remove);
- drake.on('dragend', dragend);
- drake.remove();
- t.plan(3);
- t.end();
- function dragend () {
- t.pass('dragend got called');
- }
- function remove (target, container) {
- t.equal(target, item, 'remove was invoked with item');
- t.equal(container, div, 'remove was invoked with container');
- }
-});
+ t.test('when dragging and remove gets called, element is removed', function (t) {
+ var div = document.createElement('div');
+ var item = document.createElement('div');
+ var drake = dragula([div]);
+ div.appendChild(item);
+ root.appendChild(div);
+ drake.start(item);
+ drake.remove();
+ t.equal(div.children.length, 0, 'item got removed from container');
+ t.equal(drake.dragging, false, 'drake has stopped dragging');
+ t.end();
+ });
-test('when dragging a copy and remove gets called, cancel event is emitted', function (t) {
- var div = document.createElement('div');
- var item = document.createElement('div');
- var drake = dragula([div], { copy: true });
- div.appendChild(item);
- document.body.appendChild(div);
- events.raise(item, 'mousedown', { which: 1 });
- events.raise(item, 'mousemove', { which: 1 });
- drake.on('cancel', cancel);
- drake.on('dragend', dragend);
- drake.remove();
- t.plan(4);
- t.end();
- function dragend () {
- t.pass('dragend got called');
- }
- function cancel (target, container) {
- t.equal(target.className, 'gu-transit', 'cancel was invoked with item');
- t.notEqual(target, item, 'item is a copy and not the original');
- t.equal(container, null, 'cancel was invoked with container');
- }
-});
+ t.test('when dragging and remove gets called, remove event is emitted', function (t) {
+ var div = document.createElement('div');
+ var item = document.createElement('div');
+ var drake = dragula([div]);
+ div.appendChild(item);
+ root.appendChild(div);
+ drake.start(item);
+ drake.on('remove', remove);
+ drake.on('dragend', dragend);
+ drake.remove();
+ t.plan(3);
+ t.end();
+ function dragend () {
+ t.pass('dragend got called');
+ }
+ function remove (target, container) {
+ t.equal(target, item, 'remove was invoked with item');
+ t.equal(container, div, 'remove was invoked with container');
+ }
+ });
+
+ t.test('when dragging a copy and remove gets called, cancel event is emitted', function (t) {
+ var div = document.createElement('div');
+ var item = document.createElement('div');
+ var drake = dragula([div], { copy: true });
+ div.appendChild(item);
+ root.appendChild(div);
+ events.raise(item, 'mousedown', { which: 1 });
+ events.raise(item, 'mousemove', { which: 1 });
+ drake.on('cancel', cancel);
+ drake.on('dragend', dragend);
+ drake.remove();
+ t.plan(4);
+ t.end();
+ function dragend () {
+ t.pass('dragend got called');
+ }
+ function cancel (target, container) {
+ t.equal(target.className, 'gu-transit', 'cancel was invoked with item');
+ t.notEqual(target, item, 'item is a copy and not the original');
+ t.equal(container, undefined, 'cancel was invoked with container');
+ }
+ });
+}