|
129 | 129 | var statusDot = $id("statusDot"); |
130 | 130 | var statusText = $id("statusText"); |
131 | 131 | var clearConsoleBtn = $id("clearConsole"); |
| 132 | + var copyConsoleBtn = $id("copyConsole"); |
132 | 133 | var clearEditorBtn = $id("clearEditor"); |
133 | 134 | var loadExampleBtn = $id("loadExample"); |
134 | 135 | var draftSelector = $id("draftSelector"); |
|
903 | 904 | }); |
904 | 905 | } |
905 | 906 |
|
| 907 | + /* ────────────────────────────────────────────────────────────── |
| 908 | + Copy Console Button — Issue #1715 |
| 909 | + Copy console output to clipboard with visual feedback |
| 910 | + ────────────────────────────────────────────────────────────── */ |
| 911 | + if (copyConsoleBtn) { |
| 912 | + copyConsoleBtn.addEventListener("click", function (event) { |
| 913 | + event.preventDefault(); |
| 914 | + |
| 915 | + var hasPlaceholder = consoleEl.querySelector(".pg-placeholder"); |
| 916 | + var textToCopy = ""; |
| 917 | + if (!hasPlaceholder) { |
| 918 | + textToCopy = consoleEl.innerText || consoleEl.textContent || ""; |
| 919 | + } |
| 920 | + textToCopy = textToCopy.trim(); |
| 921 | + |
| 922 | + if (!textToCopy) { |
| 923 | + copyConsoleBtn.textContent = "Nothing to copy"; |
| 924 | + copyConsoleBtn.classList.add("copy-error"); |
| 925 | + copyConsoleBtn.setAttribute("aria-label", "Console is empty, nothing to copy"); |
| 926 | + setTimeout(function () { |
| 927 | + copyConsoleBtn.innerHTML = |
| 928 | + '<i aria-hidden="true" class="fas fa-copy"></i> Copy'; |
| 929 | + copyConsoleBtn.classList.remove("copy-error"); |
| 930 | + copyConsoleBtn.setAttribute( |
| 931 | + "aria-label", |
| 932 | + "Copy console output to clipboard" |
| 933 | + ); |
| 934 | + }, 1500); |
| 935 | + return; |
| 936 | + } |
| 937 | + |
| 938 | + function fallbackCopy(text) { |
| 939 | + return new Promise(function (resolve, reject) { |
| 940 | + var textarea = document.createElement("textarea"); |
| 941 | + textarea.value = text; |
| 942 | + textarea.style.position = "fixed"; |
| 943 | + textarea.style.left = "-9999px"; |
| 944 | + textarea.style.opacity = "0"; |
| 945 | + textarea.setAttribute("aria-hidden", "true"); |
| 946 | + textarea.setAttribute("tabindex", "-1"); |
| 947 | + |
| 948 | + document.body.appendChild(textarea); |
| 949 | + |
| 950 | + try { |
| 951 | + textarea.select(); |
| 952 | + var success = document.execCommand("copy"); |
| 953 | + if (success) { |
| 954 | + resolve(); |
| 955 | + } else { |
| 956 | + reject(new Error("execCommand copy failed")); |
| 957 | + } |
| 958 | + } catch (error) { |
| 959 | + reject(error); |
| 960 | + } finally { |
| 961 | + document.body.removeChild(textarea); |
| 962 | + } |
| 963 | + }); |
| 964 | + } |
| 965 | + |
| 966 | + var copyPromise = |
| 967 | + navigator.clipboard && navigator.clipboard.writeText |
| 968 | + ? navigator.clipboard.writeText(textToCopy) |
| 969 | + : fallbackCopy(textToCopy); |
| 970 | + |
| 971 | + copyPromise |
| 972 | + .then(function () { |
| 973 | + copyConsoleBtn.innerHTML = |
| 974 | + '<i aria-hidden="true" class="fas fa-check"></i> Copied!'; |
| 975 | + copyConsoleBtn.classList.add("copy-success"); |
| 976 | + copyConsoleBtn.setAttribute("aria-label", "Console output copied to clipboard"); |
| 977 | + |
| 978 | + setTimeout(function () { |
| 979 | + copyConsoleBtn.innerHTML = |
| 980 | + '<i aria-hidden="true" class="fas fa-copy"></i> Copy'; |
| 981 | + copyConsoleBtn.classList.remove("copy-success"); |
| 982 | + copyConsoleBtn.setAttribute( |
| 983 | + "aria-label", |
| 984 | + "Copy console output to clipboard" |
| 985 | + ); |
| 986 | + }, 2000); |
| 987 | + }) |
| 988 | + .catch(function (error) { |
| 989 | + console.error("Copy failed:", error); |
| 990 | + copyConsoleBtn.textContent = "Copy failed"; |
| 991 | + copyConsoleBtn.classList.add("copy-error"); |
| 992 | + copyConsoleBtn.setAttribute("aria-label", "Copy failed, try again"); |
| 993 | + |
| 994 | + setTimeout(function () { |
| 995 | + copyConsoleBtn.innerHTML = |
| 996 | + '<i aria-hidden="true" class="fas fa-copy"></i> Copy'; |
| 997 | + copyConsoleBtn.classList.remove("copy-error"); |
| 998 | + copyConsoleBtn.setAttribute( |
| 999 | + "aria-label", |
| 1000 | + "Copy console output to clipboard" |
| 1001 | + ); |
| 1002 | + }, 2000); |
| 1003 | + }); |
| 1004 | + }); |
| 1005 | + } |
| 1006 | + |
906 | 1007 | // Keyboard shortcut for copy: Ctrl+Shift+C in editor |
907 | 1008 | if (cmView) { |
908 | 1009 | document.addEventListener("keydown", function (event) { |
|
0 commit comments