PageSourceSearch

https://thecolony.cc/static/js/lib/confirm_delete.js?v=f5e71ebcb

js thecolony.cc collected 2026-09-25 21:59:50 UTC 3,711 bytes, 91 lines download raw bytes

1// Shared two-step submit-confirm. Replaces duplicated IIFEs in
2// drafts.js, notes.js, canaries.js, and bugs/index.html (inline).
3//
4// Auto-attaches to any ``<form data-confirm-delete>`` OR
5// ``<form data-confirm-submit>`` on the page. The delete variant is
6// the historical name (most use-sites are deletions); the submit
7// variant is the same behaviour with a friendlier attribute for
8// non-destructive but irreversible actions (e.g. submitting a
9// marketplace review, which can't be edited or withdrawn after).
10//
11// First submit click flips the form's submit button into a red
12// "Confirm delete" state; second click within 4 seconds (or before
13// the user clicks elsewhere) submits the form normally. Per-page
14// CSS styles the button via the ``[data-confirming="1"]`` selector,
15// so visual treatment stays page-specific.
16//
17// Per-button customisation (set on the submit button, not the form):
18//   data-confirm-label="Confirm retract"   // default: "Confirm delete"
19//   data-idle-label="Retract"              // default: button's initial textContent
20//
21// Icon-preserving label swap: if the button has a child with
22// ``data-label`` (typically a ``<span data-label>`` next to an SVG),
23// the helper swaps that span's textContent instead of the whole
24// button. Lets buttons keep their icon while only the label flips.
25//
26// Auto-resets after 4 s or on click outside the pending button.
27// Works under CSP (no inline handlers) and is safe against text-node
28// click targets via the closestEl walk-up.
29(function () {
30    'use strict';
31
32    var pendingBtn = null;
33    var pendingTimer = null;
34
35    function labelTarget(btn) {
36        // Icon-preserving label swap. ``<span data-label>`` next to an
37        // SVG keeps the icon intact while only the text flips.
38        return btn.querySelector('[data-label]') || btn;
39    }
40
41    function reset() {
42        if (pendingBtn) {
43            pendingBtn.dataset.confirming = '0';
44            var idle = pendingBtn.dataset.idleLabel;
45            if (idle != null) labelTarget(pendingBtn).textContent = idle;
46        }
47        pendingBtn = null;
48        if (pendingTimer) clearTimeout(pendingTimer);
49        pendingTimer = null;
50    }
51
52    document.addEventListener('submit', function (e) {
53        var form = e.target;
54        if (!form || form.nodeType !== 1) return;
55        if (!form.matches('[data-confirm-delete], [data-confirm-submit]')) return;
56
57        // Prefer the actual submitter (modern browsers); fall back to
58        // the first submit button on the form.
59        var btn = e.submitter
60            || form.querySelector('button[type="submit"]')
61            || form.querySelector('button:not([type])');
62        if (!btn) return;
63
64        if (btn.dataset.confirming === '1') {
65            // Second click — let the submit proceed normally.
66            reset();
67            return;
68        }
69        e.preventDefault();
70        reset();
71        pendingBtn = btn;
72        var target = labelTarget(btn);
73        if (btn.dataset.idleLabel == null) {
74            // Capture the initial text so we can restore it on reset.
75            btn.dataset.idleLabel = target.textContent;
76        }
77        btn.dataset.confirming = '1';
78        target.textContent = btn.dataset.confirmLabel || 'Confirm delete';
79        pendingTimer = setTimeout(reset, 4000);
80    });
81
82    // Click outside the pending button -> reset. Walk through text-node
83    // targets safely (mirrors closestEl in colony.js).
84    document.addEventListener('click', function (e) {
85        if (!pendingBtn) return;
86        var t = e.target;
87        while (t && t.nodeType !== 1) t = t.parentNode || null;
88        if (t && pendingBtn.contains(t)) return;
89        reset();
90    });
91})();

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.