Add layout review multi-select controls

This commit is contained in:
Sean McElwain 2026-05-25 23:51:30 -05:00
parent 4dcb6ebd0e
commit 1e55035f09
1 changed files with 33 additions and 1 deletions

View File

@ -5,6 +5,10 @@
box-shadow: 0 0 0 4px rgba(34, 197, 94, 0.18) !important;
font-weight: 800 !important;
}
body.layout-multi-select-active #layout-word-popover {
display: none !important;
}
</style>
{% extends "base.html" %}
@ -1926,6 +1930,9 @@ document.addEventListener("DOMContentLoaded", () => {
<div class="word-ribbon-group">
<div class="word-ribbon-row">
<button type="button" class="layout-tool-btn active" id="layout-tool-select">Select</button>
<button type="button" class="layout-tool-btn" id="layout-select-all">Select All</button>
<button type="button" class="layout-tool-btn" id="layout-multi-select">Multi</button>
<button type="button" class="layout-tool-btn" id="layout-clear-selection">Clear</button>
<button type="button" class="layout-tool-btn" id="layout-tool-pan">Pan</button>
<button type="button" class="layout-tool-btn" id="layout-tool-add">Add</button>
<button type="button" class="layout-tool-btn danger" id="layout-delete-word">Delete</button>
@ -2504,6 +2511,8 @@ const HANDLE_SIZE_PX = 14;
const page = pages[0];
let words = JSON.parse(JSON.stringify(page.words || []));
let selectedId = null;
let selectedIds = new Set();
let multiSelectMode = false;
let tool = "select";
let zoom = 1;
let dragState = null;
@ -3070,7 +3079,7 @@ function refreshSelectionUI(opts = {}) {
const y2 = bbox[3] * scaleY;
const w = Math.max(1, x2 - x1);
const h = Math.max(1, y2 - y1);
const selected = String(word.id) === String(selectedId);
const selected = selectedIds.has(String(word.id)) || String(word.id) === String(selectedId);
if (showText) {
drawReplicaText(word, bbox, x1, y1, x2, y2, w, h, scaleX, scaleY);
@ -3558,6 +3567,7 @@ function refreshSelectionUI(opts = {}) {
if (popoverEl) popoverEl.style.display = "none";
canvas.style.cursor = "default";
refreshSelectionUI({ forceText: true });
if (multiSelectMode) hidePopover();
renderCanvas();
setStatus("No selection");
return;
@ -3727,6 +3737,28 @@ function refreshSelectionUI(opts = {}) {
document.getElementById("layout-nudge-down")?.addEventListener("click", () => nudge(0, 1));
document.getElementById("layout-tool-select")?.addEventListener("click", () => setTool("select"));
document.getElementById("layout-select-all")?.addEventListener("click", () => {
selectedIds = new Set(words.map(w => String(w.id)));
selectedId = Array.from(selectedIds).at(-1) || null;
refreshSelectionUI({ forceText: true });
if (multiSelectMode) hidePopover();
renderCanvas();
setStatus("Selected all: " + selectedIds.size);
});
document.getElementById("layout-clear-selection")?.addEventListener("click", () => {
selectedIds.clear();
selectedId = null;
refreshSelectionUI({ forceText: true });
renderCanvas();
setStatus("Selection cleared");
});
document.getElementById("layout-multi-select")?.addEventListener("click", () => {
multiSelectMode = !multiSelectMode;
document.getElementById("layout-multi-select")?.classList.toggle("active", multiSelectMode);
document.body.classList.toggle("layout-multi-select-active", multiSelectMode);
if (multiSelectMode) hidePopover();
setStatus(multiSelectMode ? "Multi-select on" : "Multi-select off");
});
document.getElementById("layout-tool-pan")?.addEventListener("click", () => setTool("pan"));
document.getElementById("layout-tool-add")?.addEventListener("click", () => setTool("add"));