Pertanyaan Bagaimana cara menyalin ke clipboard di JavaScript?


Apa cara terbaik untuk menyalin teks ke clipboard? (multi-browser)

Saya telah mencoba:

function copyToClipboard(text) {
    if (window.clipboardData) { // Internet Explorer
        window.clipboardData.setData("Text", text);
    } else {  
        unsafeWindow.netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");  
        const clipboardHelper = Components.classes["@mozilla.org/widget/clipboardhelper;1"].getService(Components.interfaces.nsIClipboardHelper);  
        clipboardHelper.copyString(text);
    }
}

tetapi di Internet Explorer memberikan kesalahan sintaks. Di Firefox, katanya unsafeWindow is not defined.

Trik yang bagus tanpa flash: Bagaimana cara Trello mengakses papan klip pengguna?


2663
2017-12-30 13:09


asal


Jawaban:


Ikhtisar

Ada 3 API browser utama untuk menyalin ke clipboard:

  1. Async Clipboard API  [navigator.clipboard.writeText]
    • Bagian yang berfokus pada teks tersedia di Chrome 66 (Maret 2018)
    • Akses bersifat asinkron dan digunakan Janji JavaScript, dapat ditulis sehingga permintaan pengguna keamanan (jika ditampilkan) tidak mengganggu JavaScript di halaman.
    • Teks dapat disalin ke clipboard langsung dari suatu variabel.
    • Hanya didukung pada halaman yang dilayani melalui HTTPS.
    • Di Chrome 66 halaman di tab aktif dapat menulis ke clipboard tanpa meminta izin.
  2. document.execCommand('copy')
    • Sebagian besar browser mendukung ini sejak ~ April 2015 (lihat Dukungan Browser di bawah).
    • Akses sinkron, yaitu berhenti JavaScript di halaman hingga selesai termasuk menampilkan dan pengguna berinteraksi dengan petunjuk keamanan apa pun.
    • Teks dibaca dari DOM dan ditempatkan di papan klip.
    • Selama pengujian ~ April 2015 hanya Internet Explorer yang tercatat sebagai menampilkan izin saat menulis ke clipboard.
  3. Mengganti acara salin
    • Lihat dokumentasi Clipboard API Mengganti acara salin.
    • Memungkinkan Anda untuk memodifikasi apa yang muncul di clipboard dari setiap acara salin, dapat menyertakan format data lain selain teks biasa.
    • Tidak dibahas di sini karena tidak secara langsung menjawab pertanyaan.

Catatan pengembangan umum

Jangan berharap perintah yang terkait dengan clipboard berfungsi saat Anda menguji kode di konsol. Umumnya halaman harus aktif (Async Clipboard API) atau memerlukan interaksi pengguna (misalnya, pengguna mengklik) untuk memperbolehkan (document.execCommand('copy')) untuk mengakses clipboard lihat di bawah ini untuk lebih detail.

Async + Fallback

Karena tingkat dukungan browser untuk Async Clipboard API baru, Anda mungkin ingin mundur ke document.execCommand('copy') metode untuk mendapatkan cakupan browser yang baik.

Berikut ini contoh sederhana:

function fallbackCopyTextToClipboard(text) {
  var textArea = document.createElement("textarea");
  textArea.value = text;
  document.body.appendChild(textArea);
  textArea.focus();
  textArea.select();

  try {
    var successful = document.execCommand('copy');
    var msg = successful ? 'successful' : 'unsuccessful';
    console.log('Fallback: Copying text command was ' + msg);
  } catch (err) {
    console.error('Fallback: Oops, unable to copy', err);
  }

  document.body.removeChild(textArea);
}
function copyTextToClipboard(text) {
  if (!navigator.clipboard) {
    fallbackCopyTextToClipboard(text);
    return;
  }
  navigator.clipboard.writeText(text).then(function() {
    console.log('Async: Copying to clipboard was successful!');
  }, function(err) {
    console.error('Async: Could not copy text: ', err);
  });
}

