diff --git a/static/js/code-block-buttons.js b/static/js/code-block-buttons.js index 0279288ca..eb0c44239 100644 --- a/static/js/code-block-buttons.js +++ b/static/js/code-block-buttons.js @@ -1,47 +1,78 @@ -// Turn off ESLint for this file because it's sent down to users as-is. /* eslint-disable */ -window.addEventListener("load", function () { - function button(label, ariaLabel, icon, className) { +window.addEventListener("DOMContentLoaded", function () { + function createButton(label, ariaLabel, icon, className) { const btn = document.createElement("button"); btn.classList.add("btnIcon", className); btn.setAttribute("type", "button"); btn.setAttribute("aria-label", ariaLabel); - btn.innerHTML = - '
' + - icon + - '' + - label + - "" + - "
"; + btn.innerHTML = ` +
+ ${icon} + ${label} +
+ `; return btn; } - function addButtons(codeBlockSelector, btn) { - document.querySelectorAll(codeBlockSelector).forEach(function (code) { - code.parentNode.appendChild(btn.cloneNode(true)); + function addButtons(codeBlockSelector, btnTemplate) { + document.querySelectorAll(codeBlockSelector).forEach((codeBlock) => { + // Ensure we don't duplicate buttons + if (!codeBlock.parentNode.querySelector(".btnClipboard")) { + const btn = btnTemplate.cloneNode(true); + codeBlock.parentNode.appendChild(btn); + } }); } - const copyIcon = - ''; + const copyIcon = ` + + `; - addButtons( - ".hljs", - button("Copy", "Copy code to clipboard", copyIcon, "btnClipboard") + const copyButton = createButton( + "Copy", + "Copy code to clipboard", + copyIcon, + "btnClipboard" ); + addButtons(".hljs", copyButton); + const clipboard = new ClipboardJS(".btnClipboard", { - target: function (trigger) { - return trigger.parentNode.querySelector("code"); - }, + text: (trigger) => { + const codeBlock = trigger.parentNode.querySelector("code"); + return codeBlock ? codeBlock.innerText : ""; + } }); - clipboard.on("success", function (event) { + // Track timeouts per button + const buttonTimeouts = new WeakMap(); + + clipboard.on("success", (event) => { event.clearSelection(); - const textEl = event.trigger.querySelector(".btnIcon__label"); - textEl.textContent = "Copied"; - setTimeout(function () { - textEl.textContent = "Copy"; + const button = event.trigger; + const label = button.querySelector(".btnIcon__label"); + + // Clear existing timeout if any + if (buttonTimeouts.has(button)) { + clearTimeout(buttonTimeouts.get(button)); + } + + label.textContent = "Copied!"; + + // Set new timeout + const timeoutId = setTimeout(() => { + label.textContent = "Copy"; + buttonTimeouts.delete(button); + }, 2000); + + buttonTimeouts.set(button, timeoutId); + }); + + clipboard.on("error", (event) => { + const label = event.trigger.querySelector(".btnIcon__label"); + label.textContent = "Failed"; + setTimeout(() => { + label.textContent = "Copy"; }, 2000); }); });