Solusi # 1 (Khusus Teks Biasa dan membutuhkan Firefox 22+)
Bekerja untuk IE6 +, FF 22+, Chrome, Safari, Edge (Hanya diuji di IE9 +, tetapi seharusnya berfungsi untuk versi yang lebih rendah)
Jika Anda memerlukan dukungan untuk menempelkan HTML atau Firefox <= 22, lihat Solusi # 2.
HTML
<div id='editableDiv' contenteditable='true'>Paste</div>
JavaScript
function handlePaste (e) {
var clipboardData, pastedData;
// Stop data actually being pasted into div
e.stopPropagation();
e.preventDefault();
// Get pasted data via clipboard API
clipboardData = e.clipboardData || window.clipboardData;
pastedData = clipboardData.getData('Text');
// Do whatever with pasteddata
alert(pastedData);
}
document.getElementById('editableDiv').addEventListener('paste', handlePaste);
JSFiddle: https://jsfiddle.net/swL8ftLs/12/
Perhatikan bahwa solusi ini menggunakan parameter 'Teks' untuk getData
fungsi, yang tidak standar. Namun, ini berfungsi di semua browser pada saat penulisan.
Solusi # 2 (HTML dan berfungsi untuk Firefox <= 22)
Diuji dalam IE6 +, FF 3.5+, Chrome, Safari, Edge
HTML
<div id='div' contenteditable='true'>Paste</div>
JavaScript
var editableDiv = document.getElementById('editableDiv');
function handlepaste (e) {
var types, pastedData, savedContent;
// Browsers that support the 'text/html' type in the Clipboard API (Chrome, Firefox 22+)
if (e && e.clipboardData && e.clipboardData.types && e.clipboardData.getData) {
// Check for 'text/html' in types list. See abligh's answer below for deatils on
// why the DOMStringList bit is needed. We cannot fall back to 'text/plain' as
// Safari/Edge don't advertise HTML data even if it is available
types = e.clipboardData.types;
if (((types instanceof DOMStringList) && types.contains("text/html")) || (types.indexOf && types.indexOf('text/html') !== -1)) {
// Extract data and pass it to callback
pastedData = e.clipboardData.getData('text/html');
processPaste(editableDiv, pastedData);
// Stop the data from actually being pasted
e.stopPropagation();
e.preventDefault();
return false;
}
}
// Everything else: Move existing element contents to a DocumentFragment for safekeeping
savedContent = document.createDocumentFragment();
while(editableDiv.childNodes.length > 0) {
savedContent.appendChild(editableDiv.childNodes[0]);
}
// Then wait for browser to paste content into it and cleanup
waitForPastedData(editableDiv, savedContent);
return true;
}
function waitForPastedData (elem, savedContent) {
// If data has been processes by browser, process it
if (elem.childNodes && elem.childNodes.length > 0) {
// Retrieve pasted content via innerHTML
// (Alternatively loop through elem.childNodes or elem.getElementsByTagName here)
var pastedData = elem.innerHTML;
// Restore saved content
elem.innerHTML = "";
elem.appendChild(savedContent);
// Call callback
processPaste(elem, pastedData);
}
// Else wait 20ms and try again
else {
setTimeout(function () {
waitForPastedData(elem, savedContent)
}, 20);
}
}
function processPaste (elem, pastedData) {
// Do whatever with gathered data;
alert(pastedData);
elem.focus();
}
// Modern browsers. Note: 3rd argument is required for Firefox <= 6
if (editableDiv.addEventListener) {
editableDiv.addEventListener('paste', handlepaste, false);
}
// IE <= 8
else {
editableDiv.attachEvent('onpaste', handlepaste);
}
JSFiddle: https://jsfiddle.net/nicoburns/wrqmuabo/23/
Penjelasan
The onpaste
event dari div
memiliki handlePaste
fungsi yang melekat padanya dan melewati argumen tunggal: event
objek untuk acara paste. Yang menarik bagi kami adalah clipboardData
properti acara ini yang memungkinkan akses clipboard di browser non-ie. Di IE, yang setara adalah window.clipboardData
, meskipun ini memiliki API yang sedikit berbeda.
Lihat bagian sumber daya di bawah ini.
The handlepaste
Fungsi:
Fungsi ini memiliki dua cabang.
Pemeriksaan pertama untuk keberadaan event.clipboardData
dan memeriksa apakah types
properti itu mengandung 'teks / html' ( types
bisa berupa DOMStringList
yang diperiksa menggunakan contains
metode, atau string yang diperiksa menggunakan indexOf
metode). Jika semua kondisi ini terpenuhi, maka kami melanjutkan seperti dalam solusi # 1, kecuali dengan 'teks / html' alih-alih 'teks / polos'. Ini saat ini berfungsi di Chrome dan Firefox 22+.
Jika metode ini tidak didukung (semua browser lain), maka kami
- Simpan konten elemen ke a
DocumentFragment
- Kosongkan elemennya
- Panggil
waitForPastedData
fungsinya
The waitforpastedata
Fungsi:
Fungsi ini pertama-tama memberikan jajak pendapat untuk data yang di-paste (sekali per 20 ms), yang diperlukan karena tidak langsung muncul. Ketika data telah muncul itu:
- Menyimpan innerHTML dari div yang dapat diedit (yang sekarang menjadi data yang disisipkan) ke variabel
- Kembalikan konten yang disimpan di DocumentFragment
- Memanggil fungsi 'processPaste' dengan data yang diambil
Itu processpaste
Fungsi:
Apakah hal-hal yang sewenang-wenang dengan data yang di-paste. Dalam hal ini kami hanya memberitahukan data, Anda dapat melakukan apa pun yang Anda suka. Anda mungkin ingin menjalankan data yang di-paste melalui semacam proses sanitasi data.
Menyimpan dan mengembalikan posisi kursor
Dalam situasi nyata Anda mungkin ingin menyimpan pilihan sebelumnya, dan mengembalikannya setelah itu ( Tetapkan posisi kursor pada contentEditable <div> ). Anda kemudian bisa menyisipkan data yang di-paste di posisi kursor ketika pengguna memulai tindakan tempel.
Sumber:
Terima kasih kepada Tim Down untuk menyarankan penggunaan DocumentFragment, dan abligh untuk menangkap kesalahan di Firefox karena penggunaan DOMStringList bukan string untuk clipboardData.types