251

I want to capture if any changes happened to <textarea>. Like typing any characters (deleting,backspace) or mouse click and paste or cut. Is there a jQuery event that can trigger for all those events?

I tried change event, but it triggers the callback only after tabbing out from the component.

Use: I want to enable a button if a <textarea> contains any text.

Jason
  • 15,017
  • 23
  • 85
  • 116
Lolly
  • 34,250
  • 42
  • 115
  • 150
  • 18
    Binding to key events is not enough because text can be changed by mouse ("paste"/"cut" from context menu or drag&drop). – Konstantin Smolyanin Mar 18 '13 at 23:41
  • 1
    Similar question is discussed in [Textarea onchange detection](http://stackoverflow.com/questions/2823733/textarea-onchange-detection). – dma_k Aug 04 '14 at 11:51

11 Answers11

365

Try this actually:

$('#textareaID').bind('input propertychange', function() {

      $("#yourBtnID").hide();

      if(this.value.length){
        $("#yourBtnID").show();
      }
});

DEMO

That works for any changes you make, typing, cutting, pasting.

Vladimir Panteleev
  • 24,651
  • 6
  • 70
  • 114
Blaster
  • 9,414
  • 1
  • 29
  • 25
160

bind is deprecated. Use on:

$("#textarea").on('change keyup paste', function() {
    // your code here
});

Note: The code above will fire multiple times, once for each matching trigger-type. To handle that, do something like this:

var oldVal = "";
$("#textarea").on("change keyup paste", function() {
    var currentVal = $(this).val();
    if(currentVal == oldVal) {
        return; //check to prevent multiple simultaneous triggers
    }

    oldVal = currentVal;
    //action to be performed on textarea changed
    alert("changed!");
});

jsFiddle Demo

SNag
  • 17,681
  • 10
  • 54
  • 69
  • 3
    the ```on("change", function() ....``` part is not working for me. Doesn't trigger any alert, nor console logs, anything. For keyup works like a charm, though. – Sebastialonso Jun 04 '14 at 21:31
  • 3
    @Sebastialonso: The `on("change", function() ... ` is **only fired when the textarea loses focus**. Refer my [earlier question](http://stackoverflow.com/questions/17317465/jquery-textbox-change-event-doesnt-fire-until-textbox-loses-focus) for this, and try it out on [this fiddle](http://jsfiddle.net/6bt2g/55/) -- change the textarea, then click outside the textarea, and you should see the change event firing. – SNag Jun 05 '14 at 05:11
  • @SNag that code not working on Chrome 45, but it's working on FF 41 – DariusVE Oct 09 '15 at 14:15
  • If you're stuck using jQuery prior to version 1.7, though, then this does not apply – Code Jockey Apr 05 '16 at 15:10
  • upvoting for use on non deprecated function. Much better than .bind() – Danny Harding Dec 21 '16 at 17:49
  • Event "kye" will trigger everytime enter any character in textarea. My suggestion better to have "change" and "paste" – Suresh Kamrushi Nov 15 '19 at 10:35
  • keyup can be arrows – Lucas Vazquez Jan 17 '20 at 11:48
  • 1
    You might just use `.one("change keyup paste", function ...` instead of `.on`. The `one` eventlistener fires only once. – solitud Jul 28 '20 at 13:36
  • @solitud I tried `.one()` [here](https://jsfiddle.net/54g8yrvj/) but it stops firing after the first character and doesn't fire for every subsequent character change or paste. Can you verify? – SNag Jul 29 '20 at 08:41
  • @SNag That is the intended behaviour. If the text changes it should only fire once e.g. to make the submit button visible via an added css class. Not necessary to apply the CSS class on every consecutive keystroke. You can wrap the event listener in a function so you can call the function again after someone clicked the *submit* button to reactivate the listener for the next single keystroke. – solitud Jul 30 '20 at 09:18
  • it doesn't seem like this handles paste events? thanks for your help. – Crashalot Aug 16 '21 at 00:54
  • @Crashalot Are you sure you included the `paste` verb? `.on("change keyup paste") ...`? – SNag Aug 17 '21 at 14:17
  • "change the textarea, then click outside the textarea, and you should see the change event firing. – SNag Jun 5 '14 at 5:11" Is it possible to avoid this? Is there a way to make it trigger while still inside the textarea? – bieboebap Aug 27 '21 at 09:35
  • @bieboebap: Yes, you can achieve that with `.on("keyup")`. Also experiment with `keydown` and `keypress` to see which one suits your particular usecase best. This [Q&A](https://stackoverflow.com/q/3396754/979621) discusses the differences in the event firing behaviour. – SNag Aug 31 '21 at 13:52
94

Use an input event.

var button = $("#buttonId");
$("#textareaID").on('input',function(e){
  if(e.target.value === ''){
    // Textarea has no value
    button.hide();
  } else {
    // Textarea has a value
    button.show();
  }
});
Jean-François Fabre
  • 137,073
  • 23
  • 153
  • 219
Steel Brain
  • 4,321
  • 28
  • 38
  • For Internet Explorer, this requires 9+, or even 10+ to function properly. – Udi Aug 31 '15 at 03:37
  • 2
    This solution works like a charm. Perfectly overcomes the limitatins of change() and keypress() event handlers. Thanks a ton forks. – Vickar Jun 22 '18 at 21:27
  • This doesn't seem to work for paste events? thanks for your help. – Crashalot Aug 16 '21 at 00:50
  • @Crashalot Actually it works perfectly fine for typing, *pasting**, deleting with both a keyboard and a mouse. Just tested this with the latest (at the time of writing this comment) versions of Chrome, Firefox and Edge. – informatik01 Feb 10 '23 at 12:33
27

This question needed a more up-to-date answer, with sources. This is what actually works (though you don't have to take my word for it):

// Storing this jQuery object outside of the event callback 
// prevents jQuery from having to search the DOM for it again
// every time an event is fired.
var $myButton = $("#buttonID")

// input           :: for all modern browsers [1]
// selectionchange :: for IE9 [2]
// propertychange  :: for <IE9 [3]
$('#textareaID').on('input selectionchange propertychange', function() {

  // This is the correct way to enable/disabled a button in jQuery [4]
  $myButton.prop('disabled', this.value.length === 0)

}

1: https://developer.mozilla.org/en-US/docs/Web/Events/input#Browser_compatibility
2: oninput in IE9 doesn't fire when we hit BACKSPACE / DEL / do CUT
3: https://msdn.microsoft.com/en-us/library/ms536956(v=vs.85).aspx
4: http://api.jquery.com/prop/#prop-propertyName-function

BUT, for a more global solution that you can use throughout your project, I recommend using the textchange jQuery plugin to gain a new, cross-browser compatible textchange event. It was developed by the same person who implemented the equivalent onChange event for Facebook's ReactJS, which they use for nearly their entire website. And I think it's safe to say, if it's a robust enough solution for Facebook, it's probably robust enough for you. :-)

UPDATE: If you happen to need features like drag and drop support in Internet Explorer, you may instead want to check out pandell's more recently updated fork of jquery-splendid-textchange.

Community
  • 1
  • 1
Chris Fritz
  • 1,922
  • 1
  • 19
  • 23
  • Though it seems "selectionchange" works only when applied to the document. Active element could be gotten with "document.activeElement". – tfE Dec 27 '16 at 13:55
14

2018, without JQUERY

The question is with JQuery, it's just FYI.

JS

let textareaID = document.getElementById('textareaID');
let yourBtnID = document.getElementById('yourBtnID');
textareaID.addEventListener('input', function() {
    yourBtnID.style.display = 'none';
    if (textareaID.value.length) {
        yourBtnID.style.display = 'inline-block';
    }
});

HTML

<textarea id="textareaID"></textarea>
<button id="yourBtnID" style="display: none;">click me</div>
rap-2-h
  • 30,204
  • 37
  • 167
  • 263
5

Here's another (modern) but slightly different version than the ones mentioned before. Tested with IE9:

$('#textareaID').on('input change keyup', function () {
  if (this.value.length) {
    // textarea has content
  } else {
    // textarea is empty
  }
});

For outdated browsers you might also add selectionchange and propertychange (as mentioned in other answers). But selectionchange didn't work for me in IE9. That's why I added keyup.

kevinweber
  • 606
  • 9
  • 11
2

try this ...

$("#txtAreaID").bind("keyup", function(event, ui) {                          

              // Write your code here       
 });
stay_hungry
  • 1,448
  • 1
  • 14
  • 21
2

Try to do it with focusout

$("textarea").focusout(function() {
   alert('textarea focusout');
});
llioor
  • 5,804
  • 4
  • 36
  • 44
1

.delegate is the only one that is working to me with jQuery JavaScript Library v2.1.1

 $(document).delegate('#textareaID','change', function() {
          console.log("change!");
    });
eeadev
  • 3,662
  • 8
  • 47
  • 100
0

After some experimentation I came up with this implementation:

$('.detect-change')
    .on('change cut paste', function(e) {
        console.log("Change detected.");
        contentModified = true;
    })
    .keypress(function(e) {
        if (e.which !== 0 && e.altKey == false && e.ctrlKey == false && e.metaKey == false) {
            console.log("Change detected.");
            contentModified = true;
        }
    });

Handles changes to any kind of input and select as well as textareas ignoring arrow keys and things like ctrl, cmd, function keys, etc.

Note: I've only tried this in FF since it's for a FF add-on.

Rooster242
  • 911
  • 3
  • 10
  • 19
-11

Try this

 $('textarea').trigger('change');
 $("textarea").bind('cut paste', function(e) { });
Rajesh Tandukar
  • 403
  • 2
  • 9
  • this is not completely wrong. In fact if one combines `$("#textarea").on('change keyup paste', function() {})` and `$('textarea').trigger('change');` can address the issue that prevents to `paste` to work automatically! – loretoparisi Jan 25 '19 at 09:29