解决方案1(仅纯文本,需要Firefox 22+)
适用于IE6 +,FF 22 +,Chrome,Safari,Edge(仅在IE9 +中进行过测试,但应在较低版本中使用)
如果需要粘贴<= 22的HTML或Firefox的支持,请参阅解决方案#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而不是剪贴板数据的字符串而在Firefox中捕获错误。