improve task list handling

This commit is contained in:
2026-05-23 08:44:19 +02:00
parent a25d5434ac
commit bf16f2ec3c
9 changed files with 392 additions and 25 deletions
+108 -11
View File
@@ -1,17 +1,114 @@
(function () {
var content = document.querySelector("main");
var content = document.querySelector('.content');
if (!content) return;
var headings = content.querySelectorAll("h2, h3, h4");
if (!headings) return
var allHeadings = content.querySelectorAll('h1, h2, h3, h4, h5, h6');
if (!allHeadings.length) return;
headings.forEach(function (h) {
if (!h.id) return;
var a = document.createElement('a');
a.href = '#' + h.id;
a.className = 'heading-anchor';
a.setAttribute('aria-label', 'Link to this section');
a.textContent = '#';
h.insertBefore(a, h.firstChild);
function copyAnchor(id, item, label, menu) {
var url = window.location.origin + window.location.pathname + '#' + id;
function flash() {
item.textContent = 'Copied!';
setTimeout(function () {
item.textContent = label;
menu.classList.remove('is-open');
}, 1200);
}
function fallback() {
var ta = document.createElement('textarea');
ta.value = url;
ta.setAttribute('readonly', '');
ta.style.position = 'fixed';
ta.style.opacity = '0';
document.body.appendChild(ta);
ta.select();
var ok = false;
try { ok = document.execCommand('copy'); } catch (e) { ok = false; }
document.body.removeChild(ta);
if (ok) flash();
else openModal({
title: 'Copy anchor link',
body: 'Could not copy automatically. URL:\n' + url,
confirm: { label: 'OK', onConfirm: function () { closeModal(); } }
});
}
if (navigator.clipboard && navigator.clipboard.writeText) {
navigator.clipboard.writeText(url).then(flash, fallback);
} else {
fallback();
}
}
function addTask(sectionIndex, headingId) {
var input = document.createElement('input');
input.type = 'text';
input.className = 'modal-input';
input.placeholder = 'Task description';
var ctrl = openModal({
title: 'Add task',
body: input,
confirm: {
label: 'ADD',
initiallyDisabled: true,
onConfirm: function () {
var text = input.value.trim();
if (!text) return;
var action = window.location.pathname + '?addtask=' + sectionIndex;
var target = window.location.pathname + '#' + headingId;
closeModal();
postReplace(action, 'text=' + encodeURIComponent(text), target);
}
}
});
input.addEventListener('input', function () {
ctrl.setConfirmDisabled(input.value.trim() === '');
});
}
allHeadings.forEach(function (h, i) {
if (!h.id) return;
var tag = h.tagName.toLowerCase();
if (tag !== 'h2' && tag !== 'h3' && tag !== 'h4') return;
var sectionIndex = i + 1;
var wrap = document.createElement('span');
wrap.className = 'dropdown heading-anchor';
var trigger = document.createElement('button');
trigger.type = 'button';
trigger.className = 'dropdown-toggle';
trigger.setAttribute('aria-haspopup', 'menu');
trigger.setAttribute('aria-label', 'Section actions');
trigger.textContent = '#';
var menu = document.createElement('div');
menu.className = 'dropdown-menu';
var copyLabel = 'Copy anchor link';
var copyBtn = document.createElement('button');
copyBtn.type = 'button';
copyBtn.className = 'btn btn-tool btn-block';
copyBtn.dataset.action = 'copy-anchor';
copyBtn.textContent = copyLabel;
copyBtn.addEventListener('click', function (e) {
e.stopPropagation();
copyAnchor(h.id, copyBtn, copyLabel, menu);
});
var addBtn = document.createElement('button');
addBtn.type = 'button';
addBtn.className = 'btn btn-tool btn-block';
addBtn.dataset.action = 'add-task';
addBtn.textContent = 'Add task';
addBtn.addEventListener('click', function () { addTask(sectionIndex, h.id); });
menu.appendChild(copyBtn);
menu.appendChild(addBtn);
wrap.appendChild(trigger);
wrap.appendChild(menu);
h.insertBefore(wrap, h.firstChild);
wireDropdown(trigger);
});
}());