/** * Rückfrage im Stil der Verwaltung - statt confirm() des Browsers, und statt gar keiner. * * Ein Formular meldet sich mit data-confirm-title an (dazu optional data-confirm-text, * data-confirm-label und data-confirm-variant="danger"). Sein Absenden wird angehalten, bis der * Dialog bestätigt ist. Ohne JavaScript bleibt es ein gewöhnliches Formular. * * Skripte rufen kantConfirm({ title, message, confirmLabel, variant, onConfirm }) auf. */ (() => { let dialog = null; let pending = null; let opener = null; const build = () => { dialog = document.createElement('dialog'); dialog.className = 'confirm-dialog'; dialog.setAttribute('aria-labelledby', 'confirm-dialog-title'); dialog.setAttribute('aria-describedby', 'confirm-dialog-text'); const title = document.createElement('h2'); title.id = 'confirm-dialog-title'; const text = document.createElement('p'); text.id = 'confirm-dialog-text'; const actions = document.createElement('div'); actions.className = 'dialog-actions'; const cancel = document.createElement('button'); cancel.type = 'button'; cancel.className = 'secondary'; cancel.textContent = 'Abbrechen'; cancel.dataset.confirmCancel = ''; const ok = document.createElement('button'); ok.type = 'button'; ok.dataset.confirmOk = ''; actions.append(cancel, ok); dialog.append(title, text, actions); cancel.addEventListener('click', () => dialog.close()); ok.addEventListener('click', () => { const run = pending; pending = null; dialog.close(); run?.(); }); // Escape und der Klick neben den Dialog schließen ohne Folgen. dialog.addEventListener('click', event => { if (event.target === dialog) dialog.close(); }); dialog.addEventListener('close', () => { pending = null; opener?.focus?.({ preventScroll: true }); opener = null; }); document.body.append(dialog); }; const ask = ({ title, message = '', confirmLabel = 'Bestätigen', variant = 'primary', onConfirm }) => { if (!dialog) build(); if (dialog.open) dialog.close(); opener = document.activeElement; dialog.querySelector('h2').textContent = title; const text = dialog.querySelector('p'); text.textContent = message; text.hidden = '' === message; const ok = dialog.querySelector('[data-confirm-ok]'); ok.textContent = confirmLabel; ok.className = 'danger' === variant ? 'primary danger' : 'primary'; pending = onConfirm; dialog.showModal(); // Der Fokus liegt auf „Abbrechen“: Die Eingabetaste darf nichts Endgültiges auslösen. dialog.querySelector('[data-confirm-cancel]').focus(); }; window.kantConfirm = ask; document.addEventListener('submit', event => { const form = event.target; if (!(form instanceof HTMLFormElement) || !form.dataset.confirmTitle || form.dataset.confirmed) return; event.preventDefault(); const submitter = event.submitter; ask({ title: form.dataset.confirmTitle, message: form.dataset.confirmText || '', confirmLabel: form.dataset.confirmLabel || submitter?.textContent.trim() || 'Bestätigen', variant: form.dataset.confirmVariant || 'primary', onConfirm: () => { form.dataset.confirmed = '1'; // requestSubmit nimmt den Knopf mit, falls er einen Namen und Wert trägt. submitter && submitter.form === form ? form.requestSubmit(submitter) : form.requestSubmit(); }, }); }); })();