Skip to content

Commit

Permalink
Add scrolling from bevacqua#449 (with modifications)
Browse files Browse the repository at this point in the history
Merge remote-tracking branch 'scrollfork2/fix/scroll' into scroll

# Conflicts:
#	dist/dragula.js
#	dist/dragula.min.js
  • Loading branch information
benelliottgsa committed Nov 13, 2017
2 parents 8002d72 + dd20e3c commit 37612f4
Show file tree
Hide file tree
Showing 7 changed files with 330 additions and 10 deletions.
109 changes: 105 additions & 4 deletions dist/dragula.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion dist/dragula.min.js

Large diffs are not rendered by default.

107 changes: 104 additions & 3 deletions dragula.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ var crossvent = require('crossvent');
var classes = require('./classes');
var doc = document;
var documentElement = doc.documentElement;
var _autoScrollingInterval; // reference to auto scrolling
// A simple requestAnimationFrame polyfill
var raf = window.requestAnimationFrame || function(callback){ return setTimeout(callback, 1000 / 60); };
var caf = window.cancelAnimationFrame || function(cafID){ clearTimeout(cafID); };

function dragula (initialContainers, options) {
var len = arguments.length;
Expand Down Expand Up @@ -39,6 +43,7 @@ function dragula (initialContainers, options) {
if (o.direction === void 0) { o.direction = 'vertical'; }
if (o.ignoreInputTextSelection === void 0) { o.ignoreInputTextSelection = true; }
if (o.mirrorContainer === void 0) { o.mirrorContainer = doc.body; }
if (o.scrollEdge === void 0) { o.scrollEdge = 36; }

var drake = emitter({
containers: o.containers,
Expand Down Expand Up @@ -214,6 +219,7 @@ function dragula (initialContainers, options) {

function end () {
if (!drake.dragging) {
caf(_autoScrollingInterval);
return;
}
var item = _copy || _item;
Expand Down Expand Up @@ -299,6 +305,7 @@ function dragula (initialContainers, options) {

function cleanup () {
var item = _copy || _item;
caf(_autoScrollingInterval);
ungrab();
removeMirrorImage();
if (item) {
Expand Down Expand Up @@ -351,16 +358,20 @@ function dragula (initialContainers, options) {
}

function drag (e) {
if (!_mirror) {
return;
}
if (!_mirror) { return; }
// For iframe. When dragging an item and mouse moves out of the iframe and
// mouseup, then decides to move back, the event will be 0 so we should
// just call cancel.
if (whichMouseButton(e) === 0) { cancel(); }

e.preventDefault();

var clientX = getCoord('clientX', e);
var clientY = getCoord('clientY', e);
var x = clientX - _offsetX;
var y = clientY - _offsetY;

// _mirror.style can be null if it is off the page:
_mirror.style.left = x + 'px';
_mirror.style.top = y + 'px';

Expand Down Expand Up @@ -391,6 +402,7 @@ function dragula (initialContainers, options) {
if (_copy && parent) {
parent.removeChild(item);
}
startScroll(_item, e, o);
return;
}
if (
Expand All @@ -405,6 +417,8 @@ function dragula (initialContainers, options) {
function moved (type) { drake.emit(type, item, _lastDropTarget, _source); }
function over () { if (changed) { moved('over'); } }
function out () { if (_lastDropTarget) { moved('out'); } }

startScroll(_item, e, o);
}

function spillOver (el) {
Expand Down Expand Up @@ -601,4 +615,91 @@ function getCoord (coord, e) {
return host[coord];
}

function getScrollContainer(node) {
if (node === null) { return null; }
// NOTE: Manually calculating height because IE's `clientHeight` isn't always
// reliable.
// var nodeOuterHeight = parseFloat(window.getComputedStyle(node).getPropertyValue('height')) +
// parseFloat(window.getComputedStyle(node).getPropertyValue('padding-top')) +
// parseFloat(window.getComputedStyle(node).getPropertyValue('padding-bottom'));

// We determine an element to be scrollable if its scroll height is larger than its computed height:
if (node.scrollHeight > Math.ceil(node.clientHeight)) { return node; }

var REGEX_BODY_HTML = new RegExp('(body|html)', 'i');

if (!REGEX_BODY_HTML.test(node.parentNode.tagName)) { return getScrollContainer(node.parentNode); }

return null;
}

function startAutoScrolling(node, amount, direction) {
_autoScrollingInterval = raf(function() {
startAutoScrolling(node, amount, direction);
});

return node[direction] += (amount * 0.25);
}

function startScroll(item, event, options) {
var scrollingElement = null;
var scrollEdge = options.scrollEdge;
var scrollSpeed = 20;
var scrollContainer = getScrollContainer(item);
var pageX = null;
var pageY = null;

if (event.touches) {
pageX = event.touches[0].pageX;
pageY = event.touches[0].pageY;
} else {
pageX = event.pageX;
pageY = event.pageY;
}

caf(_autoScrollingInterval);


// If a container contains the list that is scrollable
if (scrollContainer) {
// Scrolling vertically
if (pageY - getOffset(scrollContainer).top < scrollEdge) {
// If difference between y-coord of top of scroll container (getOffset(scrollContainer).top) and y-coord of mouse
// event is less than threshold, then start scrolling up:
startAutoScrolling(scrollContainer, -scrollSpeed, 'scrollTop');
} else if ((getOffset(scrollContainer).top + scrollContainer.getBoundingClientRect().height) - pageY < scrollEdge) {
// If difference between y-coord of bottom of scroll container (bottom = start of element + element height) and
// y-coord of mouse event is less than threshold, then start scrolling down:
startAutoScrolling(scrollContainer, scrollSpeed, 'scrollTop');
}

// Scrolling horizontally
if (pageX - scrollContainer.getBoundingClientRect().left < scrollEdge) {
startAutoScrolling(scrollContainer, -scrollSpeed, 'scrollLeft');
} else if ((getOffset(scrollContainer).left + scrollContainer.getBoundingClientRect().width) - pageX < scrollEdge) {
startAutoScrolling(scrollContainer, scrollSpeed, 'scrollLeft');
}

// If the window contains the list
} else {
scrollingElement = document.scrollingElement || document.documentElement || document.body;

// Scrolling vertically
// NOTE: Using `window.pageYOffset` here because IE doesn't have `window.scrollY`.
if ((pageY - window.pageYOffset) < scrollEdge) {
startAutoScrolling(scrollingElement, -scrollSpeed, 'scrollTop');
} else if ((window.innerHeight - (pageY - window.pageYOffset)) < scrollEdge) {
startAutoScrolling(scrollingElement, scrollSpeed, 'scrollTop');
}

// Scrolling horizontally
// NOTE: Using `window.pageXOffset` here because IE doesn't have `window.scrollX`.
if ((pageX - window.pageXOffset) < scrollEdge) {
startAutoScrolling(scrollingElement, -scrollSpeed, 'scrollLeft');
} else if ((window.innerWidth - (pageX - window.pageXOffset)) < scrollEdge) {
startAutoScrolling(scrollingElement, scrollSpeed, 'scrollLeft');
}
}
}

module.exports = dragula;
22 changes: 22 additions & 0 deletions example/example.css
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,28 @@ button:hover {
#right-lovehandles > div {
cursor: initial;
}
.scrollable {
display: block;
width: 100%;
overflow-y: auto;
height: 12em;
}

.scrollable--horizontal {
display: block;
max-width: 100%;
margin-top: 1.5em;
overflow-y: hidden;
overflow-x: auto;
}
.scrollable--horizontal .scroll {
display: block;
width: 1000px;
}
.scrollable--horizontal .scroll div {
display: inline-block;
width: auto;
}
.handle {
padding: 0 5px;
margin-right: 5px;
Expand Down
2 changes: 2 additions & 0 deletions example/example.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ dragula([$('left-copy-1tomany'), $('right-copy-1tomany')], {
});

dragula([sortable]);
dragula([document.querySelector('.scrollable')]);
dragula([document.querySelector('.scroll')]);

crossvent.add(sortable, 'click', clickHandler);

Expand Down
6 changes: 4 additions & 2 deletions example/example.min.js

Large diffs are not rendered by default.

92 changes: 92 additions & 0 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,98 @@ <h3 class='tagline'><span class='tagline-text'>Drag and drop so simple it hurts<
</code>
</pre>
</div>
<div class='parent'>
<label for='hy'>Need to see more while dragging? Sure we'll scroll for you.</label>
<div class='wrap'>
<div class="container scrollable">
<div>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</div>
<div>Integer luctus magna elementum nibh vestibulum, ut commodo justo vulputate.</div>
<div>Praesent in ex tempor, maximus arcu et, fermentum magna.</div>
<div>Suspendisse a urna et tellus commodo condimentum.</div>
<div>Suspendisse convallis nulla at sapien hendrerit dignissim.</div>
<div>Suspendisse ut ex in sem rutrum volutpat.</div>
<div>Nullam quis mauris et leo pretium tincidunt.</div>
<div>Sed sit amet mauris lobortis, auctor ligula quis, convallis dui.</div>
<div>Nulla id neque nec odio accumsan eleifend.</div>
<div>Donec eget quam in neque sollicitudin molestie.</div>
<div>Nunc ut est sed nisi eleifend commodo.</div>
<div>Nulla sollicitudin odio eu sollicitudin rhoncus.</div>
<div>Quisque ac tortor placerat, tempus turpis sit amet, mollis risus.</div>
<div>Morbi at arcu euismod, facilisis nisl condimentum, ultrices leo.</div>
<div>Vestibulum pulvinar quam id nisl dictum, quis ultricies dui laoreet.</div>
<div>Nunc sed nisl eu nisl accumsan tincidunt non at nibh.</div>
<div>Nullam bibendum leo vitae sollicitudin hendrerit.</div>
<div>Suspendisse imperdiet odio ut diam fermentum iaculis.</div>
<div>Vestibulum elementum sapien a purus facilisis egestas.</div>
<div>Pellentesque ac nulla quis ex congue pellentesque eu eleifend lacus.</div>
<div>Nunc rutrum lectus vitae ipsum facilisis, et tincidunt nisi dapibus.</div>
<div>Phasellus vehicula nisl quis felis rutrum, vel dictum est rutrum.</div>
<div>Nunc in orci vitae nunc hendrerit ultrices.</div>
<div>Sed scelerisque dui vel sapien congue, at vestibulum orci pretium.</div>
<div>Nulla a nisl vel massa rhoncus gravida molestie id leo.</div>
<div>Integer a dui iaculis nisl tincidunt convallis.</div>
<div>In quis purus eu tellus ultricies egestas ut in quam.</div>
<div>Integer fringilla metus nec lorem mattis, vel gravida mauris vulputate.</div>
<div>Nullam scelerisque sapien ac dui euismod vestibulum.</div>
<div>Aliquam ac erat vel dolor gravida viverra.</div>
<div>Sed vitae ex accumsan, venenatis dolor quis, molestie mi.</div>
<div>Duis quis libero sit amet mauris rutrum porta a at augue.</div>
<div>Cras vitae magna nec dui vestibulum pharetra.</div>
<div>In vitae libero ac odio consectetur lobortis.</div>
<div>Fusce congue ante nec pretium consequat.</div>
<div>Aliquam efficitur nulla ac risus scelerisque, id viverra lacus tempus.</div>
<div>Mauris ornare eros at lacus efficitur posuere quis et ligula.</div>
<div>In in ipsum id justo vulputate lobortis vel vitae ipsum.</div>
<div>Proin at ipsum bibendum, finibus mi ac, accumsan felis.</div>
<div>Aenean malesuada massa id tempus mollis.</div>
<div>Mauris pellentesque dolor vitae urna condimentum, sed sodales elit commodo.</div>
<div>Sed sollicitudin elit et tellus tincidunt maximus.</div>
<div>Nunc eleifend neque at lorem dapibus mollis.</div>
<div>Aliquam ullamcorper massa eu aliquam viverra.</div>
<div>Vestibulum vitae quam id enim consectetur facilisis.</div>
<div>Curabitur viverra justo vel eros tempor ornare.</div>
<div>Duis gravida augue sit amet dictum cursus.</div>
<div>Mauris ut massa convallis, hendrerit massa ut, maximus nulla.</div>
<div>Aenean vitae leo sit amet felis faucibus porta ut ut nibh.</div>
<div>Phasellus ac massa sit amet purus vehicula tempus.</div>
<div>Vestibulum pharetra eros id odio pellentesque, ac aliquet risus lobortis.</div>
<div>Maecenas gravida purus non interdum dignissim.</div>
<div>Mauris molestie mi congue nibh viverra convallis.</div>
<div>Vivamus eget sem nec lorem sagittis mattis.</div>
<div>Donec pellentesque turpis et magna pretium hendrerit.</div>
<div>Morbi rhoncus quam quis ligula pellentesque tincidunt.</div>
<div>Curabitur pretium erat sed orci posuere rhoncus.</div>
<div>Donec congue sapien nec convallis maximus.</div>
<div>Vivamus consectetur justo et consequat tempor.</div>
<div>Mauris scelerisque justo vitae ligula pretium, non auctor justo cursus.</div>
<div>Mauris congue nunc porta tortor sagittis dapibus.</div>
<div>Morbi hendrerit mauris vitae imperdiet condimentum.</div>
<div>Nulla volutpat tellus sit amet sem vehicula viverra.</div>
<div>Nullam aliquet dui nec pharetra gravida.</div>
</div>
</div>

<div class="wrap">
<div class="scrollable scrollable--horizontal">
<div class="container scroll">
<div>Morbi rhoncus quam quis ligula pellentesque tincidunt.</div>
<div>Curabitur pretium erat sed orci posuere rhoncus.</div>
<div>Donec congue sapien nec convallis maximus.</div>
<div>Vivamus consectetur justo et consequat tempor.</div>
<div>Mauris scelerisque justo vitae ligula pretium, non auctor justo cursus.</div>
<div>Mauris congue nunc porta tortor sagittis dapibus.</div>
<div>Morbi hendrerit mauris vitae imperdiet condimentum.</div>
<div>Nulla volutpat tellus sit amet sem vehicula viverra.</div>
<div>Nullam aliquet dui nec pharetra gravida.</div>
</div>
</div>
</div>
<pre>
<code>
dragula([document.querySelector('.scrollable')]);
</code>
</pre>
</div>
<div class='parent'>
<label for='hy'>Copying stuff is common too, so we made it easy for you.</label>
<div class='wrapper'>
Expand Down

0 comments on commit 37612f4

Please sign in to comment.