Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 7f9235dbdc | |||
| bb3ac1c946 |
119
Asset/js/drag-autoscroll.js
Normal file
119
Asset/js/drag-autoscroll.js
Normal file
@@ -0,0 +1,119 @@
|
|||||||
|
/*
|
||||||
|
* TweakDrag -- auto-scroll the board while dragging a card near a screen edge.
|
||||||
|
*
|
||||||
|
* Kanboard drags cards with jQuery UI sortable. The board does not scroll during a drag
|
||||||
|
* (jQuery UI's autoscroll is unreliable horizontally, and on touch the bundled Touch Punch
|
||||||
|
* shim suppresses native scrolling while a card is held), so you can only drop onto columns
|
||||||
|
* already on screen. This scrolls #board-container while a card drag is active and the
|
||||||
|
* pointer nears the left/right edge, with a smooth continuous speed that grows toward the
|
||||||
|
* edge -- so you can drag a card to the edge and roll the board to a far column.
|
||||||
|
*
|
||||||
|
* It only acts during an active card drag near an edge, so it is harmless when idle. Works
|
||||||
|
* on desktop (mouse) and mobile (touch, via Touch Punch). No core changes.
|
||||||
|
*/
|
||||||
|
(function () {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
var EDGE_ZONE = 50; // px from the board edge where auto-scroll begins
|
||||||
|
var MAX_SPEED = 22; // px per animation frame at the very edge
|
||||||
|
var EASE = 1; // 1 = linear ramp, 2 = gentle-then-fast
|
||||||
|
|
||||||
|
var jq = window.jQuery;
|
||||||
|
if (!jq) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var container = null;
|
||||||
|
var dragging = false;
|
||||||
|
var rafId = 0;
|
||||||
|
var lastX = 0;
|
||||||
|
var lastY = 0;
|
||||||
|
|
||||||
|
function onMove(e) {
|
||||||
|
if (e.touches && e.touches.length) {
|
||||||
|
lastX = e.touches[0].clientX;
|
||||||
|
lastY = e.touches[0].clientY;
|
||||||
|
} else {
|
||||||
|
lastX = e.clientX;
|
||||||
|
lastY = e.clientY;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Distance is px from the edge; returns 0 at the zone border up to MAX_SPEED at the edge.
|
||||||
|
function speedFor(distance) {
|
||||||
|
var p = (EDGE_ZONE - distance) / EDGE_ZONE;
|
||||||
|
if (p <= 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (p > 1) {
|
||||||
|
p = 1;
|
||||||
|
}
|
||||||
|
if (EASE !== 1) {
|
||||||
|
p = Math.pow(p, EASE);
|
||||||
|
}
|
||||||
|
return MAX_SPEED * p;
|
||||||
|
}
|
||||||
|
|
||||||
|
function step() {
|
||||||
|
if (!dragging || !container) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var rect = container.getBoundingClientRect();
|
||||||
|
var dLeft = lastX - rect.left;
|
||||||
|
var dRight = rect.right - lastX;
|
||||||
|
var speed = 0;
|
||||||
|
|
||||||
|
if (dLeft < EDGE_ZONE) {
|
||||||
|
speed = -speedFor(dLeft);
|
||||||
|
} else if (dRight < EDGE_ZONE) {
|
||||||
|
speed = speedFor(dRight);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (speed !== 0) {
|
||||||
|
var before = container.scrollLeft;
|
||||||
|
container.scrollLeft = before + speed;
|
||||||
|
|
||||||
|
// Only when the board actually moved: nudge jQuery UI to recompute drop
|
||||||
|
// positions so the placeholder follows onto the newly revealed column.
|
||||||
|
if (container.scrollLeft !== before) {
|
||||||
|
document.dispatchEvent(new MouseEvent("mousemove", {
|
||||||
|
clientX: lastX,
|
||||||
|
clientY: lastY,
|
||||||
|
bubbles: true
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
rafId = window.requestAnimationFrame(step);
|
||||||
|
}
|
||||||
|
|
||||||
|
function startLoop() {
|
||||||
|
container = document.getElementById("board-container");
|
||||||
|
if (!container) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
dragging = true;
|
||||||
|
if (!rafId) {
|
||||||
|
rafId = window.requestAnimationFrame(step);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function stopLoop() {
|
||||||
|
dragging = false;
|
||||||
|
if (rafId) {
|
||||||
|
window.cancelAnimationFrame(rafId);
|
||||||
|
rafId = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Track the pointer at all times (cheap; only used while dragging).
|
||||||
|
document.addEventListener("mousemove", onMove, true);
|
||||||
|
document.addEventListener("touchmove", onMove, true);
|
||||||
|
document.addEventListener("pointermove", onMove, true);
|
||||||
|
|
||||||
|
// A card drag started / stopped. jQuery UI sortable fires these (on touch too, via
|
||||||
|
// Touch Punch); delegated on the document so board redraws need no rebinding.
|
||||||
|
jq(document).on("sortstart", startLoop);
|
||||||
|
jq(document).on("sortstop", stopLoop);
|
||||||
|
})();
|
||||||
@@ -25,6 +25,12 @@ class Plugin extends Base
|
|||||||
'template' => 'plugins/TweakDrag/Asset/js/drag-scroll.js',
|
'template' => 'plugins/TweakDrag/Asset/js/drag-scroll.js',
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Auto-scroll the board while dragging a card near a screen edge. Always loaded;
|
||||||
|
// it only acts during an active card drag.
|
||||||
|
$this->hook->on('template:layout:js', array(
|
||||||
|
'template' => 'plugins/TweakDrag/Asset/js/drag-autoscroll.js',
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getPluginName()
|
public function getPluginName()
|
||||||
@@ -44,7 +50,7 @@ class Plugin extends Base
|
|||||||
|
|
||||||
public function getPluginVersion()
|
public function getPluginVersion()
|
||||||
{
|
{
|
||||||
return '0.3.0';
|
return '1.0.0';
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getPluginHomepage()
|
public function getPluginHomepage()
|
||||||
|
|||||||
@@ -9,6 +9,8 @@ A Kanboard plugin that groups board dragging and spacing tweaks, configurable un
|
|||||||
apart and to touch.
|
apart and to touch.
|
||||||
- **Mobile drag handle size** -- enlarge the card drag handle Kanboard shows on mobile so
|
- **Mobile drag handle size** -- enlarge the card drag handle Kanboard shows on mobile so
|
||||||
it is easy to grab with a finger.
|
it is easy to grab with a finger.
|
||||||
|
- **Drag auto-scroll** -- while dragging a card, the board scrolls when the pointer nears a
|
||||||
|
screen edge, so you can reach a column that is off screen (desktop and mobile).
|
||||||
|
|
||||||
These options were originally part of the ShrinkVertically plugin and moved here so that
|
These options were originally part of the ShrinkVertically plugin and moved here so that
|
||||||
drag/touch behaviour can grow on its own (planned: mobile drag-to-move cards, and a drag
|
drag/touch behaviour can grow on its own (planned: mobile drag-to-move cards, and a drag
|
||||||
@@ -30,6 +32,12 @@ movement threshold so ending a drag does not open the task) without bloating tha
|
|||||||
is hard to grab. FontAwesome icons are sized by `font-size`, so a single rule scales the
|
is hard to grab. FontAwesome icons are sized by `font-size`, so a single rule scales the
|
||||||
handle from the `--td-handle-size` CSS variable. It is inert on desktop, where Kanboard
|
handle from the `--td-handle-size` CSS variable. It is inert on desktop, where Kanboard
|
||||||
keeps the handle hidden.
|
keeps the handle hidden.
|
||||||
|
- **Drag auto-scroll**: a script (`Asset/js/drag-autoscroll.js`) listens for jQuery UI
|
||||||
|
sortable's `sortstart`/`sortstop` (which also fire on touch via Kanboard's bundled Touch
|
||||||
|
Punch) and, while a card drag is active, scrolls `#board-container` when the pointer nears
|
||||||
|
its left/right edge. Speed ramps up smoothly toward the edge. After each scroll step it
|
||||||
|
dispatches a synthetic `mousemove` so jQuery UI moves the drop placeholder onto the newly
|
||||||
|
revealed column. It only acts during an active drag, so it is idle otherwise.
|
||||||
|
|
||||||
## Requirements
|
## Requirements
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user