Update editor toolbar.

Unify dropdown handling, refactor crowded toolbar
This commit is contained in:
2026-05-08 09:29:31 +02:00
parent fcbfeeb96a
commit 922f2e02ec
3 changed files with 65 additions and 80 deletions
+53 -12
View File
@@ -4,30 +4,71 @@
{{end}}
{{define "content"}}
<script>
if (sessionStorage.getItem('editor-wide') === '1') document.body.classList.add('editor-wide');
</script>
<form id="edit-form" class="edit-form" method="POST" action="{{.PostURL}}">
{{if ge .SectionIndex 0}}<input type="hidden" name="section" value="{{.SectionIndex}}">{{end}}
<div class="editor-toolbar">
<button type="button" class="btn btn-tool" data-action="bold" data-key="B" title="Bold (B)">**</button>
<button type="button" class="btn btn-tool" data-action="italic" data-key="I" title="Italic (I)">*</button>
<span class="toolbar-sep"></span>
<button type="button" class="btn btn-tool" data-action="h1" data-key="1" title="Heading 1 (1)">#</button>
<button type="button" class="btn btn-tool" data-action="h2" data-key="2" title="Heading 2 (2)">##</button>
<button type="button" class="btn btn-tool" data-action="h3" data-key="3" title="Heading 3 (3)">###</button>
<span class="dropdown">
<button type="button" class="btn btn-tool dropdown-toggle" title="Heading (1/2/3)">H▾</button>
<div class="dropdown-menu">
<button type="button" class="btn btn-tool dropdown-item" data-action="h1" data-key="1" title="Heading 1 (1)">Heading 1</button>
<button type="button" class="btn btn-tool dropdown-item" data-action="h2" data-key="2" title="Heading 2 (2)">Heading 2</button>
<button type="button" class="btn btn-tool dropdown-item" data-action="h3" data-key="3" title="Heading 3 (3)">Heading 3</button>
</div>
</span>
<span class="toolbar-sep"></span>
<button type="button" class="btn btn-tool" data-action="code" data-key="C" title="Inline code (C)">`</button>
<button type="button" class="btn btn-tool" data-action="codeblock" data-key="K" title="Code block (K)">```</button>
<span class="toolbar-sep"></span>
<button type="button" class="btn btn-tool" data-action="link" data-key="L" title="Link (L)">[]</button>
<button type="button" class="btn btn-tool" data-action="wikilink" data-key="P" title="Insert wiki link (P)">[[]]</button>
<span class="dropdown">
<button type="button" class="btn btn-tool dropdown-toggle" title="Link (L/P)">L▾</button>
<div class="dropdown-menu">
<button type="button" class="btn btn-tool dropdown-item" data-action="link" data-key="L" title="Link (L)">Link</button>
<button type="button" class="btn btn-tool dropdown-item" data-action="wikilink" data-key="P" title="Wiki link (P)">Wiki link</button>
</div>
</span>
<span class="dropdown">
<button type="button" class="btn btn-tool dropdown-toggle" title="List (U/O/X)">≡▾</button>
<div class="dropdown-menu">
<button type="button" class="btn btn-tool dropdown-item" data-action="ul" data-key="U" title="Unordered list (U)">Unordered list</button>
<button type="button" class="btn btn-tool dropdown-item" data-action="ol" data-key="O" title="Ordered list (O)">Ordered list</button>
<button type="button" class="btn btn-tool dropdown-item" data-action="task" data-key="X" title="Task list (X)">Task list</button>
</div>
</span>
<button type="button" class="btn btn-tool" data-action="quote" data-key="Q" title="Blockquote (Q)">&gt;</button>
<button type="button" class="btn btn-tool" data-action="ul" data-key="U" title="Unordered list (U)">-</button>
<button type="button" class="btn btn-tool" data-action="ol" data-key="O" title="Ordered list (O)">1.</button>
<button type="button" class="btn btn-tool" data-action="hr" data-key="R" title="Horizontal rule (R)">---</button>
<span class="toolbar-sep"></span>
<button type="button" class="btn btn-tool dropdown" data-action="tbldrop" title="Table (T)">T▾</button>
<button type="button" class="btn btn-tool dropdown" data-action="datedrop" title="Insert date (D/W)">D</button>
<span class="dropdown">
<button type="button" class="btn btn-tool dropdown-toggle" title="Table (T)">T</button>
<div class="dropdown-menu">
<button type="button" class="btn btn-tool dropdown-item" data-action="fmttable" data-key="T" title="Format table (T)">Format table</button>
<button type="button" class="btn btn-tool dropdown-item" data-action="tblalignleft" title="Align left">Align left</button>
<button type="button" class="btn btn-tool dropdown-item" data-action="tblaligncenter" title="Align center">Align center</button>
<button type="button" class="btn btn-tool dropdown-item" data-action="tblalignright" title="Align right">Align right</button>
<button type="button" class="btn btn-tool dropdown-item" data-action="tblinsertcol" title="Insert column">Insert column</button>
<button type="button" class="btn btn-tool dropdown-item" data-action="tbldeletecol" title="Delete column">Delete column</button>
<button type="button" class="btn btn-tool dropdown-item" data-action="tblinsertrow" title="Insert row">Insert row</button>
<button type="button" class="btn btn-tool dropdown-item" data-action="tbldeleterow" title="Delete row">Delete row</button>
</div>
</span>
<span class="dropdown">
<button type="button" class="btn btn-tool dropdown-toggle" title="Insert date (D/W)">D▾</button>
<div class="dropdown-menu">
<button type="button" class="btn btn-tool dropdown-item" data-action="dateiso" data-key="D" title="YYYY-MM-DD (D)">YYYY-MM-DD</button>
<button type="button" class="btn btn-tool dropdown-item" data-action="datelong" data-key="W" title="DE Long (W)">DE Long</button>
</div>
</span>
<span class="dropdown">
<button type="button" class="btn btn-tool dropdown-toggle" title="Special (V)">★▾</button>
<div class="dropdown-menu">
<button type="button" class="btn btn-tool dropdown-item" data-action="movie" data-key="V" title="Import movie (V)">Import movie</button>
</div>
</span>
<span class="toolbar-sep"></span>
<button type="button" class="btn btn-tool" data-action="movie" data-key="V" title="Import movie (V)">MV</button>
<button type="button" class="btn btn-tool" data-action="wide" data-key="Z" title="Toggle wide mode (Z)"></button>
</div>
<textarea name="content" id="editor" autofocus>{{.RawContent}}</textarea>
</form>
+8 -68
View File
@@ -124,6 +124,7 @@
wikilink: insertWikilink,
ul: function () { linePrefix('- '); },
ol: function () { linePrefix('1. '); },
task: function () { linePrefix('- [ ] '); },
hr: function () { wrap('\n\n---\n\n', '', ''); },
fmttable: function () { applyTableOp(T.formatTableText); },
tblalignleft: function () { applyTableOp(T.setColumnAlignment, 'left'); },
@@ -136,6 +137,11 @@
dateiso: function () { insertAtCursor(D.isoDate()); },
datelong: function () { insertAtCursor(D.longDate()); },
movie: function () { M.run(textarea); },
wide: function () {
var enabled = !document.body.classList.contains('editor-wide');
document.body.classList.toggle('editor-wide', enabled);
sessionStorage.setItem('editor-wide', enabled ? '1' : '0');
},
};
// --- Keyboard shortcut registration ---
@@ -151,10 +157,6 @@
}
});
keyMap['T'] = actions.fmttable;
keyMap['D'] = actions.dateiso;
keyMap['W'] = actions.datelong;
document.addEventListener('keydown', function (e) {
if (!e.altKey || !e.shiftKey) return;
// Shift+digit produces a layout-dependent character in e.key (e.g. "!"
@@ -192,69 +194,7 @@
applyResult(result);
});
// --- Dropdown helper ---
// --- Dropdowns ---
var openMenus = [];
function makeDropdown(triggerBtn, items) {
var menu = document.createElement('div');
menu.className = 'dropdown-menu';
items.forEach(function (item) {
var btn = document.createElement('button');
btn.type = 'button';
btn.className = 'btn btn-tool dropdown-item';
btn.textContent = item.label;
btn.addEventListener('mousedown', function (e) {
e.preventDefault();
actions[item.action]();
menu.classList.remove('is-open');
});
menu.appendChild(btn);
});
triggerBtn.appendChild(menu);
openMenus.push(menu);
triggerBtn.addEventListener('click', function (e) {
if (e.target !== triggerBtn) return;
var wasOpen = menu.classList.contains('is-open');
openMenus.forEach(function (m) { m.classList.remove('is-open'); });
if (!wasOpen) menu.classList.add('is-open');
});
}
document.addEventListener('click', function (e) {
var insideAny = openMenus.some(function (m) {
return m.parentElement && m.parentElement.contains(e.target);
});
if (!insideAny) openMenus.forEach(function (m) { m.classList.remove('is-open'); });
});
document.addEventListener('keydown', function (e) {
if (e.key === 'Escape') openMenus.forEach(function (m) { m.classList.remove('is-open'); });
});
// --- Table dropdown ---
var tblDropBtn = document.querySelector('[data-action="tbldrop"]');
if (tblDropBtn) {
makeDropdown(tblDropBtn, [
{ label: 'Format table', action: 'fmttable' },
{ label: 'Align left', action: 'tblalignleft' },
{ label: 'Align center', action: 'tblaligncenter' },
{ label: 'Align right', action: 'tblalignright' },
{ label: 'Insert column', action: 'tblinsertcol' },
{ label: 'Delete column', action: 'tbldeletecol' },
{ label: 'Insert row', action: 'tblinsertrow' },
{ label: 'Delete row', action: 'tbldeleterow' },
]);
}
// --- Date dropdown ---
var dateDropBtn = document.querySelector('[data-action="datedrop"]');
if (dateDropBtn) {
makeDropdown(dateDropBtn, [
{ label: 'YYYY-MM-DD', action: 'dateiso' },
{ label: 'DE Long', action: 'datelong' },
]);
}
document.querySelectorAll('.dropdown-toggle').forEach(wireDropdown);
})();