35

I have a little trouble catching a pasted text into my input:

 <input type="text" id="myid" val="default">
 $('#myid').on('paste',function(){
        console.log($('#myid').val());
 });  

console.log shows:

default

How I catch the pasted text and get ready to use?

greenbandit
  • 2,267
  • 5
  • 30
  • 44

6 Answers6

60

The accepted answer is actually hacky and ugly, seems to be suggested quite often for the paste event on stackoverflow. I think a better way to do it is this

$('#someInput').bind('paste', function(e) {
    var data = e.originalEvent.clipboardData.getData('Text');
    //IE9 Equivalent ==> window.clipboardData.getData("Text");   
});
Todd Vance
  • 4,627
  • 7
  • 46
  • 66
cateyes
  • 5,208
  • 2
  • 24
  • 31
  • 4
    This does not work in IE 9 for me, but the `setTimeout` method does. – BateTech May 01 '14 at 15:09
  • 3
    window.clipboardData.getData("Text") <-- IE9 equivalent to the above. – Todd Vance Mar 23 '15 at 16:50
  • 1
    It looks like it doesn't work in Android on mobile. It returns an empty string. [example](http://jsfiddle.net/7o8qzckp/1/) – RedGiant Aug 29 '15 at 03:02
  • 1
    The accepted answer always works, while [`ClipboardEvent.clipboardData`](https://developer.mozilla.org/en-US/docs/Web/API/ClipboardEvent/clipboardData) is tagged as "experimental" by MDN, and has somewhat shaky support, especially on mobile. – adeneo Dec 10 '15 at 14:39
50

Because the paste event is triggered before the inputs value is updated, the solution is to either:

  1. Capture the data from the clipboard instead, as the clipboards data will surely be the same as the data being pasted into the input at that exact moment.

  2. Wait until the value has updated using a timer

Luckily, years after the original answer was posted, most modern browsers now support the fantastic Clipboard API, a much more elegant solution to capturing data from the clipboard.

For browsers that don't support the Clipboard API, we could fall back to the unreliable event.clipboardData if we do some checking as to which version, if any, is supported in the browser.

As a final fallback, using a timer to delay until the inputs value is updated, will work in all browsers, making this a truly cross-browser solution.

I've made a convenient function that handles everything

function catchPaste(evt, elem, callback) {
  if (navigator.clipboard && navigator.clipboard.readText) {
    // modern approach with Clipboard API
    navigator.clipboard.readText().then(callback);
  } else if (evt.originalEvent && evt.originalEvent.clipboardData) {
    // OriginalEvent is a property from jQuery, normalizing the event object
    callback(evt.originalEvent.clipboardData.getData('text'));
  } else if (evt.clipboardData) {
    // used in some browsers for clipboardData
    callback(evt.clipboardData.getData('text/plain'));
  } else if (window.clipboardData) {
    // Older clipboardData version for Internet Explorer only
    callback(window.clipboardData.getData('Text'));
  } else {
    // Last resort fallback, using a timer
    setTimeout(function() {
      callback(elem.value)
    }, 100);
  }
}

// to be used as 

$('#myid').on('paste', function(evt) {
  catchPaste(evt, this, function(clipData) {
    console.log(clipData);
  });
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input id="myid" />

Note that getting the data from the clipboard only gets you the pasted text, while waiting for the inputs value to update is the only solution above that actually gets the entire value of the input, including the newly pasted text.

adeneo
  • 312,895
  • 29
  • 395
  • 388
  • 2
    Why did you make the timeout 100 milliseconds, instead of 0? – user2867288 Sep 26 '16 at 19:29
  • 5
    @user2867288 - 4 years later, I have no idea why, I just did ? – adeneo Sep 26 '16 at 20:03
  • Just wondering if it was because it didn't work in some browsers, otherwise (IE), because ideally most people wouldn't want to add in unnecessary delays into their web application. – user2867288 Sep 27 '16 at 13:49
  • The `setTimeout` solution its fantastic if you only wants work with paste. – SilverSurfer Jun 28 '19 at 08:43
  • I would like to draw attention to the 'input' event described in another answer to this question, for a seemingly much simpler solution: https://stackoverflow.com/a/61736532/371793 – mvds Feb 04 '22 at 14:47
2

using "input" avoids the Timeout kludge on paste and is better than change which can not work for things like paste or search events.

$('input').on('input', function(e) {
    var type = e.originalEvent.inputType;
    if (typeof(type) == 'undefined'){
       type = 'search';
    switch(type){
    case 'search':
    case 'deleteByCut':
    case 'insertText':
    case 'insertFromPaste':
    case 'deleteContentBackward':
       var content = $(this).val();
    }
});

Search is a special case which doesnt generate an input type; it's basically the same as 'deleteByCut' in function in that it clears the field.

You could, of course, have different handlers for each case if necessary.

Danial
  • 1,496
  • 14
  • 15
  • Perfect for any kind of input editing I could thing of. This answer deserves a lot more upvotes! – mvds Feb 04 '22 at 14:44
1

$('#myid').on('paste' , function(e){
   get_content(this);
});

function get_content(gelen){
var value_input = $(gelen).val();
document.getElementById("write-value").innerHTML = value_input;
console.log(value_input);
}
input{ width: calc(100% - 16px); padding:8px; font-size:large}
div{ color:red; margin-top:16px; padding:8px; font-size:large}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input type="text" id="myid" onkeyUP="get_content(this)" >

<div id="write-value">
</div>
Murat Kezli
  • 187
  • 2
  • 5
0

JSfiddle EXAMPLE here

Bigger picture, I think you usually want three events:

  1. When the user pastes
  2. When the user hits <enter>
  3. When the textbox looses focus.

I DON'T want on('input') because that raises an event for every keypress.

This way, you get one event, when the user gets done making input to the text box.

$(document).ready(function () {

            $('#myid').keydown(function (e) {
                var key = e.charCode ? e.charCode : e.keyCode ? e.keyCode : 0;
                if (key == 13) {
                    e.preventDefault();
                    alert($(this).val());
                }
            }).on("change", function () {
                alert($(this).val());
            }).on("paste", function (e) {
                var _this = this;
                // Short pause to wait for paste to complete
                setTimeout(function () {
                    alert($(_this).val());
                }, 100);
            });
        });
mike
  • 2,149
  • 20
  • 29
  • keydown also generates an event for every keypress. So your logic in not using "input" event is broken. input is a better solution and doesnt require the timeout kludge – Danial May 11 '20 at 18:05
  • Hi Danial, I added a JS fiddle to help explain the example. 1). The timeout is not a "Kludge", it is necessary if you want to trap the paste event. 2). Keydown fires for all keypress, but event (alert in this example) only for CR/LF as needed. Please be more gentle with your comments. "kludge" is a strong word, and you did not bother to understand/test my example before slamming it. – mike May 12 '20 at 06:27
  • Timeouts are a workaround for not wanting to bother to do something correctly (like use the clipboard or use the "input" event). It is the definition of Kludge. – Danial May 12 '20 at 16:23
-6

Try this or adding a timeOut too:

   $('#myid').on('paste',function(){
           console.log(this.value);
    });
Miguel
  • 178
  • 1
  • 1