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 --- docs/dashboard.md | 8 ++++---- src/api/dashboard/dashboard.html | 43 +++++++++++++++++----------------------- 2 files changed, 22 insertions(+), 29 deletions(-) diff --git a/docs/dashboard.md b/docs/dashboard.md index 6a75036..d9bbaa5 100644 --- a/docs/dashboard.md +++ b/docs/dashboard.md @@ -149,10 +149,10 @@ measured. * **Drag a node**: move it. On a dynamic map, the others follow at once, and once let go of, it moves back among them; on a static map it stays where it is put until the map is laid out again. -* **Double-click a node**: pin it where it is (a dot in its middle): the layout leaves - it there. A double-click whose second press drags the node pins it where it's - dropped. Double-clicked again, it's let go, and moves to its place among the others - (on a static map, only it moves). +* **Middle-click a node**: pin it where it is (a dot in its middle): the layout leaves + it there. Dragged with the middle button, it is pinned where it's dropped. + Middle-clicked again, it's let go, and moves to its place among the others (on a + static map, only it moves). The map is laid out when the page opens, and again when the window or the box is resized. A member that comes later is placed among the others, which stay where they 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