From 8164937fbc4412fdf0e02b136555f3073c790bfc Mon Sep 17 00:00:00 2001 From: Thomas Smith Date: Thu, 16 Feb 2017 16:34:20 +0100 Subject: [PATCH 1/4] Make dragging work inside and between shadow DOM --- dragula.js | 16 +- test/cancel.js | 205 +++++++++++--------- test/destroy.js | 196 ++++++++++--------- test/drag.js | 481 ++++++++++++++++++++++++---------------------- test/end.js | 148 ++++++++------- test/events.js | 496 +++++++++++++++++++++++++----------------------- test/remove.js | 155 ++++++++------- 7 files changed, 910 insertions(+), 787 deletions(-) diff --git a/dragula.js b/dragula.js index 4f732311..49f7ca54 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,26 @@ 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); + while (el && el.shadowRoot) { + el = el.shadowRoot.elementFromPoint(x, y); + } + 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.host || el.parentNode); } 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..a66b03cb 100644 --- a/test/cancel.js +++ b/test/cancel.js @@ -3,106 +3,125 @@ var test = require('tape'); var dragula = require('..'); -test('cancel does not throw when not dragging', function (t) { - t.test('a single time', function once (st) { - var drake = dragula(); - st.doesNotThrow(function () { - drake.cancel(); - }, 'dragula ignores a single call to drake.cancel'); - st.end(); - }); - t.test('multiple times', function once (st) { - var drake = dragula(); - st.doesNotThrow(function () { - drake.cancel(); - drake.cancel(); - drake.cancel(); - drake.cancel(); - }, 'dragula ignores multiple calls to drake.cancel'); - st.end(); - }); +test('with normal DOM', function(t) { + allTests(t, document.body); t.end(); }); -test('when dragging and cancel gets called, nothing happens', function (t) { +test('with nested shadow DOM', function(t) { var div = document.createElement('div'); - var item = document.createElement('div'); - var drake = dragula([div]); - div.appendChild(item); + var div2 = document.createElement('div'); + div.createShadowRoot(); + div2.createShadowRoot(); + div.shadowRoot.appendChild(div2); 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'); + + allTests(t, div2.shadowRoot); t.end(); }); -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'); - } -}); +function allTests(t, root) { + test('cancel does not throw when not dragging', function (t) { + t.test('a single time', function once (st) { + var drake = dragula(); + st.doesNotThrow(function () { + drake.cancel(); + }, 'dragula ignores a single call to drake.cancel'); + st.end(); + }); + t.test('multiple times', function once (st) { + var drake = dragula(); + st.doesNotThrow(function () { + drake.cancel(); + drake.cancel(); + drake.cancel(); + drake.cancel(); + }, 'dragula ignores multiple calls to drake.cancel'); + st.end(); + }); + 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'); - } -}); + 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, 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'); - } -}); + 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, 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'); + } + }); + + 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'); + } + }); +} \ No newline at end of file diff --git a/test/destroy.js b/test/destroy.js index 1fcf178c..6b62ef91 100644 --- a/test/destroy.js +++ b/test/destroy.js @@ -2,102 +2,120 @@ var test = require('tape'); var dragula = require('..'); - -test('destroy does not throw when not dragging, destroyed, or whatever', function (t) { - t.test('a single time', function once (st) { - var drake = dragula(); - st.doesNotThrow(function () { - drake.destroy(); - }, 'dragula bites into a single call to drake.destroy'); - st.end(); - }); - t.test('multiple times', function once (st) { - var drake = dragula(); - st.doesNotThrow(function () { - drake.destroy(); - drake.destroy(); - drake.destroy(); - drake.destroy(); - }, 'dragula bites into multiple calls to drake.destroy'); - st.end(); - }); +test('with normal DOM', function(t) { + allTests(t, document.body); t.end(); }); -test('when dragging and destroy gets called, nothing happens', function (t) { +test('with nested shadow DOM', function(t) { var div = document.createElement('div'); - var item = document.createElement('div'); - var drake = dragula([div]); - div.appendChild(item); + var div2 = document.createElement('div'); + div.createShadowRoot(); + div2.createShadowRoot(); + div.shadowRoot.appendChild(div2); 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'); + + allTests(t, div2.shadowRoot); 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'); - } -}); +function allTests(t, root) { + test('destroy does not throw when not dragging, destroyed, or whatever', function (t) { + t.test('a single time', function once (st) { + var drake = dragula(); + st.doesNotThrow(function () { + drake.destroy(); + }, 'dragula bites into a single call to drake.destroy'); + st.end(); + }); + t.test('multiple times', function once (st) { + var drake = dragula(); + st.doesNotThrow(function () { + drake.destroy(); + drake.destroy(); + drake.destroy(); + drake.destroy(); + }, 'dragula bites into multiple calls to drake.destroy'); + st.end(); + }); + t.end(); + }); -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'); - } -}); + 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 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'); - } -}); + 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); + 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); + 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'); + } + }); +} \ No newline at end of file diff --git a/test/drag.js b/test/drag.js index baea9182..9a48bf3d 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) { + allTests(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'); + + allTests(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 allTests(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; } +} \ No newline at end of file diff --git a/test/end.js b/test/end.js index bd19805a..8d168433 100644 --- a/test/end.js +++ b/test/end.js @@ -2,76 +2,94 @@ var test = require('tape'); var dragula = require('..'); - -test('end does not throw when not dragging', function (t) { - t.test('a single time', function once (st) { - var drake = dragula(); - st.doesNotThrow(function () { - drake.end(); - }, 'dragula ignores a single call to drake.end'); - st.end(); - }); - t.test('multiple times', function once (st) { - var drake = dragula(); - st.doesNotThrow(function () { - drake.end(); - drake.end(); - drake.end(); - drake.end(); - }, 'dragula ignores multiple calls to drake.end'); - st.end(); - }); - 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'); +test('with normal DOM', function(t) { + allTests(t, document.body); 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) { +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.end(); - t.plan(5); - t.equal(drake.dragging, false, 'final state is: drake is not dragging'); + + allTests(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 allTests(t, root) { + test('end does not throw when not dragging', function (t) { + t.test('a single time', function once (st) { + var drake = dragula(); + st.doesNotThrow(function () { + drake.end(); + }, 'dragula ignores a single call to drake.end'); + st.end(); + }); + t.test('multiple times', function once (st) { + var drake = dragula(); + st.doesNotThrow(function () { + drake.end(); + drake.end(); + drake.end(); + drake.end(); + }, 'dragula ignores multiple calls to drake.end'); + st.end(); + }); + 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); + 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); + 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'); + } + }); +} \ No newline at end of file diff --git a/test/events.js b/test/events.js index 23125d30..2f449d06 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); +test('with normal DOM', function(t) { + allTests(t, document.body); 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) { +test('with nested shadow DOM', function(t) { var div = document.createElement('div'); - var item = document.createElement('div'); - var drake = dragula([div]); - div.appendChild(item); + var div2 = document.createElement('div'); + div.createShadowRoot(); + div2.createShadowRoot(); + div.shadowRoot.appendChild(div2); document.body.appendChild(div); - drake.on('drag', drag); - drake.start(item); - t.plan(2); + + allTests(t, div2.shadowRoot); 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'); - } -}); +function allTests(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('.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); - 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'); - } -}); + 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('.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); - 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'); - } -}); + 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('.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'); - } -}); + 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('.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('.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('.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('.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, 'item is a copy of item'); + t.equal(container, null, 'container matches expectation'); + } + }); -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('.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'); + } + }); -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('.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'); + } + }); -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.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('.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'); + } + }); -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('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..04b72b76 100644 --- a/test/remove.js +++ b/test/remove.js @@ -4,80 +4,99 @@ var test = require('tape'); var events = require('./lib/events'); var dragula = require('..'); -test('remove does not throw when not dragging', function (t) { - t.test('a single time', function once (st) { - var drake = dragula(); - st.doesNotThrow(function () { - drake.remove(); - }, 'dragula ignores a single call to drake.remove'); - st.end(); - }); - t.test('multiple times', function once (st) { - var drake = dragula(); - st.doesNotThrow(function () { - drake.remove(); - drake.remove(); - drake.remove(); - drake.remove(); - }, 'dragula ignores multiple calls to drake.remove'); - st.end(); - }); +test('with normal DOM', function(t) { + allTests(t, document.body); t.end(); }); -test('when dragging and remove gets called, element is removed', function (t) { +test('with nested shadow DOM', function(t) { var div = document.createElement('div'); - var item = document.createElement('div'); - var drake = dragula([div]); - div.appendChild(item); + var div2 = document.createElement('div'); + div.createShadowRoot(); + div2.createShadowRoot(); + div.shadowRoot.appendChild(div2); 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'); + + allTests(t, div2.shadowRoot); t.end(); }); -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'); - } -}); +function allTests(t, root) { + test('remove does not throw when not dragging', function (t) { + t.test('a single time', function once (st) { + var drake = dragula(); + st.doesNotThrow(function () { + drake.remove(); + }, 'dragula ignores a single call to drake.remove'); + st.end(); + }); + t.test('multiple times', function once (st) { + var drake = dragula(); + st.doesNotThrow(function () { + drake.remove(); + drake.remove(); + drake.remove(); + drake.remove(); + }, 'dragula ignores multiple calls to drake.remove'); + st.end(); + }); + 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'); - } -}); + 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 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'); + } + }); + + 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, null, 'cancel was invoked with container'); + } + }); +} \ No newline at end of file From f6e8dcc9245b3014c08ffe7ce18dbb241e827c5a Mon Sep 17 00:00:00 2001 From: Thomas Smith Date: Fri, 17 Feb 2017 20:59:48 +0100 Subject: [PATCH 2/4] Only run tests with shadow DOM that actually touch the DOM --- test/cancel.js | 55 +++++++++++++++++++++++++------------------------ test/destroy.js | 55 +++++++++++++++++++++++++------------------------ test/drag.js | 8 +++---- test/end.js | 50 ++++++++++++++++++++++---------------------- test/events.js | 6 +++--- test/remove.js | 53 ++++++++++++++++++++++++----------------------- 6 files changed, 115 insertions(+), 112 deletions(-) diff --git a/test/cancel.js b/test/cancel.js index a66b03cb..4918bf29 100644 --- a/test/cancel.js +++ b/test/cancel.js @@ -4,7 +4,7 @@ var test = require('tape'); var dragula = require('..'); test('with normal DOM', function(t) { - allTests(t, document.body); + domTests(t, document.body); t.end(); }); @@ -16,33 +16,34 @@ test('with nested shadow DOM', function(t) { div.shadowRoot.appendChild(div2); document.body.appendChild(div); - allTests(t, div2.shadowRoot); + domTests(t, div2.shadowRoot); t.end(); }); -function allTests(t, root) { - test('cancel does not throw when not dragging', function (t) { - t.test('a single time', function once (st) { - var drake = dragula(); - st.doesNotThrow(function () { - drake.cancel(); - }, 'dragula ignores a single call to drake.cancel'); - st.end(); - }); - t.test('multiple times', function once (st) { - var drake = dragula(); - st.doesNotThrow(function () { - drake.cancel(); - drake.cancel(); - drake.cancel(); - drake.cancel(); - }, 'dragula ignores multiple calls to drake.cancel'); - st.end(); - }); - t.end(); +test('cancel does not throw when not dragging', function (t) { + t.test('a single time', function once (st) { + var drake = dragula(); + st.doesNotThrow(function () { + drake.cancel(); + }, 'dragula ignores a single call to drake.cancel'); + st.end(); + }); + t.test('multiple times', function once (st) { + var drake = dragula(); + st.doesNotThrow(function () { + drake.cancel(); + drake.cancel(); + drake.cancel(); + drake.cancel(); + }, 'dragula ignores multiple calls to drake.cancel'); + st.end(); }); + t.end(); +}); + +function domTests(t, root) { - test('when dragging and cancel gets called, nothing happens', function (t) { + 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]); @@ -55,7 +56,7 @@ function allTests(t, root) { t.end(); }); - test('when dragging and cancel gets called, cancel event is emitted', function (t) { + 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]); @@ -76,7 +77,7 @@ function allTests(t, root) { } }); - test('when dragging a copy and cancel gets called, default does not revert', function (t) { + 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'); @@ -101,7 +102,7 @@ function allTests(t, root) { } }); - test('when dragging a copy and cancel gets called, revert is executed', function (t) { + 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'); @@ -124,4 +125,4 @@ function allTests(t, root) { t.equal(container, div, 'cancel was invoked with container'); } }); -} \ No newline at end of file +} diff --git a/test/destroy.js b/test/destroy.js index 6b62ef91..3f56261e 100644 --- a/test/destroy.js +++ b/test/destroy.js @@ -3,7 +3,7 @@ var test = require('tape'); var dragula = require('..'); test('with normal DOM', function(t) { - allTests(t, document.body); + domTests(t, document.body); t.end(); }); @@ -15,33 +15,34 @@ test('with nested shadow DOM', function(t) { div.shadowRoot.appendChild(div2); document.body.appendChild(div); - allTests(t, div2.shadowRoot); + domTests(t, div2.shadowRoot); t.end(); }); -function allTests(t, root) { - test('destroy does not throw when not dragging, destroyed, or whatever', function (t) { - t.test('a single time', function once (st) { - var drake = dragula(); - st.doesNotThrow(function () { - drake.destroy(); - }, 'dragula bites into a single call to drake.destroy'); - st.end(); - }); - t.test('multiple times', function once (st) { - var drake = dragula(); - st.doesNotThrow(function () { - drake.destroy(); - drake.destroy(); - drake.destroy(); - drake.destroy(); - }, 'dragula bites into multiple calls to drake.destroy'); - st.end(); - }); - t.end(); +test('destroy does not throw when not dragging, destroyed, or whatever', function (t) { + t.test('a single time', function once (st) { + var drake = dragula(); + st.doesNotThrow(function () { + drake.destroy(); + }, 'dragula bites into a single call to drake.destroy'); + st.end(); + }); + t.test('multiple times', function once (st) { + var drake = dragula(); + st.doesNotThrow(function () { + drake.destroy(); + drake.destroy(); + drake.destroy(); + drake.destroy(); + }, 'dragula bites into multiple calls to drake.destroy'); + st.end(); }); + t.end(); +}); - test('when dragging and destroy gets called, nothing happens', function (t) { +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]); @@ -54,7 +55,7 @@ function allTests(t, root) { t.end(); }); - test('when dragging and destroy gets called, dragend event is emitted gracefully', function (t) { + 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]); @@ -70,7 +71,7 @@ function allTests(t, root) { } }); - test('when dragging a copy and destroy gets called, default does not revert', function (t) { + 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'); @@ -95,7 +96,7 @@ function allTests(t, root) { } }); - test('when dragging a copy and destroy gets called, revert is executed', function (t) { + 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'); @@ -118,4 +119,4 @@ function allTests(t, root) { t.equal(container, div, 'cancel was invoked with container'); } }); -} \ No newline at end of file +} diff --git a/test/drag.js b/test/drag.js index 9a48bf3d..ba92309e 100644 --- a/test/drag.js +++ b/test/drag.js @@ -5,7 +5,7 @@ var events = require('./lib/events'); var dragula = require('..'); test('with normal DOM', function(t) { - allTests(t, document.body); + domTests(t, document.body); t.end(); }); @@ -17,11 +17,11 @@ test('with nested shadow DOM', function(t) { div.shadowRoot.appendChild(div2); document.body.appendChild(div); - allTests(t, div2.shadowRoot); + domTests(t, div2.shadowRoot); t.end(); }); -function allTests(t, root) { +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 }); @@ -272,4 +272,4 @@ function allTests(t, root) { function always () { return true; } function never () { return false; } -} \ No newline at end of file +} diff --git a/test/end.js b/test/end.js index 8d168433..173b74b7 100644 --- a/test/end.js +++ b/test/end.js @@ -3,7 +3,7 @@ var test = require('tape'); var dragula = require('..'); test('with normal DOM', function(t) { - allTests(t, document.body); + domTests(t, document.body); t.end(); }); @@ -15,33 +15,33 @@ test('with nested shadow DOM', function(t) { div.shadowRoot.appendChild(div2); document.body.appendChild(div); - allTests(t, div2.shadowRoot); + domTests(t, div2.shadowRoot); t.end(); }); -function allTests(t, root) { - test('end does not throw when not dragging', function (t) { - t.test('a single time', function once (st) { - var drake = dragula(); - st.doesNotThrow(function () { - drake.end(); - }, 'dragula ignores a single call to drake.end'); - st.end(); - }); - t.test('multiple times', function once (st) { - var drake = dragula(); - st.doesNotThrow(function () { - drake.end(); - drake.end(); - drake.end(); - drake.end(); - }, 'dragula ignores multiple calls to drake.end'); - st.end(); - }); - t.end(); +test('end does not throw when not dragging', function (t) { + t.test('a single time', function once (st) { + var drake = dragula(); + st.doesNotThrow(function () { + drake.end(); + }, 'dragula ignores a single call to drake.end'); + st.end(); + }); + t.test('multiple times', function once (st) { + var drake = dragula(); + st.doesNotThrow(function () { + drake.end(); + drake.end(); + drake.end(); + drake.end(); + }, 'dragula ignores multiple calls to drake.end'); + st.end(); }); + t.end(); +}); - test('when already dragging, .end() ends (cancels) previous drag', function (t) { +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'); @@ -65,7 +65,7 @@ function allTests(t, root) { } }); - test('when already dragged, ends (drops) previous drag', function (t) { + 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'); @@ -92,4 +92,4 @@ function allTests(t, root) { t.equal(target, div2, 'drop invoked with correct target'); } }); -} \ No newline at end of file +} diff --git a/test/events.js b/test/events.js index 2f449d06..56d37a8f 100644 --- a/test/events.js +++ b/test/events.js @@ -5,7 +5,7 @@ var events = require('./lib/events'); var dragula = require('..'); test('with normal DOM', function(t) { - allTests(t, document.body); + domTests(t, document.body); t.end(); }); @@ -17,11 +17,11 @@ test('with nested shadow DOM', function(t) { div.shadowRoot.appendChild(div2); document.body.appendChild(div); - allTests(t, div2.shadowRoot); + domTests(t, div2.shadowRoot); t.end(); }); -function allTests(t, root) { +function domTests(t, root) { t.test('.start() emits "cloned" for copies', function (t) { var div = document.createElement('div'); var item = document.createElement('div'); diff --git a/test/remove.js b/test/remove.js index 04b72b76..549578e2 100644 --- a/test/remove.js +++ b/test/remove.js @@ -5,7 +5,7 @@ var events = require('./lib/events'); var dragula = require('..'); test('with normal DOM', function(t) { - allTests(t, document.body); + domTests(t, document.body); t.end(); }); @@ -17,33 +17,34 @@ test('with nested shadow DOM', function(t) { div.shadowRoot.appendChild(div2); document.body.appendChild(div); - allTests(t, div2.shadowRoot); + domTests(t, div2.shadowRoot); t.end(); }); -function allTests(t, root) { - test('remove does not throw when not dragging', function (t) { - t.test('a single time', function once (st) { - var drake = dragula(); - st.doesNotThrow(function () { - drake.remove(); - }, 'dragula ignores a single call to drake.remove'); - st.end(); - }); - t.test('multiple times', function once (st) { - var drake = dragula(); - st.doesNotThrow(function () { - drake.remove(); - drake.remove(); - drake.remove(); - drake.remove(); - }, 'dragula ignores multiple calls to drake.remove'); - st.end(); - }); - t.end(); +test('remove does not throw when not dragging', function (t) { + t.test('a single time', function once (st) { + var drake = dragula(); + st.doesNotThrow(function () { + drake.remove(); + }, 'dragula ignores a single call to drake.remove'); + st.end(); + }); + t.test('multiple times', function once (st) { + var drake = dragula(); + st.doesNotThrow(function () { + drake.remove(); + drake.remove(); + drake.remove(); + drake.remove(); + }, 'dragula ignores multiple calls to drake.remove'); + st.end(); }); + t.end(); +}); + +function domTests(t, root) { - test('when dragging and remove gets called, element is removed', function (t) { + 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]); @@ -56,7 +57,7 @@ function allTests(t, root) { t.end(); }); - test('when dragging and remove gets called, remove event is emitted', function (t) { + 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]); @@ -77,7 +78,7 @@ function allTests(t, root) { } }); - test('when dragging a copy and remove gets called, cancel event is emitted', function (t) { + 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 }); @@ -99,4 +100,4 @@ function allTests(t, root) { t.equal(container, null, 'cancel was invoked with container'); } }); -} \ No newline at end of file +} From 102fa6f053084ee6709a8913140ca0e904e30224 Mon Sep 17 00:00:00 2001 From: Thomas Smith Date: Mon, 20 Feb 2017 21:21:41 +0100 Subject: [PATCH 3/4] Fix elemFromPoint to always return non-null --- dragula.js | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/dragula.js b/dragula.js index 49f7ca54..9db991a8 100644 --- a/dragula.js +++ b/dragula.js @@ -559,8 +559,14 @@ function getElementBehindPoint (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) { - el = el.shadowRoot.elementFromPoint(x, y); + maybeElem = el.shadowRoot.elementFromPoint(x, y); + if (maybeElem) { + el = maybeElem; + } else { + return el; + } } return el; } From 91cae2b53a93fc6032c3bac2ac498536c3b77401 Mon Sep 17 00:00:00 2001 From: Thomas Smith Date: Mon, 26 Feb 2018 12:32:37 +0100 Subject: [PATCH 4/4] Fix getParent for anchor tags --- dragula.js | 2 +- test/events.js | 4 ++-- test/remove.js | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/dragula.js b/dragula.js index 9db991a8..b99724e7 100644 --- a/dragula.js +++ b/dragula.js @@ -576,7 +576,7 @@ 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.host || 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/events.js b/test/events.js index 56d37a8f..d32fdd22 100644 --- a/test/events.js +++ b/test/events.js @@ -16,7 +16,7 @@ test('with nested shadow DOM', function(t) { div2.createShadowRoot(); div.shadowRoot.appendChild(div2); document.body.appendChild(div); - + domTests(t, div2.shadowRoot); t.end(); }); @@ -146,7 +146,7 @@ function domTests(t, root) { 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'); + t.equal(container, undefined, 'container matches expectation'); } }); diff --git a/test/remove.js b/test/remove.js index 549578e2..597430c6 100644 --- a/test/remove.js +++ b/test/remove.js @@ -16,7 +16,7 @@ test('with nested shadow DOM', function(t) { div2.createShadowRoot(); div.shadowRoot.appendChild(div2); document.body.appendChild(div); - + domTests(t, div2.shadowRoot); t.end(); }); @@ -97,7 +97,7 @@ function domTests(t, root) { 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.equal(container, undefined, 'cancel was invoked with container'); } }); }