From 876037792788b3e8358be128d55208752d180c12 Mon Sep 17 00:00:00 2001 From: Ruben Carlo Benante Date: Mon, 6 Jul 2026 07:52:21 -0300 Subject: [PATCH] fix background drag-scroll dying after card move; delegate to document, body marker; v1.1 --- Asset/css/tweak-drag.css | 9 +++++---- Asset/js/drag-scroll.js | 38 ++++++++++++++++++++++++++------------ Plugin.php | 2 +- VERSION | 2 +- 4 files changed, 33 insertions(+), 18 deletions(-) diff --git a/Asset/css/tweak-drag.css b/Asset/css/tweak-drag.css index a64d8d6..cd6708d 100644 --- a/Asset/css/tweak-drag.css +++ b/Asset/css/tweak-drag.css @@ -6,16 +6,17 @@ * --td-column-gap value, so it is not in this static stylesheet. * * Below: click-and-drag horizontal scrolling (added by Asset/js/drag-scroll.js when the - * "Drag the board background to scroll" setting is enabled). The .td-drag-scroll class is - * set on #board-container by the script, so these rules are inert when disabled. A grab + * "Drag the board background to scroll" setting is enabled). The .td-drag-scroll marker is + * set on by the script (not on #board-container, which Kanboard replaces on every + * card move), so these rules are inert when disabled and survive board rebuilds. A grab * cursor advertises the empty background; cards keep the normal cursor since pressing them * does a card drag, not a pan. */ -#board-container.td-drag-scroll { +body.td-drag-scroll #board-container { cursor: grab; } -#board-container.td-drag-scroll .task-board { +body.td-drag-scroll #board-container .task-board { cursor: default; } diff --git a/Asset/js/drag-scroll.js b/Asset/js/drag-scroll.js index a4040d1..cbf5d8b 100644 --- a/Asset/js/drag-scroll.js +++ b/Asset/js/drag-scroll.js @@ -6,6 +6,13 @@ * pressing a task card, a drag handle, or any interactive control is ignored, so this * never interferes with Kanboard's own card and column drag-and-drop. * + * Resilience note: after a card drag Kanboard rebuilds the board with + * `$("#board-container").replaceWith(data)` (BoardDragAndDrop.refresh), destroying the + * element. So we must NOT bind to #board-container directly: we listen on `document` and + * re-resolve the container on each press, and the grab-cursor marker lives on + * (which is never replaced). Previously the mousedown listener and the cursor class were + * on the container, so background dragging stopped working after every card move. + * * Loaded only when the "Drag the board background to scroll" setting is enabled. */ (function () { @@ -21,34 +28,40 @@ } function init() { - var container = document.getElementById("board-container"); - - if (!container || container.getAttribute("data-td-drag") === "1") { + if (!document.getElementById("board-container") || document.body.getAttribute("data-td-drag") === "1") { return; } - container.setAttribute("data-td-drag", "1"); - container.classList.add("td-drag-scroll"); + // Marker on (stable) enables the grab cursor via CSS, surviving board rebuilds. + document.body.setAttribute("data-td-drag", "1"); + document.body.classList.add("td-drag-scroll"); var dragging = false; + var container = null; var startX = 0; var startScrollLeft = 0; - container.addEventListener("mousedown", function (e) { - // Left button only, and only on empty board background. - if (e.button !== 0 || isIgnored(e.target)) { + document.addEventListener("mousedown", function (e) { + if (e.button !== 0) { return; } + // Re-resolve the current container and only act on its empty background. + var c = document.getElementById("board-container"); + if (!c || !c.contains(e.target) || isIgnored(e.target)) { + return; + } + + container = c; dragging = true; startX = e.clientX; - startScrollLeft = container.scrollLeft; - container.classList.add("td-grabbing"); + startScrollLeft = c.scrollLeft; + document.body.classList.add("td-grabbing"); e.preventDefault(); }); document.addEventListener("mousemove", function (e) { - if (!dragging) { + if (!dragging || !container) { return; } container.scrollLeft = startScrollLeft - (e.clientX - startX); @@ -60,7 +73,8 @@ return; } dragging = false; - container.classList.remove("td-grabbing"); + container = null; + document.body.classList.remove("td-grabbing"); } document.addEventListener("mouseup", stop); diff --git a/Plugin.php b/Plugin.php index 5ee9e73..b6a2168 100644 --- a/Plugin.php +++ b/Plugin.php @@ -50,7 +50,7 @@ class Plugin extends Base public function getPluginVersion() { - return '1.0.0'; + return '1.1.0'; } public function getPluginHomepage() diff --git a/VERSION b/VERSION index b8bf011..9fa4ced 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -TweakDrag v1.0 +TweakDrag v1.1