// Steward's own confirm dialog (#5314): a form, or its submit button, with // data-confirm="Question? What follows." asks in the #confirm-dialog that // base.html renders before it submits, never through window.confirm. // // The prompt is attribute text read through dataset and written with // textContent, never parsed as HTML or JavaScript, so a name inside it // cannot run as script (#5099). Optional attributes beside data-confirm: // data-confirm-title the heading (default: the prompt up to its first "? ") // data-confirm-detail the line under it (default: the rest of the prompt) // data-confirm-action the button that goes ahead (default: the submit // button's own label, or the prompt's first word) // data-confirm-dismiss the button that backs out (default: "Cancel") // Cancel has the focus, and Esc backs out. (function () { function label(btn, title) { var own = btn ? (btn.dataset.confirmAction || btn.textContent || btn.value || '').trim() : ''; if (own.length > 2) return own; // "×" and other icons say nothing return title.split(' ')[0].replace(/\?$/, ''); } function ask(form, btn) { var src = btn && btn.dataset.confirm ? btn : form; var prompt = src.dataset.confirm; var cut = prompt.indexOf('? '); var title = src.dataset.confirmTitle || (cut > 0 ? prompt.slice(0, cut + 1) : prompt); var detail = src.dataset.confirmDetail || (cut > 0 ? prompt.slice(cut + 2) : ''); var d = document.getElementById('confirm-dialog'); d.querySelector('[data-part="title"]').textContent = title; var p = d.querySelector('[data-part="detail"]'); p.textContent = detail; p.hidden = !detail; d.querySelector('[data-part="go"]').textContent = src.dataset.confirmAction || label(btn, title); d.querySelector('[data-part="back"]').textContent = src.dataset.confirmDismiss || 'Cancel'; d.returnValue = ''; d.onclose = function () { if (d.returnValue !== 'go') return; form.dataset.confirmed = '1'; form.requestSubmit(btn && btn.form === form ? btn : undefined); }; d.showModal(); } document.addEventListener('submit', function (ev) { var form = ev.target, btn = ev.submitter; if (!((btn && btn.dataset.confirm) || form.dataset.confirm)) return; if (form.dataset.confirmed === '1') { delete form.dataset.confirmed; return; } // the asked-for submit ev.preventDefault(); ev.stopPropagation(); // before HTMX sees it: an hx-post form waits for the answer too ask(form, btn); }, true); })();