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

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

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

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

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


当前回答

现场演示

在Chrome / FF / IE11上测试

有一个Chrome/IE的烦恼是这些浏览器为每一行添加<div>元素。这里有一篇关于这个的文章,它可以通过设置contentteditable元素为display:inline-block来修复

选择一些突出显示的HTML并粘贴在这里:

function onPaste(e){ var content; e.preventDefault(); if( e.clipboardData ){ content = e.clipboardData.getData('text/plain'); document.execCommand('insertText', false, content); return false; } else if( window.clipboardData ){ content = window.clipboardData.getData('Text'); if (window.getSelection) window.getSelection().getRangeAt(0).insertNode( document.createTextNode(content) ); } } /////// EVENT BINDING ///////// document.querySelector('[contenteditable]').addEventListener('paste', onPaste); [contenteditable]{ /* chroem bug: https://stackoverflow.com/a/24689420/104380 */ display:inline-block; width: calc(100% - 40px); min-height:120px; margin:10px; padding:10px; border:1px dashed green; } /* mark HTML inside the "contenteditable" (Shouldn't be any OFC!)' */ [contenteditable] *{ background-color:red; } <div contenteditable></div>

其他回答

这招对我很管用:

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);" />

现场演示

在Chrome / FF / IE11上测试

有一个Chrome/IE的烦恼是这些浏览器为每一行添加<div>元素。这里有一篇关于这个的文章,它可以通过设置contentteditable元素为display:inline-block来修复

选择一些突出显示的HTML并粘贴在这里:

function onPaste(e){ var content; e.preventDefault(); if( e.clipboardData ){ content = e.clipboardData.getData('text/plain'); document.execCommand('insertText', false, content); return false; } else if( window.clipboardData ){ content = window.clipboardData.getData('Text'); if (window.getSelection) window.getSelection().getRangeAt(0).insertNode( document.createTextNode(content) ); } } /////// EVENT BINDING ///////// document.querySelector('[contenteditable]').addEventListener('paste', onPaste); [contenteditable]{ /* chroem bug: https://stackoverflow.com/a/24689420/104380 */ display:inline-block; width: calc(100% - 40px); min-height:120px; margin:10px; padding:10px; border:1px dashed green; } /* mark HTML inside the "contenteditable" (Shouldn't be any OFC!)' */ [contenteditable] *{ background-color:red; } <div contenteditable></div>

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

这对于Nico的回答来说太长了,我认为它在Firefox上已经不起作用了(根据评论),在Safari上也不起作用了。

首先,您现在似乎可以直接从剪贴板读取。而不是像这样的代码:

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');
}

use:

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');
}

因为Firefox有一个类型字段,它是一个DOMStringList,它不实现测试。

Next Firefox将不允许粘贴,除非焦点位于contentteditable =true字段中。

最后,Firefox将不允许可靠地粘贴,除非焦点在文本区域(或者可能是输入),这不仅是contenteditable=true,而且:

不显示:没有 隐藏不可见性: 不是零大小

I was trying to hide the text field so I could make paste work over a JS VNC emulator (i.e. it was going to a remote client and there was no actually textarea etc to paste into). I found trying to hide the text field in the above gave symptoms where it worked sometimes, but typically failed on the second paste (or when the field was cleared to prevent pasting the same data twice) as the field lost focus and would not properly regain it despite focus(). The solution I came up with was to put it at z-order: -1000, make it display:none, make it as 1px by 1px, and set all the colours to transparent. Yuck.

在Safari上,你应用上面的第二部分,即你需要有一个不显示的文本区域:none。

这是上面发布的一个现有代码,但我已经为IE更新了它,错误是当现有的文本被选择和粘贴时,不会删除所选的内容。下面的代码已经修复了这个问题

selRange.deleteContents(); 

参见下面的完整代码

$('[contenteditable]').on('paste', function (e) {
    e.preventDefault();

    if (window.clipboardData) {
        content = window.clipboardData.getData('Text');        
        if (window.getSelection) {
            var selObj = window.getSelection();
            var selRange = selObj.getRangeAt(0);
            selRange.deleteContents();                
            selRange.insertNode(document.createTextNode(content));
        }
    } else if (e.originalEvent.clipboardData) {
        content = (e.originalEvent || e).clipboardData.getData('text/plain');
        document.execCommand('insertText', false, content);
    }        
});