From 627efc3b2620d75fcf2deab170187ba2e082417c Mon Sep 17 00:00:00 2001 From: tv Date: Mon, 2 Nov 2026 21:43:41 +0100 Subject: dashboard: pin with middle button --- src/api/dashboard/dashboard.html | 43 +++++++++++++++++----------------------- 1 file changed, 18 insertions(+), 25 deletions(-) (limited to 'src/api/dashboard/dashboard.html') diff --git a/src/api/dashboard/dashboard.html b/src/api/dashboard/dashboard.html index afb8ea5..7125ad9 100644 --- a/src/api/dashboard/dashboard.html +++ b/src/api/dashboard/dashboard.html @@ -252,7 +252,7 @@ class="toggle">messages: on
drag to pan, wheel or pinch to zoom, turn with two fingers; - drag a node to move it, double-click it to pin it there or let it go + drag a node to move it, middle-click it to pin it there or let it go
@@ -1007,7 +1007,7 @@ function renderGraph() { (dormant ? " (dormant)" : "") + (clock && clock.off ? " (clock " + seconds(clock.offsetMs) + " off the swarm's, ±" + clock.withinMs + " ms)" : "")); - // Pinned (double-clicked): a dot in the middle. + // Pinned (middle-clicked): a dot in the middle. const pin = pinned.has(id) ? [drawing("pin " + id, "circle", { cx: p.x, cy: p.y, r: 2, fill: member.self || reported ? "var(--panel)" : "var(--fg)", "pointer-events": "none" })] : []; @@ -1613,21 +1613,20 @@ graph.addEventListener("pointerdown", event => { // Not the browser's drag and drop of the picture. graph.addEventListener("dragstart", event => event.preventDefault()); // A node: dragged, it moves, held where the pointer is (`grabbed`) until let go; a click, -// it is in focus; a second one soon after pins it where it is (`pinned`: the layout -// leaves it there), or lets it go if pinned (`unpin`), and so does a second press soon -// after that drags it (pinned where it's dropped). Told apart here: the map holds the -// pointer while pressed (`pressing`), so the browser's clicks and double-clicks go to -// the map, not the node. -let lastNodeClick = { id: null, at: 0 }; -const DOUBLE_CLICK_MS = 400; +// it is in focus. A middle click pins it where it is (`pinned`: the layout leaves it +// there), or lets it go if pinned (`unpin`); dragged with the middle button, it is +// pinned where it's dropped. Told apart here: the map holds the pointer while pressed +// (`pressing`), so the browser's clicks go to the map, not the node. let grabbed = null; -// Of the press under way on a node: whether it's the second of a double-click, and -// whether it moved the node. -let secondPress = false, dragMoved = false; +// Of the press under way on a node: whether it's the middle button's, and whether it +// moved the node. +let middlePress = false, dragMoved = false; function drag(event, id) { const p = positions.get(id), from = { x: p.x, y: p.y }; grabbed = id; - secondPress = lastNodeClick.id === id && performance.now() - lastNodeClick.at < DOUBLE_CLICK_MS; + middlePress = event.button === 1; + // Not the browser's scrolling by the middle button. + if (middlePress) event.preventDefault(); dragMoved = false; pressing(event, (dx, dy) => { dragMoved = true; @@ -1639,25 +1638,19 @@ function drag(event, id) { // Dynamic: the others follow it at once. if (byRtt) settle(); }, () => { - const now = performance.now(); - if (lastNodeClick.id === id && now - lastNodeClick.at < DOUBLE_CLICK_MS) { - lastNodeClick = { id: null, at: now }; - if (pinned.has(id)) unpin(id); else pin(id); - } else { - lastNodeClick = { id, at: now }; - focus(id); - } + if (!middlePress) focus(id); + else if (pinned.has(id)) unpin(id); + else pin(id); }); } // A dragged node let go of: dynamic, it moves to its place among the others again; -// dragged by a double-click's second press, its pin toggled. +// dragged with the middle button, it is pinned there. function dropped() { if (grabbed === null) return; const id = grabbed; grabbed = null; - if (dragMoved && secondPress) { - lastNodeClick = { id: null, at: 0 }; - if (pinned.has(id)) unpin(id); else pin(id); + if (dragMoved && middlePress) { + pin(id); return; } if (byRtt) settle(); -- cgit v1.3.1