解决方案#1(纯文本,需要Firefox 22+)
适用于IE6+, FF 22+, Chrome, Safari, Edge
(仅在IE9+中测试,但应该适用于较低版本)
如果您需要支持粘贴HTML或Firefox <= 22,请参阅解决方案#2。
函数handlePaste(e) {
var clipboardData,粘贴数据;
//停止数据实际粘贴到div
e.stopPropagation ();
e.preventDefault ();
//通过剪贴板API获取粘贴数据
clipboardData = e.clipboardData || window.clipboardData;
paste data = clipboardData.getData('Text');
//对粘贴数据做任何事情
警报(pastedData);
}
. getelementbyid(“editableDiv”)。addEventListener(“粘贴”,handlePaste);
<div id='editableDiv' contenteditable='true'>粘贴</div>
JSFiddle
注意,这个解决方案为getData函数使用了参数“Text”,这是非标准的。但是,在编写本文时,它可以在所有浏览器中运行。
解决方案#2 (HTML和适用于Firefox <= 22)
测试在IE6+, FF 3.5+, Chrome, Safari, Edge
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);
}
<div id='div' contenteditable='true'>Paste</div>
JSFiddle
解释
div的onpaste事件附加了handlePaste函数,并传递了一个参数:粘贴事件的事件对象。我们特别感兴趣的是这个事件的clipboardData属性,它允许在非ie浏览器中访问剪贴板。在IE中,对应的是window。clipboardData,尽管它有一个稍微不同的API。
请参阅下面的参考资料部分。
句柄粘贴函数:
这个函数有两个分支。
第一个检查事件是否存在。clipboardData和检查它的类型属性是否包含'text/html'(类型可以是使用contains方法检查的DOMStringList,也可以是使用indexOf方法检查的字符串)。如果所有这些条件都满足,那么我们继续执行解决方案#1,只是使用'text/html'而不是'text/plain'。目前Chrome和Firefox 22+都可以使用。
如果此方法不受支持(所有其他浏览器),则我们
将元素的内容保存到一个DocumentFragment中
清空元素
调用waitforpastedata函数
waitforpastedata函数:
这个函数首先轮询粘贴的数据(每20毫秒一次),这是必要的,因为它不会立即出现。当数据出现时:
保存可编辑div的innerHTML(现在是粘贴的数据)到一个变量
恢复保存在DocumentFragment中的内容
使用检索的数据调用'processPaste'函数
processpaste函数:
对粘贴的数据做任意的事情。在这种情况下,我们只是提醒数据,你可以做任何你喜欢的事情。您可能希望通过某种数据消毒过程来运行粘贴的数据。
保存并恢复光标位置
在实际情况下,您可能希望在之前保存选择,然后在之后恢复它(将光标位置设置为contentEditable <div>)。然后,您可以在用户发起粘贴操作时光标所在的位置插入粘贴的数据。
MDN资源
粘贴事件
文档片段
DomStringList
感谢Tim Down建议使用DocumentFragment,以及abligh在Firefox中捕捉由于使用DOMStringList而不是clipboardData.types的字符串而导致的错误