diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/api/dashboard/dashboard.html | 64 |
1 files changed, 19 insertions, 45 deletions
diff --git a/src/api/dashboard/dashboard.html b/src/api/dashboard/dashboard.html index 6df3300..18c7ab1 100644 --- a/src/api/dashboard/dashboard.html +++ b/src/api/dashboard/dashboard.html @@ -76,7 +76,6 @@ section.collapsed { align-self: start; } section.collapsed h2 { margin: 0; } section.collapsed h2 .toggle { display: none; } - section.collapsed h2 button.add { display: none; } /* A choice beside a box's title (the console's filter). */ section h2 label.choice { font-size: 12px; text-transform: none; letter-spacing: 0; margin-left: 1em; cursor: pointer; } @@ -274,13 +273,9 @@ max-height: 20em; overflow: auto; } .note { color: var(--muted); font-style: italic; } .error { color: var(--bad); } - .tree button.add, #document-head button.add { font: inherit; line-height: 1; padding: 0 4px; margin-left: 4px; - color: var(--muted); background: none; border: 1px solid var(--line); border-radius: 3px; - cursor: pointer; } - .tree button.add:hover, #document-head button.add:hover { color: var(--fg); border-color: var(--muted); } .tree .nested { padding-left: 1.1em; } - /* The store's root is the box: its keys listed at the top level, its size and its "+" - in the title (`#document-head`). */ + /* The store's root is the box: its keys listed at the top level, its size in the + title (`#document-head`), whose menu is the root's. */ #document > details.root { padding-left: 0; } #document > details.root > summary { display: none; } section h2 .count { text-transform: none; letter-spacing: 0; font-weight: normal; @@ -1612,7 +1607,7 @@ async function readStore(path, shallow) { const EMPTY = { map: "{}", list: "[]", text: "\"\"" }; const EMPTY_VALUE = { map: () => ({}), list: () => [], text: () => "" }; -// --- Editing: a double click on an entry turns it into a field holding its contents; +// --- Editing: `Edit value` in an entry's menu turns it into a field holding its contents; // saved with PUT /store/<path> (the whole value, objects too) --- // A string is edited as text (sent as text/plain), anything else as JSON; "JSON" // switches. `done(saved, response)` when saved or cancelled. @@ -1746,21 +1741,10 @@ const editing = element => element.querySelector(".editor") !== null; // Adding to a map (a key and its value, PUT /store/<path>/<key>) or a list (an index // and the value, POST /store/<path>/<index>: the items from there on move up; -1 is the -// end), without writing it whole: a "+" on the row, the field below it. `known()`: a -// map's keys as last read, so an existing one isn't overwritten. -function addButton(kind, path, known, place) { - const button = el("button", { type: "button", class: "add", - title: kind === "map" ? "Add a key" : "Insert an item" }, "+"); - button.addEventListener("click", event => { - // Not a click on the row: it would open or close it. - event.preventDefault(); - event.stopPropagation(); - adding(kind, path, known, place, "-1"); - }); - return button; -} -// The field for adding to `path` (`addButton`), below its row: a list's index as -// `index` has it at first ("-1": at the end; "": asked for). +// end), without writing it whole. `known()`: a map's keys as last read, so an existing +// one isn't overwritten. +// The field for adding to `path` (from its menu, `entryItems`), below its row: a list's +// index as `index` has it at first ("-1": at the end; "": asked for). function adding(kind, path, known, place, index) { const map = kind === "map"; { @@ -1798,7 +1782,7 @@ function adding(kind, path, known, place, index) { // --- An entry's menu (right-click, or a finger held on it): edit its value, rename its // key (a map's), add to it (a map: a key; a list: an item at the end, or at an index). -// Each as the double-click and the "+" do. --- +// Each in a field below its row. --- function entryMenu(x, y, items) { const menu = document.getElementById("entry-menu"); menu.replaceChildren(...items.map(([label, act]) => { @@ -1938,7 +1922,7 @@ function editableLeaf(key, shown, value, path) { ...(glosses ? glossed(aliasOf(key)) : []), ": "), shown, ...(glosses ? glossed(gloss(key, value)) : [])); if (!editable(path)) return leaf; - leaf.title = "Double-click to edit, right-click for more"; + leaf.title = "Right-click (or hold a finger on it) for its menu"; leaf.edit = () => { if (editing(leaf)) return; window.getSelection().removeAllRanges(); @@ -1948,10 +1932,6 @@ function editableLeaf(key, shown, value, path) { edited(path, saved); })); }; - leaf.addEventListener("dblclick", event => { - event.preventDefault(); - leaf.edit(); - }); return leaf; } @@ -1975,10 +1955,9 @@ function glow(entry) { function documentEntry(key, summary, path, parentKind = null, siblings = () => []) { if (summary.size === 0 && summary.type in EMPTY) { const leaf = editableLeaf(key, EMPTY[summary.type], EMPTY_VALUE[summary.type](), path); - // An empty map or list takes its first entry here: "+" on its row, the field below. + // An empty map or list takes its first entry here: from its menu, the field below. if ((summary.type === "map" || summary.type === "list") && editable(path)) { const below = el("div", { class: "nested" }); - leaf.append(" ", addButton(summary.type, path, () => [], () => below)); withMenu(leaf, () => entryItems({ path, kind: summary.type, parentKind, siblings, row: leaf, edit: leaf.edit, known: () => [], place: () => below })); return el("div", {}, leaf, below); @@ -2000,15 +1979,10 @@ function documentEntry(key, summary, path, parentKind = null, siblings = () => [ const head = el("summary", {}, el("span", { class: "key" }, key), ...(glossedPath(path) ? glossed(aliasOf(key)) : []), " ", described); details.append(head); - // A double click edits the whole of it: read, then shown in a field. + // Edited as a whole (from its menu): read, then shown in a field. let edit = null; if (editable(path)) { - head.title = "Double-click to edit, right-click for more"; - head.addEventListener("mousedown", event => { if (event.detail > 1) event.preventDefault(); }); - head.addEventListener("dblclick", event => { - event.preventDefault(); - edit(); - }); + head.title = "Right-click (or hold a finger on it) for its menu"; edit = async () => { if (details.querySelector(":scope > .editor:not(.renamer)")) return; let value; @@ -2044,11 +2018,9 @@ function documentEntry(key, summary, path, parentKind = null, siblings = () => [ details.open = true; return { prepend: form => head.after(form), querySelector: q => details.querySelector(":scope > " + q) }; }; - if (writable) { - head.append(" ", addButton(summary.type, path, () => [...children.keys()], place)); - } - withMenu(head, () => entryItems({ path, kind: summary.type, parentKind, siblings, row: head, - edit, known: () => [...children.keys()], place: writable ? place : null })); + details.menuItems = () => entryItems({ path, kind: summary.type, parentKind, siblings, + row: head, edit, known: () => [...children.keys()], place: writable ? place : null }); + withMenu(head, details.menuItems); let read = false; // Read once at least: what's new or changed from then on breathes (`glow`). let filled = false; @@ -2132,13 +2104,15 @@ function documentChanged(change) { if (change.all || change.paths.some(path => related(path, branch.path))) branch.refresh(); } } -// The store's root, always open: its keys are the box's top level, and its size and its -// "+" (everything its row has but its key) go into the title. +// The store's root, always open: its keys are the box's top level, and its size +// (everything its row has but its key) goes into the title. const documentRoot = documentEntry("store", { type: "map", size: "…" }, []); documentRoot.classList.add("root"); documentRoot.open = true; document.getElementById("document-head").append( ...[...documentRoot.querySelector(":scope > summary").childNodes].slice(1)); +// The title stands for the root: its menu adds a key at the top level. +withMenu(document.querySelector("#document-box > h2"), documentRoot.menuItems); document.getElementById("document").replaceChildren(documentRoot); // A box is busy while text in it is selected: drawing it anew would lose the selection, |
