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的最新版本都使用这种技术:

  1. 使用按键事件处理程序检测ctrl-v / shift-ins事件
  2. 在该处理程序中,保存当前用户选择,在屏幕外添加一个textarea元素(比如左边-1000px),关闭designMode并在textarea上调用focus(),从而移动插入符并有效地重定向粘贴
  3. 在事件处理程序中设置一个非常简短的计时器(比如说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'); } 字段,这是一个没有实现typesDOMStringList

除非焦点位于test字段中,否则Firefox将不允许粘贴。

最后,除非焦点位于contenteditable=true(或可能是输入)中,否则Firefox不会允许可靠粘贴,这不仅是textarea而且还是:

  • 不是contenteditable=true
  • 不是display:none
  • 不是零大小

我试图隐藏文本字段,以便我可以在JS VNC模拟器上进行粘贴工作(即,它将转到远程客户端,并且实际上没有粘贴到visibility:hidden等)。我发现试图隐藏上面的文本字段给出了有时工作的症状,但通常在第二次粘贴时失败(或当字段被清除以防止粘贴相同的数据两次),因为字段失去焦点并且无法正常恢复它尽管textarea。我提出的解决方案是将它放在focus(),使它成为z-order: -1000,使其成为1px 1px,并将所有颜色设置为透明。呸。

在Safari上,你应用上面的第二部分,即你需要有一个不是display:nonetextarea

另一答案

首先想到的是谷歌关闭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在粘贴事件上获取剪贴板数据(跨浏览器)的主要内容,如果未能解决你的问题,请参考以下文章

粘贴前更新剪贴板数据(不是“粘贴”事件)

js复制粘贴事件

如何在跨浏览器中读取剪贴板数据?

IOS剪贴板(复制粘贴)不能跨应用程序

JS处理剪贴板

报表神器FastReport.NET v2020.1第一个跨年新版本强势发布!