web应用程序如何检测粘贴事件并检索要粘贴的数据?

我想在文本粘贴到富文本编辑器之前删除HTML内容。

在粘贴后清理文本是有效的,但问题是所有以前的格式都会丢失。例如,我可以在编辑器中编写一个句子并将其加粗,但当我粘贴新文本时,所有格式都会丢失。我只想清除粘贴的文本,并保留以前的任何格式不变。

理想情况下,解决方案应该可以跨所有现代浏览器(例如,MSIE、Gecko、Chrome和Safari)工作。

注意,MSIE有clipboardData.getData(),但我找不到其他浏览器的类似功能。


当前回答

首先想到的是谷歌的闭包库的pastehandler http://closure-library.googlecode.com/svn/trunk/closure/goog/demos/pastehandler.html

其他回答

首先想到的是谷歌的闭包库的pastehandler http://closure-library.googlecode.com/svn/trunk/closure/goog/demos/pastehandler.html

当用户通过浏览器的用户界面发起“粘贴”操作时,粘贴事件将被触发。

HTML

<div class="source" contenteditable="true">Try copying text from this box...</div>
<div class="target" contenteditable="true">...and pasting it into this one</div>

JavaScript

const target = document.querySelector('div.target');

target.addEventListener('paste', (event) => {
    let paste = (event.clipboardData || window.clipboardData).getData('text');
    paste = paste.toUpperCase();

    const selection = window.getSelection();
    if (!selection.rangeCount) return false;
    selection.deleteFromDocument();
    selection.getRangeAt(0).insertNode(document.createTextNode(paste));

    event.preventDefault();
});

知道更多

为了在IE11和Chrome上都支持纯文本的复制和粘贴,我使用了以下函数。

它有两个if语句来区分IE和chome,并执行适当的代码。在第一部分中,代码从剪贴板中读取文本,在第二部分中,它将文本粘贴到光标位置,替换当前所选文本。

特别是,对于IE上的粘贴,代码获取选择范围,删除所选文本,将文本从剪贴板插入到一个新的html文本节点中,重新配置范围以在光标位置加上文本长度处插入文本节点。

代码如下:

editable.addEventListener("paste", function(e) {
    e.preventDefault();

    // Get text from the clipboard.
    var text = '';
    if (e.clipboardData || (e.originalEvent && e.originalEvent.clipboardData)) {
      text = (e.originalEvent || e).clipboardData.getData('text/plain');
    } else if (window.clipboardData) {
      text = window.clipboardData.getData('Text');
    }
    
    // bool to indicate if the user agent is internet explorer
    let isIE = /Trident/.test(navigator.userAgent);
    
    if (document.queryCommandSupported('insertText') && !isIE) {
        // Chrome etc.
        document.execCommand('insertText', false, text);
        
    } else {
        // IE.
        
        // delete content from selection.
        var sel = window.getSelection();
        var range = sel.getRangeAt(0);
        document.execCommand("delete");

        // paste plain text in a new node.
        var newNode = document.createTextNode(text);

        range.insertNode(newNode);
        range.setStart(newNode, 0)
        range.setEnd(newNode, newNode.childNodes.length);

        sel.removeAllRanges;
        sel.addRange(range);
    }

}, false);

特别是为了在IE上粘贴许多答案的文本,我找到了这个说明文档。execCommand('paste', false, text);这在IE11上不起作用,因为浏览器会一次又一次地调用粘贴事件。我用range对象上的函数替换了它。

另一个问题是,在IE11上,根据版本,函数文档。execCommand('insertText', false, text);有时可用,有时不可用,所以我显式检查浏览器是否是IE,并为它执行基于范围选择的部分代码(参见其他)。

这个解决方案是替换html标签,简单,跨浏览器;查看这个jsfiddle: http://jsfiddle.net/tomwan/cbp1u2cx/1/,核心代码:

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(/(<[\w\W]*?)(style)([\w\W]*?>)/g, function (a, b, c, d) {
        return b + 'style_replace' + d;
    });
}

function removeTagsExcludeA (str) {
    return str.replace(/<\/?((?!a)(\w+))\s*[\w\W]*?>/g, '');
}

function removeAllTags (str) {
    return str.replace(/<\/?(\w+)\s*[\w\W]*?>/g, '');
}

注意:你应该在后面做一些关于XSS过滤器的工作,因为这个解决方案不能过滤像'<<>>'这样的字符串

你可以这样做:

使用这个jQuery插件的前后粘贴事件:

$.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);
        });
    });
};

现在你可以使用这个插件;:

$('#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();

解释

首先将所有现有元素的uid设置为data属性。

然后比较所有节点的POST PASTE事件。因此,通过比较,您可以识别新插入的元素,因为它们将有uid,然后只需从新创建的元素中删除style/class/id属性,以便您可以保留旧的格式。