var copyBobBtn = document.querySelector('.js-copy-bob-btn'),
  copyJaneBtn = document.querySelector('.js-copy-jane-btn');

copyBobBtn.addEventListener('click', function(event) {
  copyTextToClipboard('Bob');
});


copyJaneBtn.addEventListener('click', function(event) {
  copyTextToClipboard('Jane');
});
<div style="display:inline-block; vertical-align:top;">
  <button class="js-copy-bob-btn">Set clipboard to BOB</button><br /><br />
  <button class="js-copy-jane-btn">Set clipboard to JANE</button>
</div>
<div style="display:inline-block;">
  <textarea class="js-test-textarea" cols="35" rows="4">Try pasting into here to see what you have on your clipboard:
  
  </textarea>
</div>

Perhatikan bahwa cuplikan ini tidak berfungsi dengan baik di pratinjau tersemat StackOverflow Anda dapat mencobanya di sini: https://codepen.io/DeanMarkTaylor/pen/RMRaJX?editors=1011

Async Clipboard API

Perhatikan bahwa ada kemampuan untuk "meminta izin" dan menguji untuk akses ke clipboard melalui API izin di Chrome 66.

var text = "Example text to appear on clipboard";
navigator.clipboard.writeText(text).then(function() {
  console.log('Async: Copying to clipboard was successful!');
}, function(err) {
  console.error('Async: Could not copy text: ', err);
});

document.execCommand ('copy')

Sisa dari posting ini masuk ke nuansa dan detail dari document.execCommand('copy') API.

Dukungan Browser

JavaScript document.execCommand('copy') dukungan telah berkembang, lihat tautan di bawah untuk pembaruan peramban:

Contoh Sederhana

var copyTextareaBtn = document.querySelector('.js-textareacopybtn');

copyTextareaBtn.addEventListener('click', function(event) {
  var copyTextarea = document.querySelector('.js-copytextarea');
  copyTextarea.focus();
  copyTextarea.select();

  try {
    var successful = document.execCommand('copy');
    var msg = successful ? 'successful' : 'unsuccessful';
    console.log('Copying text command was ' + msg);
  } catch (err) {
    console.log('Oops, unable to copy');
  }
});
<p>
  <button class="js-textareacopybtn" style="vertical-align:top;">Copy Textarea</button>
  <textarea class="js-copytextarea">Hello I'm some text</textarea>
</p>

Contoh Kompleks: Salin ke papan klip tanpa menampilkan input

Contoh sederhana di atas berfungsi dengan baik jika ada textarea atau input elemen terlihat di layar.

Dalam beberapa kasus Anda mungkin ingin menyalin teks ke clipboard tanpa menampilkan sebuah input / textarea elemen. Ini adalah salah satu contoh cara untuk mengatasi ini (pada dasarnya memasukkan elemen, salin ke clipboard, hapus elemen):

Diuji dengan Google Chrome 44, Firefox 42.0a1 dan IE 11.0.8600.17814.

function copyTextToClipboard(text) {
  var textArea = document.createElement("textarea");

  //
  // *** This styling is an extra step which is likely not required. ***
  //
  // Why is it here? To ensure:
  // 1. the element is able to have focus and selection.
  // 2. if element was to flash render it has minimal visual impact.
  // 3. less flakyness with selection and copying which **might** occur if
  //    the textarea element is not visible.
  //
  // The likelihood is the element won't even render, not even a flash,
  // so some of these are just precautions. However in IE the element
  // is visible whilst the popup box asking the user for permission for
  // the web page to copy to the clipboard.
  //

  // Place in top-left corner of screen regardless of scroll position.
  textArea.style.position = 'fixed';
  textArea.style.top = 0;
  textArea.style.left = 0;

  // Ensure it has a small width and height. Setting to 1px / 1em
  // doesn't work as this gives a negative w/h on some browsers.
  textArea.style.width = '2em';
  textArea.style.height = '2em';

  // We don't need padding, reducing the size if it does flash render.
  textArea.style.padding = 0;

  // Clean up any borders.
  textArea.style.border = 'none';
  textArea.style.outline = 'none';
  textArea.style.boxShadow = 'none';

  // Avoid flash of white box if rendered for any reason.
  textArea.style.background = 'transparent';


  textArea.value = text;

  document.body.appendChild(textArea);
  textArea.focus();
  textArea.select();

  try {
    var successful = document.execCommand('copy');
    var msg = successful ? 'successful' : 'unsuccessful';
    console.log('Copying text command was ' + msg);
  } catch (err) {
    console.log('Oops, unable to copy');
  }

  document.body.removeChild(textArea);
}


