โซลูชัน # 1 (ข้อความล้วนเท่านั้นและต้องใช้ Firefox 22+)
ใช้งานได้กับ IE6 +, FF 22+, Chrome, Safari, Edge (ทดสอบเฉพาะใน IE9 + แต่ควรใช้ได้กับรุ่นที่ต่ำกว่า)
หากคุณต้องการการสนับสนุนสำหรับการวาง HTML หรือ Firefox <= 22 ให้ดูโซลูชัน # 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/
โปรดทราบว่าวิธีนี้ใช้พารามิเตอร์ 'ข้อความ' สำหรับgetData
ฟังก์ชั่นซึ่งไม่ได้มาตรฐาน อย่างไรก็ตามมันสามารถใช้ได้กับทุกเบราว์เซอร์ในขณะที่เขียน
โซลูชัน # 2 (HTML และใช้ได้กับ Firefox <= 22)
ทดสอบใน 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/
คำอธิบาย
onpaste
เหตุการณ์ของการdiv
มีhandlePaste
ฟังก์ชั่นที่ติดอยู่กับมันและผ่านอาร์กิวเมนต์เดียวที่: event
วัตถุสำหรับเหตุการณ์วาง สิ่งที่น่าสนใจเป็นพิเศษสำหรับเราคือclipboardData
ทรัพย์สินของเหตุการณ์นี้ซึ่งทำให้สามารถเข้าถึงคลิปบอร์ดในเบราว์เซอร์ที่ไม่ใช่เช่น ใน IE ที่เทียบเท่าคือwindow.clipboardData
แม้ว่าจะมี API ที่แตกต่างกันเล็กน้อย
ดูส่วนทรัพยากรด้านล่าง
handlepaste
ฟังก์ชั่น:
ฟังก์ชั่นนี้มีสองสาขา
การตรวจสอบครั้งแรกสำหรับการมีอยู่ของevent.clipboardData
และการตรวจสอบว่ามันเป็นtypes
คุณสมบัติที่มี 'text / html' ( types
อาจเป็นอย่างใดอย่างหนึ่งDOMStringList
ซึ่งมีการตรวจสอบโดยใช้contains
วิธีการหรือสตริงที่มีการตรวจสอบโดยใช้indexOf
วิธีการ) หากเงื่อนไขเหล่านี้เป็นจริงเราจะดำเนินการตามวิธีที่ # 1 ยกเว้นด้วย 'text / html' แทนที่จะเป็น 'text / plain' ปัจจุบันสามารถใช้งานได้ใน Chrome และ Firefox 22+
หากวิธีนี้ไม่ได้รับการสนับสนุน (เบราว์เซอร์อื่น ๆ ทั้งหมด) เราก็ทำได้
- บันทึกเนื้อหาขององค์ประกอบลงใน
DocumentFragment
- ล้างองค์ประกอบ
- เรียกใช้
waitForPastedData
ฟังก์ชัน
waitforpastedata
ฟังก์ชั่น:
ฟังก์ชันนี้สำรวจความคิดเห็นแรกสำหรับข้อมูลที่วาง (หนึ่งครั้งต่อ 20ms) ซึ่งจำเป็นเพราะไม่ปรากฏขึ้นทันที เมื่อข้อมูลปรากฏขึ้น:
- บันทึก InnerHTML ของ div ที่แก้ไขได้ (ซึ่งตอนนี้เป็นข้อมูลที่วาง) ไปยังตัวแปร
- คืนค่าเนื้อหาที่บันทึกไว้ใน DocumentFragment
- เรียกใช้ฟังก์ชัน 'processPaste' พร้อมกับดึงข้อมูล
processpaste
ฟังก์ชั่น:
ทำสิ่งที่กำหนดเองโดยใช้ข้อมูลที่วาง ในกรณีนี้เราเพียงแค่แจ้งเตือนข้อมูลคุณสามารถทำสิ่งที่คุณต้องการ คุณอาจต้องการเรียกใช้ข้อมูลที่วางผ่านกระบวนการฆ่าเชื้อข้อมูลบางประเภท
การบันทึกและกู้คืนตำแหน่งเคอร์เซอร์
ในการซิงก์จริงคุณอาจต้องการบันทึกการเลือกก่อนหน้าและเรียกคืนหลังจากนั้น ( ตั้งค่าตำแหน่งเคอร์เซอร์บน contentEditable <div> ) จากนั้นคุณสามารถแทรกข้อมูลที่วางในตำแหน่งที่เคอร์เซอร์อยู่เมื่อผู้ใช้เริ่มต้นการดำเนินการวาง
แหล่งข้อมูล:
ขอบคุณ Tim Down เพื่อแนะนำการใช้ DocumentFragment และ abligh สำหรับการตรวจจับข้อผิดพลาดใน Firefox เนื่องจากการใช้ DOMStringList แทนสตริงสำหรับ clipboardData.types