JavaScript获取粘贴事件的剪贴板数据(跨浏览器)
Web应用程序如何检测粘贴事件并检索要粘贴的数据?
我想在将文本粘贴到富文本编辑器之前删除HTML内容。
事后粘贴后清理文本的工作,但问题是,所有以前的格式丢失。 例如,我可以在编辑器中编写一个句子并使其变为粗体,但是当我粘贴新文本时,所有格式都会丢失。 我想只清理粘贴的文本,并保留以前的格式不变。
理想情况下,该解决方案应该适用于所有现代浏览器(例如,MSIE,Gecko,Chrome和Safari)。
请注意,MSIE有clipboardData.getData()
,但我找不到其他浏览器的类似功能。
自写这个答案以来,情况发生了变化:既然Firefox已经增加了对版本22的支持,所有主流浏览器现在都支持在粘贴事件中访问剪贴板数据。 以尼科伯恩斯的答案为例。
在过去,这通常不可能以跨浏览器的方式进行。 理想的做法是能够通过paste
事件获取粘贴的内容,这在最近的浏览器中是可能的,但在一些较旧的浏览器中是不可能的(特别是Firefox <22)。
当您需要支持旧版浏览器时,您可以做的事情非常多,并且可以在Firefox 2+,IE 5.5+和WebKit浏览器(如Safari或Chrome)中使用。 TinyMCE和CKEditor的最新版本都使用这种技术:
designMode
并调用textarea上的focus()
,从而移动插入符号并有效地重定向粘贴 designMode
,恢复用户选择并粘贴文本。 请注意,这只适用于键盘粘贴事件,不适用于上下文或编辑菜单。 在粘贴事件触发时,将脱字符重定向到textarea(至少在某些浏览器中)为时已晚。
如果您需要支持Firefox 2,请注意,您需要将textarea放在父文档中,而不是所见即所得编辑器iframe的文档在该浏览器中。
解决方案#1(仅限纯文本,需要Firefox 22+)
适用于IE6 +,FF22 +,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/
说明
div
的onpaste
事件附加了handlePaste
函数,并传递了一个参数:paste事件的event
对象。 我们特别感兴趣的是这个事件的clipboardData
属性,它允许在非ie浏览器中访问剪贴板。 在IE中相当于window.clipboardData
,虽然这有一个稍微不同的API。
参见下面的资源部分。
handlepaste
功能:
该功能有两个分支。
第一个检查是否存在event.clipboardData
并检查它的types
属性是否包含'text / html'( types
可以是使用contains
方法检查的DOMStringList
,也可以是使用indexOf
方法检查的字符串)。 如果所有这些条件都满足,那么我们按照解决方案#1进行操作,除了使用'text / html'而不是'text / plain'。 目前,该工具适用于Chrome和Firefox 22+。
如果此方法不受支持(所有其他浏览器),那么我们
DocumentFragment
waitForPastedData
函数 waitforpastedata
函数:
这个函数首先查询粘贴的数据(每20ms一次),这是必要的,因为它不会马上出现。 当数据出现时:
processpaste
功能:
用粘贴的数据做任意事情。 在这种情况下,我们只是提醒数据,你可以做任何你喜欢的事情。 您可能希望通过某种数据清理过程来运行粘贴的数据。
保存并恢复光标位置
在真实情况下,您可能希望先保存选区,然后再进行恢复(在contentEditable <div>上设置光标位置)。 然后,您可以在用户启动粘贴操作时将粘贴的数据插入光标所在的位置。
资源:
感谢Tim Down建议使用DocumentFragment,并且abligh用于捕获Firefox中的错误,因为使用了DOMStringList而不是用于clipboardData.types的字符串
简单版本: (jQuery)
$(document).on('paste','[contenteditable]',function(e) {
e.preventDefault();
var text = (e.originalEvent || e).clipboardData.getData('text/plain');
window.document.execCommand('insertText', false, text);
});
使用 clipboardData
演示: http : //jsbin.com/vokovividu/edit?js,output
IE Edge,Firefox,Chrome,Safari,Opera测试。
链接地址: http://www.djcxy.com/p/61597.html上一篇: JavaScript get clipboard data on paste event (Cross browser)
下一篇: Understanding the options in a handlebars #view helper for Ember.JS