var copyBobBtn = document.querySelector('.js-copy-bob-btn'),
  copyJaneBtn = document.querySelector('.js-copy-jane-btn');

copyBobBtn.addEventListener('click', function(event) {
  copyTextToClipboard('Bob');
});


copyJaneBtn.addEventListener('click', function(event) {
  copyTextToClipboard('Jane');
});
<div style="display:inline-block; vertical-align:top;">
  <button class="js-copy-bob-btn">Set clipboard to BOB</button><br /><br />
  <button class="js-copy-jane-btn">Set clipboard to JANE</button>
</div>
<div style="display:inline-block;">
  <textarea class="js-test-textarea" cols="35" rows="4">Try pasting into here to see what you have on your clipboard:
  
  </textarea>
</div>

Catatan tambahan

Hanya berfungsi jika pengguna mengambil tindakan

Semua document.execCommand('copy') panggilan harus dilakukan sebagai akibat langsung dari tindakan pengguna, mis. klik pengendali event. Ini adalah langkah untuk mencegah mengacaukan pengguna papan klip ketika mereka tidak mengharapkannya.

Lihat Google Developers memposting di sini untuk info lebih lanjut.

API Clipboard

Perhatikan spesifikasi draf API Clipboard lengkap dapat ditemukan di sini: https://w3c.github.io/clipboard-apis/

Apakah itu didukung?

  • document.queryCommandSupported('copy') harus kembali true jika perintah "didukung oleh browser".
  • dan document.queryCommandEnabled('copy') kembali true jika document.execCommand('copy') akan berhasil jika dipanggil sekarang. Memeriksa untuk memastikan perintah dipanggil dari thread yang diinisiasi oleh pengguna dan persyaratan lainnya terpenuhi.

Namun sebagai contoh masalah kompatibilitas browser, Google Chrome dari ~ April hingga ~ Oktober 2015 hanya kembali true dari document.queryCommandSupported('copy') jika perintah dipanggil dari utas yang diinisiasi oleh pengguna.

Catat detail kompatibilitas di bawah ini.

Detail Kompatibilitas Browser

Sementara panggilan sederhana untuk document.execCommand('copy') terbungkus dalam try/catch blok yang disebut sebagai hasil dari klik pengguna akan membuat Anda menggunakan kompatibilitas paling berikut ini memiliki beberapa provisos:

Panggilan ke document.execCommand, document.queryCommandSupported atau document.queryCommandEnabled harus dibungkus dalam try/catch blok.

Implementasi browser dan versi browser yang berbeda membuang jenis pengecualian yang berbeda saat dipanggil alih-alih kembali false.

Implementasi browser yang berbeda masih dalam fluks dan API Clipboard masih dalam konsep, jadi ingatlah untuk melakukan pengujian Anda.


1581
2018-06-12 18:56



Menyalin otomatis ke clipboard mungkin berbahaya, oleh karena itu sebagian besar browser (kecuali IE) membuatnya sangat sulit. Secara pribadi, saya menggunakan trik sederhana berikut ini:

function copyToClipboard(text) {
  window.prompt("Copy to clipboard: Ctrl+C, Enter", text);
}

Pengguna disajikan dengan kotak prompt, di mana teks yang akan disalin sudah dipilih. Sekarang sudah cukup untuk menekan Ctrl+C dan Memasukkan (untuk menutup kotak) - dan voila!

Sekarang operasi salin clipboard AMAN, karena pengguna melakukannya secara manual (tetapi dengan cara yang cukup sederhana). Tentu saja, berfungsi di semua browser.

