// Putting a described value on the clipboard. // // `c3e145e0`. An `Act` can say that pressing it copies a value, and this is the // browser's half. It replaces seven `window.` globals across 14 sites on // the MNW server, six of which scraped the text back off the DOM at press time // and one of which read an element by id. // // It reads one attribute the node emitter writes and nothing else: // `data-copies` carries the value. An ordinary escaped attribute, so nothing // here is a program built out of app text -- the same rule that makes this a // script rather than an emitted _hyperscript program. A licence key reading // `"; alert(1); "` is a value in an attribute here and could not be one in a // program. // // What it does NOT do is say "Copied!". Every shipped site relabelled its own // button and reverted, six at 1500ms and one at 2000ms, and that is a temporary // label rather than a copy: it belongs to `makeover-timing` and to mnw-server // `033c722f`. Splitting them is deliberate -- a host with no notion of a // reverting label still needs to be told the act copies something. (() => { "use strict"; /** The value to put on the clipboard. */ const VALUE = "data-copies"; /** * Write `text` to the clipboard, preferring the async API. * * `navigator.clipboard` is unavailable on an insecure origin and can be * refused by permissions policy, and neither is an error worth surfacing to * a reader who pressed a copy button. The fallback is the old selection * dance, which works in both cases and is why it is still here. */ const write = async (text) => { try { if (navigator.clipboard?.writeText) { await navigator.clipboard.writeText(text); return; } } catch { // Fall through: refused, or no permission. The fallback below does // not ask for one. } const carrier = document.createElement("textarea"); carrier.value = text; // Off-screen rather than hidden: a `display: none` element cannot be // selected, and selecting is the whole mechanism here. carrier.setAttribute("readonly", ""); carrier.style.position = "fixed"; carrier.style.top = "-9999px"; document.body.appendChild(carrier); carrier.select(); try { document.execCommand("copy"); } catch { // Nothing left to try. The reader sees no change, which is the // same outcome as a page that never described the copy at all. } carrier.remove(); }; // One delegated listener rather than one per control, for `FILL_JS`' // reason: these controls arrive in swaps, so binding per element would mean // rebinding on every swap. document.addEventListener("click", (event) => { const control = event.target?.closest?.(`[${VALUE}]`); if (!control) { return; } void write(control.getAttribute(VALUE) ?? ""); }); })();