CodeAngry
CodeAngry

Reputation: 12985

Capture Document-level Paste event without focused Input or Textarea

<!DOCTYPE html>
<html>
<head>
    <title>Clipboard Paste Text</title>
    <script src="//ajax.googleapis.com/ajax/libs/jquery/2.0.3/jquery.min.js"></script> 
    <script src="//ajax.googleapis.com/ajax/libs/jqueryui/1.10.3/jquery-ui.min.js"></script> 
</head>
<body>
    <input type="text" placeholder="paste in here" />
    <script type="text/javascript">
    /* <![CDATA[ */
    $(document, 'input[type="text"]').on('paste', function(event) {
        var oEvent = event.originalEvent;
        oEvent.preventDefault();

        var clipText = '';
        if(window.clipboardData){
            clipText = window.clipboardData.getData('Text');
        }else if(typeof oEvent == 'object' && oEvent.clipboardData){
            clipText = oEvent.clipboardData.getData('text/plain');
        }

        // console.log('Pasted ' + clipText.length + ' characters.');
        alert('Pasted ' + clipText.length + ' characters.');
    });
    /* ]]> */
    </script>
</body>
</html>

^ I have this demo code. It binds the paste event on INPUT[TEXT] and DOCUMENT.

Is this proper behavior? Is my JS correct?

I'd like to capture Ctrl+V without a input textbox in all three browsers. I'm using a text input now but I'd like to remove it completely and capture the event at document level, not at input box level. Can it be done?

PS: I need to paste large amounts of text that hog the browser if pasted in a textarea. I'm storing it in a hidden field by capturing the paste event in a inputbox. My current solution works properly but I'm still wondering if I'm missing something or FF and IE will only trigger paste events at input/textarea level.

PPS: I've already used the spellcheck=false and autocomplete=off trick to allow more text pasted... but it still hangs for a bit, and as I don't need it editable, this is a better solution.

PPS: My JS skills are rather rusty (they are more like a JS survival mode) and I have no worries for browser backward compatibility as those who'll use this update often and hard.

Made a jsfiddle: http://jsfiddle.net/ninty9notout/A42UN/

Upvotes: 8

Views: 4899

Answers (1)

Rylonian
Rylonian

Reputation: 306

From http://www.w3.org/TR/clipboard-apis/ 5.1.3 paste event

The paste event has no default action in a non-editable context, but the event fires regardless.

Chrome uses a lazy paste event, which means that it doesn't check to see if the focused element is an editable content area, which is why the paste event works on the document.

As for firefox and IE, it actually checks the element before letting allowing the paste event to be fired. So basically, you need an content editable element in order for the paste event to work in all browsers.

I played around with using a content editable DIV as the main div on the page and I think it seems to produce the results you are looking for. Forgive me if the answer seems somewhat "hackish".

You can place a contenteditable div as the container div to the rest of your webpage and not allow a user to type into the div by returning false when the user presses a key, unless it's a key for pasting.

Here is a fiddle if you want to see how I did it.

http://jsfiddle.net/NVqQ7/3/

html

<div id="pageDiv" contenteditable><div>other content</div></div>

css

html, body, #pageDiv {
    width: 100%;
    height: 100%;
    margin: 0;
    padding: 0;
}

javascript:

$(document).on('paste', function(event){
    var oEvent = event.originalEvent;
    if (event.preventDefault())
        event.preventDefault();

    var clipText = '';
    if(window.clipboardData){
        clipText = window.clipboardData.getData('Text');
    }else if(typeof oEvent == 'object' && oEvent.clipboardData){
        clipText = oEvent.clipboardData.getData('text/plain');
    }

    // console.log('Pasted ' + clipText.length + ' characters.');
    alert('Pasted ' + clipText.length + ' characters.');
});

$('#pageDiv').keydown(function(e){
    if (!event.ctrlKey)
        return false;
});

A few notes:

  1. The user still must click on the body of the page in order to activate the paste event. i.e. clicking on the browser by itself may not be enough.

  2. In firfox, you need to set the contenteditable="false" in child divs, otherwise users can add text to those elements.

  3. I had to make the div height and width 100%. If your html and body are not 100% height and width, it will not work in IE.

  4. I had to change the jquery library to a newer version for IE in order for the paste event to work on the document.

Hope this helps

Upvotes: 5

Related Questions