<button id="demo" onclick="copyToClipboard(document.getElementById('demo').innerHTML)">This is what I want to copy</button>

<script>
  function copyToClipboard(text) {
    window.prompt("Copy to clipboard: Ctrl+C, Enter", text);
  }
</script>


1195
2018-05-19 08:06



Pendekatan berikut ini bekerja di Chrome, Firefox, Internet Explorer, dan Edge, dan di Safari versi terbaru (Dukungan penyalinan ditambahkan di versi 10 yang dirilis Oktober 2016).

  • Buat textarea dan atur isinya ke teks yang ingin Anda salin ke clipboard.
  • Tambahkan textarea ke DOM.
  • Pilih teks di textarea.
  • Panggil document.execCommand ("copy")
  • Hapus textarea dari dom.

Catatan: Anda tidak akan melihat textarea, seperti yang ditambahkan dan dihapus dalam permintaan sinkronisasi kode Javascript yang sama.

Beberapa hal yang harus diperhatikan jika Anda menerapkan ini sendiri:

  • Untuk alasan keamanan, ini hanya dapat dipanggil dari pengendali event seperti klik (Sama seperti membuka jendela).
  • IE akan menampilkan dialog izin saat pertama kali clipboard diperbarui.
  • IE, dan Edge akan menggulir ketika textarea difokuskan.
  • execCommand () dapat melempar dalam beberapa kasus.
  • Baris dan tab baru dapat tertelan kecuali Anda menggunakan textarea. (Sebagian besar artikel tampaknya merekomendasikan menggunakan div)
  • Textarea akan terlihat ketika dialog IE ditampilkan, Anda juga perlu menyembunyikannya, atau menggunakan api clipboardData IE spesifik.
  • Di sistem administrator IE dapat menonaktifkan API clipboard.

Fungsi di bawah ini harus menangani semua masalah berikut ini sebersih mungkin. Silakan tinggalkan komentar jika Anda menemukan masalah atau memiliki saran untuk memperbaikinya.

// Copies a string to the clipboard. Must be called from within an 
// event handler such as click. May return false if it failed, but
// this is not always possible. Browser support for Chrome 43+, 
// Firefox 42+, Safari 10+, Edge and IE 10+.
// IE: The clipboard feature may be disabled by an administrator. By
// default a prompt is shown the first time the clipboard is 
// used (per session).
function copyToClipboard(text) {
    if (window.clipboardData && window.clipboardData.setData) {
        // IE specific code path to prevent textarea being shown while dialog is visible.
        return clipboardData.setData("Text", text); 

    } else if (document.queryCommandSupported && document.queryCommandSupported("copy")) {
        var textarea = document.createElement("textarea");
        textarea.textContent = text;
        textarea.style.position = "fixed";  // Prevent scrolling to bottom of page in MS Edge.
        document.body.appendChild(textarea);
        textarea.select();
        try {
            return document.execCommand("copy");  // Security exception may be thrown by some browsers.
        } catch (ex) {
            console.warn("Copy to clipboard failed.", ex);
            return false;
        } finally {
            document.body.removeChild(textarea);
        }
    }
}

https://jsfiddle.net/fx6a6n6x/


194
2017-11-26 00:03



Jika Anda menginginkan solusi yang sangat sederhana (membutuhkan waktu kurang dari 5 menit untuk diintegrasikan) dan terlihat bagus di luar kotak, maka Clippy adalah alternatif yang bagus untuk beberapa solusi yang lebih kompleks.

Clippy

Itu ditulis oleh salah satu pendiri Github. Contoh kode Flash embed di bawah ini:

