Skip to main content

max / makenotwork

1.9 KB · 49 lines History Blame Raw
1 // Clipboard helper, consolidates the ~6 duplicated copy-then-flash-label
2 // snippets and the delegated [data-copy-link] handler from mnw.js:670. Falls
3 // back to a prompt in non-secure contexts (plain HTTP, some iframes), where the
4 // old inline snippets silently no-op'd.
5
6 import { revertMs } from './timing.ts';
7
8 /** Copy `text`, flashing `copiedLabel` on `el`, then restoring the label.
9 *
10 * The flash lasts `Intent::Revert`, which is what a temporary label lasts
11 * everywhere. `resetMs` stays in the signature for a caller with a reason, and
12 * as of `2c8cf51c` no caller has one: the seven sites that used to pass a
13 * number passed 1500 six times and 2000 once, which was a divergence rather
14 * than an axis. */
15 export function copyWithFeedback(el: HTMLElement, text: string, copiedLabel = 'Copied!', resetMs = revertMs()): void {
16 const defaultLabel = el.textContent ?? '';
17 const restore = () => {
18 el.textContent = defaultLabel;
19 };
20 if (navigator.clipboard?.writeText) {
21 navigator.clipboard
22 .writeText(text)
23 .then(() => {
24 el.textContent = copiedLabel;
25 setTimeout(restore, resetMs);
26 })
27 .catch(() => {
28 window.prompt('Copy this link:', text);
29 });
30 } else {
31 window.prompt('Copy this link:', text);
32 }
33 }
34
35 /** Install the delegated `[data-copy-link]` handler. `href` stays the real
36 * destination (middle-click / no-JS / share still work); left-click copies.
37 * Ported from mnw.js:670. */
38 export function initCopyLink(): void {
39 document.addEventListener('click', (evt) => {
40 const el = (evt.target as Element | null)?.closest<HTMLElement>('[data-copy-link]');
41 if (!el) return;
42 evt.preventDefault();
43 let url = el.dataset.url || el.getAttribute('href') || window.location.href;
44 if (url.charAt(0) === '/') url = window.location.origin + url;
45 const copiedLabel = el.dataset.copiedLabel || 'Copied!';
46 copyWithFeedback(el, url, copiedLabel);
47 });
48 }
49