Langkau ke kandungan
WANCODE
EN

Fungsi Bantu Salin ke Clipboard

Salin teks dengan Clipboard API async, guna fallback dengan baik, dan beritahu pengguna (serta pembaca skrin) sama ada ia berjaya.

Pratonton langsung Buka dalam Playground
copy-text.js
/**
 * Copies text to the clipboard. Resolves to true on success.
 * Must be called from a user gesture (click, key press).
 */
export async function copyText(text) {
  // Modern API: needs a secure context (HTTPS or localhost)
  if (navigator.clipboard && window.isSecureContext) {
    try {
      await navigator.clipboard.writeText(text);
      return true;
    } catch {
      // Permission denied or blocked (e.g. inside some iframes) — try the fallback
    }
  }
  return legacyCopy(text);
}

function legacyCopy(text) {
  const previousFocus = document.activeElement;
  const textarea = document.createElement("textarea");
  textarea.value = text;
  textarea.setAttribute("readonly", "");   // no on-screen keyboard on phones
  textarea.style.position = "fixed";       // don't scroll the page
  textarea.style.opacity = "0";
  document.body.append(textarea);
  textarea.select();

  let ok = false;
  try {
    ok = document.execCommand("copy");     // deprecated, but still the only fallback
  } catch {
    ok = false;
  }

  textarea.remove();
  if (previousFocus instanceof HTMLElement) previousFocus.focus();
  return ok;
}

navigator.clipboard.writeText() ialah cara moden untuk menyalin. Ia pulangkan promise kerana pelayar mungkin perlu semak kebenaran dahulu. Ia boleh gagal — pada halaman http:// biasa, tanpa tindakan pengguna, atau dalam iframe yang tak diberi akses clipboard — jadi kita sentiasa uruskan kegagalan.

Baris demi baris

  • window.isSecureContext bernilai true pada HTTPS dan localhost. Clipboard API memang tiada (atau disekat) di tempat lain.
  • try { await … } catch { … } tukar promise yang ditolak (rejected) menjadi laluan kod biasa, bukan ralat "Uncaught (in promise)".
  • Fallback letak teks dalam <textarea> yang tak kelihatan, pilih (select) teks itu dan jalankan document.execCommand("copy"). API itu sudah deprecated, tetapi pelayar masih menyokongnya dan ia satu-satunya pilihan bila API moden disekat.
  • Memilih textarea akan mengambil fokus, jadi kita kembalikan fokus ke tempat asal. Pengguna papan kekunci kekal pada butang yang mereka tekan.
  • Fungsi ini pulangkan true/false dan tak paparkan UI sendiri, jadi anda yang tentukan cara laporkan hasilnya.

Umumkan hasilnya dalam elemen dengan role="status" (live region yang sopan) supaya pengguna pembaca skrin turut dengar "Copied". Sentiasa sediakan cara manual (teks yang kelihatan dan boleh dipilih) sekiranya penyalinan gagal.

Dalam preview

Preview WANCode ialah iframe sandbox tanpa kebenaran clipboard, jadi API moden biasanya disekat di situ dan anda akan nampak fallback (atau mesej gagal). Itu ujian yang realistik untuk laluan ralat.

Cara guna

HTML
<code id="cmd">npm install</code>
<button type="button" id="copy">Copy</button>
<span role="status" id="copy-status"></span>

<script type="module">
  import { copyText } from "./copy-text.js";

  const status = document.getElementById("copy-status");
  document.getElementById("copy").addEventListener("click", async () => {
    const ok = await copyText(document.getElementById("cmd").textContent);
    status.textContent = ok ? "Copied!" : "Couldn't copy — select the text and press Ctrl+C.";
  });
</script>