Home Articles

JavaScript在粘贴事件上获取剪贴板数据(跨浏览器)

Asked
Viewed 333 times
262

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

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

之后粘贴后清理文本有效,但问题是所有以前的格式都丢失了 . 例如,我可以在编辑器中编写一个句子并将其设为粗体,但是当我粘贴新文本时,所有格式都会丢失 . 我想只清理粘贴的文本,并保持以前的格式不变 .

理想情况下,该解决方案应适用于所有现代浏览器(例如,MSIE,Gecko,Chrome和Safari) .

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

20 Answers

  • 271

    解决方案#1(仅限纯文本,需要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/

    请注意,此解决方案使用参数'Text'作为 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/

    解释

    divonpaste 事件附加了 handlePaste 函数并传递了一个参数:粘贴事件的 event 对象 . 我们特别感兴趣的是此事件的 clipboardData 属性,它可以在非ie浏览器中启用剪贴板访问 . 在IE中,等效的是 window.clipboardData ,尽管它的API略有不同 .

    请参阅下面的资源部分


    The handlepaste function:

    这个功能有两个分支 .

    第一个检查是否存在 event.clipboardData 并检查它的 types 属性是否包含'text/html'( types 可以是使用 contains 方法检查的 DOMStringList ,也可以是使用 indexOf 方法检查的字符串) . 如果满足所有这些条件,那么我们按照解决方案#1进行,除了使用'text/html'而不是'text/plain' . 目前适用于Chrome和Firefox 22 .

    如果不支持此方法(所有其他浏览器),那么我们

    • 将元素的内容保存到 DocumentFragment

    • 清空元素

    • 调用 waitForPastedData 函数


    The waitforpastedata function:

    此函数首先轮询粘贴的数据(每20ms一次),这是必要的,因为它不会立即显示 . 当数据出现时:

    • 将可编辑div(现在是粘贴数据)的innerHTML保存到变量中

    • 恢复DocumentFragment中保存的内容

    • 使用检索到的数据调用'processPaste'函数


    The processpaste function:

    使用粘贴的数据做任意事情 . 在这种情况下,我们只是提醒数据,你可以做任何你喜欢的事 . 您可能希望通过某种数据清理过程运行粘贴的数据 .


    Saving and restoring the cursor position

    在实际情况中,您可能希望在之前保存选择,然后将其恢复(Set cursor position on contentEditable <div>) . 然后,您可以在用户启动粘贴操作时将粘贴的数据插入光标所在的位置 .

    资源:

    感谢Tim Down建议使用DocumentFragment,并且因为使用DOMStringList而不是clipData.types的字符串而在Firefox中捕获错误 .

  • 133

    The situation has changed since writing this answer: now that Firefox has added support in version 22, all major browsers now support accessing the clipboard data in a paste event. See Nico Burns's answer for an example.

    在过去,这通常不可能以跨浏览器的方式进行 . 理想情况是能够通过 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的文档放在该浏览器中 .

  • 112

    这是上面发布的现有代码,但我已经为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);
        }        
    });
    
  • 24

    我已经为Tim Downs提出了一个关于屏幕外文本的概念的一些证据 . 这里是代码:

    <html>
    <head>
    <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4/jquery.min.js"></script> 
    <script language="JavaScript">
     $(document).ready(function()
    {
    
    var ctrlDown = false;
    var ctrlKey = 17, vKey = 86, cKey = 67;
    
    $(document).keydown(function(e)
    {
        if (e.keyCode == ctrlKey) ctrlDown = true;
    }).keyup(function(e)
    {
        if (e.keyCode == ctrlKey) ctrlDown = false;
    });
    
    $(".capture-paste").keydown(function(e)
    {
        if (ctrlDown && (e.keyCode == vKey || e.keyCode == cKey)){
            $("#area").css("display","block");
            $("#area").focus();         
        }
    });
    
    $(".capture-paste").keyup(function(e)
    {
        if (ctrlDown && (e.keyCode == vKey || e.keyCode == cKey)){                      
            $("#area").blur();
            //do your sanitation check or whatever stuff here
            $("#paste-output").text($("#area").val());
            $("#area").val("");
            $("#area").css("display","none");
        }
    });
    
    });
    </script>
    
    </head>
    <body class="capture-paste">
    
    <div id="paste-output"></div>
    
    
        <div>
        <textarea id="area" style="display: none; position: absolute; left: -99em;"></textarea>
        </div>
    
    </body>
    </html>
    

    只需将整个代码复制并粘贴到一个html文件中,然后尝试从文档中的任何位置粘贴(使用ctrl-v)文本 .

    我已经在IE9以及Firefox,Chrome和Opera的新版本中进行了测试 . 效果很好 . 也可以使用他喜欢的任何组合组合来实现这一功能 . 当然不要忘记包含jQuery源代码 .

    请随意使用此代码,如果您有一些改进或问题,请将其发回 . 另请注意,我不是Javascript开发人员所以我可能错过了一些东西(=>做自己的测试) .

  • 15

    基于 l2aelba anwser . 这是在FF,Safari,Chrome,IE(8,9,10和11)上测试的

    $("#editText").on("paste", function (e) {
            e.preventDefault();
    
            var text;
            var clp = (e.originalEvent || e).clipboardData;
            if (clp === undefined || clp === null) {
                text = window.clipboardData.getData("text") || "";
                if (text !== "") {
                    if (window.getSelection) {
                        var newNode = document.createElement("span");
                        newNode.innerHTML = text;
                        window.getSelection().getRangeAt(0).insertNode(newNode);
                    } else {
                        document.selection.createRange().pasteHTML(text);
                    }
                }
            } else {
                text = clp.getData('text/plain') || "";
                if (text !== "") {
                    document.execCommand('insertText', false, text);
                }
            }
        });
    
  • 10

    这个不使用任何setTimeout() .

    我使用this伟大的文章来实现跨浏览器支持 .

    $(document).on("focus", "input[type=text],textarea", function (e) {
        var t = e.target;
        if (!$(t).data("EventListenerSet")) {
            //get length of field before paste
            var keyup = function () {
                $(this).data("lastLength", $(this).val().length);
            };
            $(t).data("lastLength", $(t).val().length);
            //catch paste event
            var paste = function () {
                $(this).data("paste", 1);//Opera 11.11+
            };
            //process modified data, if paste occured
            var func = function () {
                if ($(this).data("paste")) {
                    alert(this.value.substr($(this).data("lastLength")));
                    $(this).data("paste", 0);
                    this.value = this.value.substr(0, $(this).data("lastLength"));
                    $(t).data("lastLength", $(t).val().length);
                }
            };
            if (window.addEventListener) {
                t.addEventListener('keyup', keyup, false);
                t.addEventListener('paste', paste, false);
                t.addEventListener('input', func, false);
            }
            else {//IE
                t.attachEvent('onkeyup', function () {
                    keyup.call(t);
                });
                t.attachEvent('onpaste', function () {
                    paste.call(t);
                });
                t.attachEvent('onpropertychange', function () {
                    func.call(t);
                });
            }
            $(t).data("EventListenerSet", 1);
        }
    });
    

    在粘贴之前,使用选择句柄扩展此代码:demo

  • 9
  • 5

    Simple version:

    document.querySelector('[contenteditable]').addEventListener('paste', (e) => {
        e.preventDefault();
        const text = (e.originalEvent || e).clipboardData.getData('text/plain');
        window.document.execCommand('insertText', false, text);
    });
    

    Using clipboardData

    Demo : http://jsbin.com/nozifexasu/edit?js,output

    Edge,Firefox,Chrome,Safari,Opera测试过 .


    Note: 记得检查 server-side 的输入/输出(如PHP strip-tags

  • 5

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

    使用:

    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有一个 types 字段是 DOMStringList ,它没有实现 test .

    除非焦点位于 contenteditable=true 字段中,否则Firefox将不允许粘贴 .

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

    • 不是 display:none

    • 不是 visibility:hidden

    • 不是零大小

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

    在Safari上,您应用上述第二部分,即您需要 textarea ,而不是 display:none .

  • 4

    这对我有用:

    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);" />
    
  • 4
    $('#dom').on('paste',function (e){
        setTimeout(function(){
            console.log(e.currentTarget.value);
        },0);
    });
    
  • 3

    Live Demo

    在Chrome / FF / IE11上测试过

    存在Chrome / IE烦恼,即这些浏览器为每个新行添加 <div> 元素 . 有关于此here的帖子,可以通过将contenteditable元素设置为 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>
    
  • 2

    这适用于所有支持onpaste事件和变异观察器的浏览器 .

    此解决方案仅比获取文本更进一步,它实际上允许您在粘贴到元素之前编辑粘贴的内容 .

    它的工作原理是使用contenteditable,onpaste事件(由所有主流浏览器支持)和变异观察者(由Chrome,Firefox和IE11支持)

    step 1

    创建一个具有contenteditable的HTML元素

    <div contenteditable="true" id="target_paste_element"></div>
    

    step 2

    在您的Javascript代码中添加以下事件

    document.getElementById("target_paste_element").addEventListener("paste", pasteEventVerifierEditor.bind(window, pasteCallBack), false);
    

    我们需要绑定pasteCallBack,因为异步调用变异观察器 .

    step 3

    将以下函数添加到您的代码中

    function pasteEventVerifierEditor(callback, e)
    {
       //is fired on a paste event. 
        //pastes content into another contenteditable div, mutation observer observes this, content get pasted, dom tree is copied and can be referenced through call back.
        //create temp div
        //save the caret position.
        savedCaret = saveSelection(document.getElementById("target_paste_element"));
    
        var tempDiv = document.createElement("div");
        tempDiv.id = "id_tempDiv_paste_editor";
        //tempDiv.style.display = "none";
        document.body.appendChild(tempDiv);
        tempDiv.contentEditable = "true";
    
        tempDiv.focus();
    
        //we have to wait for the change to occur.
        //attach a mutation observer
        if (window['MutationObserver'])
        {
            //this is new functionality
            //observer is present in firefox/chrome and IE11
            // select the target node
            // create an observer instance
            tempDiv.observer = new MutationObserver(pasteMutationObserver.bind(window, callback));
            // configuration of the observer:
            var config = { attributes: false, childList: true, characterData: true, subtree: true };
    
            // pass in the target node, as well as the observer options
            tempDiv.observer.observe(tempDiv, config);
    
        }   
    
    }
    
    
    
    function pasteMutationObserver(callback)
    {
    
        document.getElementById("id_tempDiv_paste_editor").observer.disconnect();
        delete document.getElementById("id_tempDiv_paste_editor").observer;
    
        if (callback)
        {
            //return the copied dom tree to the supplied callback.
            //copy to avoid closures.
            callback.apply(document.getElementById("id_tempDiv_paste_editor").cloneNode(true));
        }
        document.body.removeChild(document.getElementById("id_tempDiv_paste_editor"));
    
    }
    
    function pasteCallBack()
    {
        //paste the content into the element.
        restoreSelection(document.getElementById("target_paste_element"), savedCaret);
        delete savedCaret;
    
        pasteHtmlAtCaret(this.innerHTML, false, true);
    }   
    
    
    saveSelection = function(containerEl) {
    if (containerEl == document.activeElement)
    {
        var range = window.getSelection().getRangeAt(0);
        var preSelectionRange = range.cloneRange();
        preSelectionRange.selectNodeContents(containerEl);
        preSelectionRange.setEnd(range.startContainer, range.startOffset);
        var start = preSelectionRange.toString().length;
    
        return {
            start: start,
            end: start + range.toString().length
        };
    }
    };
    
    restoreSelection = function(containerEl, savedSel) {
        containerEl.focus();
        var charIndex = 0, range = document.createRange();
        range.setStart(containerEl, 0);
        range.collapse(true);
        var nodeStack = [containerEl], node, foundStart = false, stop = false;
    
        while (!stop && (node = nodeStack.pop())) {
            if (node.nodeType == 3) {
                var nextCharIndex = charIndex + node.length;
                if (!foundStart && savedSel.start >= charIndex && savedSel.start <= nextCharIndex) {
                    range.setStart(node, savedSel.start - charIndex);
                    foundStart = true;
                }
                if (foundStart && savedSel.end >= charIndex && savedSel.end <= nextCharIndex) {
                    range.setEnd(node, savedSel.end - charIndex);
                    stop = true;
                }
                charIndex = nextCharIndex;
            } else {
                var i = node.childNodes.length;
                while (i--) {
                    nodeStack.push(node.childNodes[i]);
                }
            }
        }
    
        var sel = window.getSelection();
        sel.removeAllRanges();
        sel.addRange(range);
    }
    
    function pasteHtmlAtCaret(html, returnInNode, selectPastedContent) {
    //function written by Tim Down
    
    var sel, range;
    if (window.getSelection) {
        // IE9 and non-IE
        sel = window.getSelection();
        if (sel.getRangeAt && sel.rangeCount) {
            range = sel.getRangeAt(0);
            range.deleteContents();
    
            // Range.createContextualFragment() would be useful here but is
            // only relatively recently standardized and is not supported in
            // some browsers (IE9, for one)
            var el = document.createElement("div");
            el.innerHTML = html;
            var frag = document.createDocumentFragment(), node, lastNode;
            while ( (node = el.firstChild) ) {
                lastNode = frag.appendChild(node);
            }
            var firstNode = frag.firstChild;
            range.insertNode(frag);
    
            // Preserve the selection
            if (lastNode) {
                range = range.cloneRange();
                if (returnInNode)
                {
                    range.setStart(lastNode, 0); //this part is edited, set caret inside pasted node.
                }
                else
                {
                    range.setStartAfter(lastNode); 
                }
                if (selectPastedContent) {
                    range.setStartBefore(firstNode);
                } else {
                    range.collapse(true);
                }
                sel.removeAllRanges();
                sel.addRange(range);
            }
        }
    } else if ( (sel = document.selection) && sel.type != "Control") {
        // IE < 9
        var originalRange = sel.createRange();
        originalRange.collapse(true);
        sel.createRange().pasteHTML(html);
        if (selectPastedContent) {
            range = sel.createRange();
            range.setEndPoint("StartToStart", originalRange);
            range.select();
        }
    }
    

    }

    代码的作用:

    • 有人使用ctrl-v,contextmenu或其他方法触发粘贴事件

    • 在粘贴事件中,创建了一个具有contenteditable的新元素(具有contenteditable的元素具有提升的权限)

    • 保存目标元素的插入符号位置 .

    • 焦点设置为新元素

    • 内容被粘贴到新元素中并在DOM中呈现 .

    • 变异观察者捕获了这个(它记录了对dom树和内容的所有更改) . 然后触发突变事件 .

    • 粘贴内容的dom被克隆到变量中并返回到回调 . 临时元素被破坏 .

    • 回调接收克隆的DOM . 插入符号已恢复 . 您可以在将其附加到目标之前对其进行编辑 . 元件 . 在这个例子中,我使用Tim Downs函数来保存/恢复插入符并将HTML粘贴到元素中 .

    非常感谢Tim Down看到这篇文章的答案:

    Get the pasted content on document on paste event

  • 2

    只需让浏览器像往常一样在其内容可编辑div中粘贴,然后在粘贴之后交换用于自定义文本样式的任何span元素和文本本身 . 这似乎在Internet Explorer和我试过的其他浏览器中都可以正常工作......

    $('[contenteditable]').on('paste', function (e) {
        setTimeout(function () {
            $(e.target).children('span').each(function () {
                $(this).replaceWith($(this).text());
            });
        }, 0);
    });
    

    此解决方案假定您正在运行 jQueryyou don't want text formatting in any of your content editable divs .

    好的一面是,它非常简单 .

  • 1

    对于 cleaning the pasted textreplacing the currently selected text with the pasted text ,问题非常重要:

    <div id='div' contenteditable='true' onpaste='handlepaste(this, event)'>Paste</div>
    

    JS:

    function handlepaste(el, e) {
      document.execCommand('insertText', false, e.clipboardData.getData('text/plain'));
      e.preventDefault();
    }
    
  • 1

    适用于我的解决方案是,如果要粘贴到文本输入,则会将事件侦听器添加到粘贴事件 . 由于粘贴事件发生在输入更改中的文本之前,因此我在on paste处理程序中创建了一个延迟函数,在其中我检查粘贴时发生的输入框中的更改:

    onPaste: function() {
        var oThis = this;
        setTimeout(function() { // Defer until onPaste() is done
            console.log('paste', oThis.input.value);
            // Manipulate pasted input
        }, 1);
    }
    
  • 1

    你可以这样做:

    使用此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();
    

    Explaination

    首先为所有现有元素设置uid作为数据属性 .

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

  • 1
    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;
    
  • 1

    简单方案:

    document.onpaste = function(e) {
        var pasted = e.clipboardData.getData('Text');
        console.log(pasted)
    }
    
  • 0

    这个解决方案是替换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过滤器的工作,因为这个解决方案不能过滤像“<< >>”这样的字符串

Related