JavaScript get clipboard data on paste event (Cross browser)

前端 未结 20 2388
小蘑菇
小蘑菇 2020-11-21 11:22

How can a web application detect a paste event and retrieve the data to be pasted?

I would like to remove HTML content before the text is pasted into a rich text edi

相关标签:
20条回答
  • 2020-11-21 11:40

    This worked for me :

    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);" />
    
    0 讨论(0)
  • 2020-11-21 11:41

    I've written a little proof of concept for Tim Downs proposal here with off-screen textarea. And here goes the code:

    <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>
    

    Just copy and paste the whole code into one html file and try to paste (using ctrl-v) text from clipboard anywhere on the document.

    I've tested it in IE9 and new versions of Firefox, Chrome and Opera. Works quite well. Also it's good that one can use whatever key combination he prefers to triger this functionality. Of course don't forget to include jQuery sources.

    Feel free to use this code and if you come with some improvements or problems please post them back. Also note that I'm no Javascript developer so I may have missed something (=>do your own testign).

    0 讨论(0)
  • 2020-11-21 11:42

    For cleaning the pasted text and replacing the currently selected text with the pasted text the matter is pretty trivial:

    <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();
    }
    
    0 讨论(0)
  • 2020-11-21 11:42

    Solution that works for me is adding event listener to paste event if you are pasting to a text input. Since paste event happens before text in input changes, inside my on paste handler I create a deferred function inside which I check for changes in my input box that happened on paste:

    onPaste: function() {
        var oThis = this;
        setTimeout(function() { // Defer until onPaste() is done
            console.log('paste', oThis.input.value);
            // Manipulate pasted input
        }, 1);
    }
    
    0 讨论(0)
  • 2020-11-21 11:42

    This was too long for a comment on Nico's answer, which I don't think works on Firefox any more (per the comments), and didn't work for me on Safari as is.

    Firstly, you now appear to be able to read directly from the clipboard. Rather than code like:

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

    because Firefox has a types field which is a DOMStringList which does not implement test.

    Next Firefox will not allow paste unless the focus is in a contenteditable=true field.

    Finally, Firefox will not allow paste reliably unless the focus is in a textarea (or perhaps input) which is not only contenteditable=true but also:

    • not display:none
    • not visibility:hidden
    • not zero sized

    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.

    On Safari, you the second part of the above applies, i.e. you need to have a textarea which is not display:none.

    0 讨论(0)
  • 2020-11-21 11:45
    $('#dom').on('paste',function (e){
        setTimeout(function(){
            console.log(e.currentTarget.value);
        },0);
    });
    
    0 讨论(0)
提交回复
热议问题