<object 
   classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000"
   width="110"
   height="14"
   id="clippy">
  <param name="movie" value="/flash/clippy.swf"/>
  <param name="allowScriptAccess" value="always"/>
  <param name="quality" value="high"/>
  <param name="scale" value="noscale"/>
  <param NAME="FlashVars" value="text=#{text}"/>
  <param name="bgcolor" value="#{bgcolor}"/>
  <embed 
     src="/flash/clippy.swf"
     width="110"
     height="14"
     name="clippy"
     quality="high"
     allowScriptAccess="always"
     type="application/x-shockwave-flash"
     pluginspage="http://www.macromedia.com/go/getflashplayer"
     FlashVars="text=#{text}"
     bgcolor="#{bgcolor}"/>
</object>

Ingat untuk mengganti #{text} dengan teks yang perlu Anda salin, dan #{bgcolor} dengan warna.


93
2017-10-17 14:40



Membaca dan memodifikasi clipboard dari halaman web menimbulkan masalah keamanan dan privasi. Namun, di Internet Explorer, Anda bisa melakukannya. aku menemukan ini contoh cuplikan:

    <script type="text/javascript">
        function select_all(obj) {
            var text_val=eval(obj);
            text_val.focus();
            text_val.select();
            r = text_val.createTextRange();
            if (!r.execCommand) return; // feature detection
            r.execCommand('copy');
        }
    </script>
    <input value="http://www.sajithmr.com"
     onclick="select_all(this)" name="url" type="text" />


77
2017-12-30 13:33



Saya baru saja menulis a pos blog teknis pada masalah ini (saya bekerja di Lucidchart dan baru-baru ini kami melakukan perbaikan pada clipboard kami).

Menyalin teks biasa ke clipboard relatif sederhana, dengan asumsi Anda ingin melakukannya selama acara penyalinan sistem (pengguna menekan CtrlC atau menggunakan menu browser).

var isIe = (navigator.userAgent.toLowerCase().indexOf("msie") != -1 
           || navigator.userAgent.toLowerCase().indexOf("trident") != -1);

document.addEventListener('copy', function(e) {
    var textToPutOnClipboard = "This is some text";
    if (isIe) {
        window.clipboardData.setData('Text', textToPutOnClipboard);    
    } else {
        e.clipboardData.setData('text/plain', textToPutOnClipboard);
    }
    e.preventDefault();
});

Menaruh teks di clipboard tidak selama acara penyalinan sistem jauh lebih sulit. Sepertinya beberapa dari jawaban ini merupakan referensi cara untuk melakukannya melalui Flash, yang merupakan satu-satunya cara lintas-browser untuk melakukannya (sejauh yang saya mengerti).

Selain itu, ada beberapa opsi berdasarkan browser per browser.

Ini adalah yang paling sederhana di IE, di mana Anda dapat mengakses objek clipboardData kapan saja dari JavaScript melalui:

window.clipboardData

(Ketika Anda mencoba untuk melakukan ini di luar sistem memotong, menyalin, atau menempelkan acara, bagaimanapun, IE akan meminta pengguna untuk memberikan izin clipboard aplikasi web.)

Di Chrome, Anda dapat membuat ekstensi Chrome yang akan memberi Anda izin clipboard (Inilah yang kami lakukan untuk Lucidchart). Kemudian untuk pengguna dengan ekstensi Anda terpasang, Anda hanya perlu mem-fire sistem acara sendiri:

document.execCommand('copy');

Sepertinya Firefox memiliki beberapa opsi yang memungkinkan pengguna memberikan izin ke situs tertentu untuk mengakses papan klip, tetapi saya belum mencoba salah satu dari ini secara pribadi.


65
2017-12-03 20:31



clipboard.js adalah utilitas kecil, non-flash, yang memungkinkan menyalin teks atau data html ke clipboard. Ini sangat mudah digunakan, cukup sertakan .js dan gunakan sesuatu seperti ini:

<button id='markup-copy'>Copy Button</button>

<script>
document.getElementById('markup-copy').addEventListener('click', function() {
  clipboard.copy({
    'text/plain': 'Markup text. Paste me into a rich text editor.',
    'text/html': '<i>here</i> is some <b>rich text</b>'
  }).then(
    function(){console.log('success'); },
    function(err){console.log('failure', err);
  });

});
</script>

clipboard.js juga aktif GitHub


44
2017-08-11 15:33