解决方案 #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 浏览器中访问剪贴板。在 IE 中,等效的是window.clipboardData
,尽管它的 API 略有不同。
请参阅下面的资源部分。
该handlepaste
函数:
这个函数有两个分支。
第一个检查event.clipboardData
是否存在并检查它的types
属性是否包含 'text/html'(types
可以DOMStringList
是使用contains
方法检查的a 或使用indexOf
方法检查的字符串)。如果所有这些条件都满足,那么我们按照解决方案 #1 进行处理,除了使用 'text/html' 而不是 'text/plain'。这目前适用于 Chrome 和 Firefox 22+。
如果不支持此方法(所有其他浏览器),那么我们
- 将元素的内容保存到
DocumentFragment
- 清空元素
- 调用
waitForPastedData
函数
该waitforpastedata
函数:
该函数首先轮询粘贴的数据(每 20 毫秒一次),这是必要的,因为它不会立即出现。当数据出现时:
- 将可编辑 div(现在是粘贴的数据)的 innerHTML 保存到一个变量
- 恢复保存在 DocumentFragment 中的内容
- 使用检索到的数据调用“processPaste”函数
该processpaste
函数:
对粘贴的数据进行任意操作。在这种情况下,我们只是提醒数据,您可以随心所欲。您可能希望通过某种数据清理过程来运行粘贴的数据。
保存和恢复光标位置
在实际情况中,您可能希望之前保存选择,然后恢复它(在 contentEditable <div> 上设置光标位置)。然后,您可以在用户启动粘贴操作时光标所在的位置插入粘贴的数据。
资源:
感谢 Tim Down 建议使用 DocumentFragment,以及由于使用 DOMStringList 而不是 clipboardData.types 的字符串而在 Firefox 中捕获错误的 abligh