JavaScript在粘贴事件上获取剪贴板数据(跨浏览器)
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JavaScript在粘贴事件上获取剪贴板数据(跨浏览器)相关的知识,希望对你有一定的参考价值。
Web应用程序如何检测粘贴事件并检索要粘贴的数据?
我想在将文本粘贴到富文本编辑器之前删除html内容。
之后粘贴后清理文本有效,但问题是所有以前的格式都丢失了。例如,我可以在编辑器中编写一个句子并将其设为粗体,但是当我粘贴新文本时,所有格式都会丢失。我想只清理粘贴的文本,并保持以前的格式不变。
理想情况下,该解决方案应适用于所有现代浏览器(例如,MSIE,Gecko,Chrome和Safari)。
请注意,MSIE有clipboardData.getData()
,但我找不到其他浏览器的类似功能。
自写这个答案后情况发生了变化:现在Firefox已经在版本22中添加了支持,现在所有主流浏览器都支持在粘贴事件中访问剪贴板数据。有关示例,请参阅Nico Burns's answer。
在过去,这通常不可能以跨浏览器的方式进行。理想的情况是能够通过paste
事件which is possible in recent browsers获取粘贴的内容,但不能在某些旧浏览器(特别是Firefox <22)中获取。
当您需要支持旧版浏览器时,您可以做的就是参与其中,并且可以在Firefox 2 +,IE 5.5+和WebKit浏览器(如Safari或Chrome)中使用。 TinyMCE和CKEditor的最新版本都使用这种技术:
- 使用按键事件处理程序检测ctrl-v / shift-ins事件
- 在该处理程序中,保存当前用户选择,在屏幕外添加一个textarea元素(比如左边-1000px),关闭
designMode
并在textarea上调用focus()
,从而移动插入符并有效地重定向粘贴 - 在事件处理程序中设置一个非常简短的计时器(比如说1毫秒),调用另一个存储textarea值的函数,从文档中删除textarea,重新打开
designMode
,恢复用户选择并粘贴文本。
请注意,这仅适用于键盘粘贴事件,而不适用于上下文或编辑菜单中的粘贴。当粘贴事件触发时,将插入符重定向到textarea(在某些浏览器中,至少)为时已晚。
如果您需要支持Firefox 2,请注意您需要将textarea放在父文档中,而不是将WYSIWYG编辑器iframe的文档放在该浏览器中。
适用于我的解决方案是,如果要粘贴到文本输入,则会将事件侦听器添加到粘贴事件。由于粘贴事件发生在输入更改中的文本之前,因此我在on paste处理程序中创建了一个延迟函数,在其中我检查粘贴时发生的输入框中的更改:
Get the pasted content on document on paste event
这对于Nico的回答来说太长了,我认为这不再适用于Firefox(根据评论),并且在Safari上不适用于我。
首先,您现在似乎可以直接从剪贴板中读取。而不是像以下代码:
onPaste: function() {
var oThis = this;
setTimeout(function() { // Defer until onPaste() is done
console.log('paste', oThis.input.value);
// Manipulate pasted input
}, 1);
}
使用:
if (/text/plain/.test(e.clipboardData.types)) {
// shouldn't this be writing to elem.value for text/plain anyway?
elem.innerHTML = e.clipboardData.getData('text/plain');
}
因为Firefox有一个types = e.clipboardData.types;
if (((types instanceof DOMStringList) && types.contains("text/plain")) ||
(/text/plain/.test(types))) {
// shouldn't this be writing to elem.value for text/plain anyway?
elem.innerHTML = e.clipboardData.getData('text/plain');
}
字段,这是一个没有实现types
的DOMStringList
。
除非焦点位于test
字段中,否则Firefox将不允许粘贴。
最后,除非焦点位于contenteditable=true
(或可能是输入)中,否则Firefox不会允许可靠粘贴,这不仅是textarea
而且还是:
- 不是
contenteditable=true
- 不是
display:none
- 不是零大小
我试图隐藏文本字段,以便我可以在JS VNC模拟器上进行粘贴工作(即,它将转到远程客户端,并且实际上没有粘贴到visibility:hidden
等)。我发现试图隐藏上面的文本字段给出了有时工作的症状,但通常在第二次粘贴时失败(或当字段被清除以防止粘贴相同的数据两次),因为字段失去焦点并且无法正常恢复它尽管textarea
。我提出的解决方案是将它放在focus()
,使它成为z-order: -1000
,使其成为1px 1px,并将所有颜色设置为透明。呸。
在Safari上,你应用上面的第二部分,即你需要有一个不是display:none
的textarea
。
首先想到的是谷歌关闭lib display:none
的粘贴处理程序
这对我有用:
http://closure-library.googlecode.com/svn/trunk/closure/goog/demos/pastehandler.html
这个解决方案是替换html标签,它简单而且跨浏览器;检查这个jsfiddle:function onPasteMe(currentData, maxLen) {
// validate max length of pasted text
var totalCharacterCount = window.clipboardData.getData('Text').length;
}
<input type="text" onPaste="return onPasteMe(this, 50);" />
,核心代码:
http://jsfiddle.net/tomwan/cbp1u2cx/1/
注意:你应该在背面做一些关于xss过滤器的工作,因为这个解决方案不能过滤像“<< >>”这样的字符串
你可以这样做:
使用此jQuery插件进行前贴后事件:
var $plainText = $("#plainText");
var $linkOnly = $("#linkOnly");
var $html = $("#html");
$plainText.on('paste', function (e) {
window.setTimeout(function () {
$plainText.html(removeAllTags(replaceStyleAttr($plainText.html())));
}, 0);
});
$linkOnly.on('paste', function (e) {
window.setTimeout(function () {
$linkOnly.html(removeTagsExcludeA(replaceStyleAttr($linkOnly.html())));
}, 0);
});
function replaceStyleAttr (str) {
return str.replace(/(<[wW]*?)(style)([wW]*?>)/g, function (a, b, c, d) {
return b + 'style_replace' + d;
});
}
function removeTagsExcludeA (str) {
return str.replace(/</?((?!a)(w+))s*[wW]*?>/g, '');
}
function removeAllTags (str) {
return str.replace(/</?(w+)s*[wW]*?>/g, '');
}
现在你可以使用这个插件;:
$.fn.pasteEvents = function( delay ) {
if (delay == undefined) delay = 20;
return $(this).each(function() {
var $el = $(this);
$el.on("paste", function() {
$el.trigger("prepaste");
setTimeout(function() { $el.trigger("postpaste"); }, delay);
});
});
};
释
首先为所有现有元素设置uid作为数据属性。
然后比较POST PASTE事件的所有节点。因此,通过比较,您可以识别新插入的一个,因为它们将具有uid,然后只需从新创建的元素中删除style / class / id属性,以便您可以保留旧的格式。
$('#txt').on("prepaste", function() {
$(this).find("*").each(function(){
var tmp=new Date.getTime();
$(this).data("uid",tmp);
});
}).pasteEvents();
$('#txt').on("postpaste", function() {
$(this).find("*").each(function(){
if(!$(this).data("uid")){
$(this).removeClass();
$(this).removeAttr("style id");
}
});
}).pasteEvents();
只需让浏览器像往常一样在其内容可编辑div中粘贴,然后在粘贴之后交换用于自定义文本样式的任何span元素和文本本身。这似乎在Internet Explorer和我试过的其他浏览器中都可以正常工作......
$('#dom').on('paste',function (e){
setTimeout(function(){
console.log(e.currentTarget.value);
},0);
});
此解决方案假定您正在运行jQuery,并且您不希望在任何内容可编辑div中使用文本格式。
好的一面是,它非常简单。
$('[contenteditable]').on('paste', function (e) {
setTimeout(function () {
$(e.target).children('span').each(function () {
$(this).replaceWith($(this).text());
});
}, 0);
});
简单方案:
function myFunct( e ){
e.preventDefault();
var pastedText = undefined;
if( window.clipboardData && window.clipboardData.getData ){
pastedText = window.clipboardData.getData('Text');
}
else if( e.clipboardData && e.clipboardData.getData ){
pastedText = e.clipboardData.getData('text/plain');
}
//work with text
}
document.onpaste = myFunct;
Solution #1 (Plain Text only and requires 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
函数的参数“
以上是关于JavaScript在粘贴事件上获取剪贴板数据(跨浏览器)的主要内容,如果未能解决你的问题,请参考以下文章