452

I want to detect whenever a textbox's content has changed. I can use the keyup method, but that will also detect keystrokes which do not generate letters, like the arrow keys. I thought of two methods of doing this using the keyup event:

  1. Check explictly if the ascii code of the pressed key is a letter\backspace\delete
  2. Use closures to remember what was the text in the textbox before the key stroke and check whether this has changed.

Both look kinda cumbersome.

Yuck
  • 49,664
  • 13
  • 105
  • 135
olamundo
  • 23,991
  • 34
  • 108
  • 149
  • 7
    Yep, catching keyup for this is bad. You can paste stuff without any keypresses at all. – spender Sep 26 '09 at 13:06
  • 2
    any chance you can post your final solution? I need to solve this problem too :) – Matt Dotson Jun 08 '10 at 00:20
  • 1
    or `.keyup()` event... more info here: http://stackoverflow.com/questions/3003879/which-event-belongs-to-type-text-into-textfield-using-jquery – Victor S Dec 01 '11 at 04:32
  • 1
    See [$("#some-input").changePolling()](https://gist.github.com/2944926); for a wrapper that checks the current value and triggers `.change()` if it has changed. – Joel Purra Jul 25 '12 at 03:00
  • you need to check this too http://stackoverflow.com/a/23266812/3160597 – azerafati Aug 10 '16 at 11:34
  • Possible duplicate of [Detect changed input text box](http://stackoverflow.com/questions/6153047/detect-changed-input-text-box) – azerafati Nov 05 '16 at 09:33

15 Answers15

759

Start observing 'input' event instead of 'change'.

jQuery('#some_text_box').on('input', function() {
    // do your stuff
});

...which is nice and clean, but may be extended further to:

jQuery('#some_text_box').on('input propertychange paste', function() {
    // do your stuff
});
Community
  • 1
  • 1
Atul Vani
  • 7,622
  • 2
  • 14
  • 2
  • 12
    'live' is deprecated. so make use of 'on' http://stackoverflow.com/a/15111970/1724777 – NavaRajan Feb 27 '13 at 12:19
  • 21
    The only downfall of 'input' is that it is not compatible with IE < 9. – Catfish Mar 21 '13 at 20:02
  • 5
    input is html5 event that is not supported in all browsers. https://developer.mozilla.org/en-US/docs/Web/API/window.oninput – commonpike Jun 30 '13 at 20:01
  • 18
    You could also cover more bases by using: .on('input propertychange paste', function() { – Graeck Aug 22 '13 at 20:43
  • Re @Graeck suggestion, just remember that `propertychange` is fired for ANY property that changes on the element, not just the value property. – Jonas Schubert Erlandsson Nov 12 '13 at 13:23
  • 2
    Sadly even `input propertychange paste` doesn't detect *EVERY* change to the textbox: http://jsfiddle.net/obtg2d8f/1/ - "click me" makes a change that doesn't trigger the event. – Roman Starkov May 14 '15 at 14:58
  • 29
    The only downfall of IE < 9 is that nobody uses it! – sohaiby Aug 25 '15 at 14:42
  • @QuantumHive here you go: `textchange` event for cross-browser `input` compatibility http://benalpert.com/2013/06/18/a-near-perfect-oninput-shim-for-ie-8-and-9.html (github: https://github.com/pandell/jquery-splendid-textchange/blob/master/jquery.splendid.textchange.js) – Ber Sep 01 '16 at 23:13
  • 1
    Is there any way i can detect change event when value is set by jquery i.e. $("#id").val('aaa'); (without explicitly invoking/triggering change event)? – Jaimin Dave Apr 21 '17 at 07:58
68

Use the onchange event in HTML/standard JavaScript.

In jQuery that is the change() event. For example:

$('element').change(function() { // do something } );

EDIT

After reading some comments, what about:

$(function() {
    var content = $('#myContent').val();

    $('#myContent').keyup(function() { 
        if ($('#myContent').val() != content) {
            content = $('#myContent').val();
            alert('Content has been changed');
        }
    });
});
Waleed Amjad
  • 6,716
  • 4
  • 35
  • 35
  • 3
    Yes, this is similar to what I suggested in option #2 in my question. I prefer closures since using a global will make this function work only for one textbox. Anyway, it seems weird jquery doesn't have a simpler way of doing this. – olamundo Sep 26 '09 at 13:31
  • 1
    It is indeed weird, but I doubt there is a better way of doing it. You could use setInterval and then check if content has been changed every 0.1 sec and then do something. This will also include mouse pastes and so on. But it doesn't sound too elegant. – Waleed Amjad Sep 26 '09 at 13:33
  • 4
    It's still possible that the content can be changed without a keystroke, for example by pasting with the mouse. If you care about this, you could theoretically catch mouse events too, but that setup is even uglier. On the other hand, if you're willing to ignore mouse-driven changes, this will do. – Adam Bellaire Sep 26 '09 at 13:48
48

The 'change' event doesn't work correctly, but the 'input' is perfect.

$('#your_textbox').bind('input', function() {
    /* This will be fired every time, when textbox's value changes. */
} );
Spudley
  • 166,037
  • 39
  • 233
  • 307
schwarzkopfb
  • 489
  • 4
  • 2
  • 8
    This works perfectly for my situation, although the use of `.on` is recommended from 1.7 onwards (rather than `.bind`). – Nick Jul 10 '12 at 00:38
  • 8
    OP didn't specify a need for cross browser compatibility. @schwarzkopfb provided a solution. No reason to vote down because you have the rep to do so. – David East Jan 20 '13 at 23:08
  • 3
    @David he also didn't specify which browser – ozz Nov 12 '13 at 14:53
  • 10
    @jmo21 I think we can assume for web development when a browser isn't specific the solution should be cross-functional. The norm is supporting all browsers. – Chris Feb 26 '15 at 21:40
  • 6
    @Chris "The norm is supporting all browsers" - only if you're a sadist. There's no good reason to avoid HTML5 goodness for the 2% of global users on IE 8/9. http://caniuse.com/#feat=input-event – Yarin Feb 26 '16 at 20:06
45

How about this:

< jQuery 1.7

$("#input").bind("propertychange change keyup paste input", function(){
    // do stuff;
});

> jQuery 1.7

$("#input").on("propertychange change keyup paste input", function(){
    // do stuff;
});

This works in IE8/IE9, FF, Chrome

Catfish
  • 18,876
  • 54
  • 209
  • 353
  • 1
    The issue I have with this answer is it fires once you blur the textbox, even if the value didn't change. The culprit is "change". – Justin Apr 16 '14 at 21:32
  • Are you using Chrome? Seems it's a bug with chrome and not jQuery's change event http://bugs.jquery.com/ticket/9335 – Catfish Apr 17 '14 at 02:05
  • works but has a minor bug if you do a `console.log` the value of the field it logs twice whenever you key in a character. – Sam B. Sep 19 '19 at 11:11
  • And yet, i am able to find someone else code that not even this solution works. Number field though – Mbotet Mar 31 '21 at 11:15
21

Use closures to remember what was the text in the checkbox before the key stroke and check whether this has changed.

Yep. You don't have to use closures necessarily, but you will need to remember the old value and compare it to the new.

However! This still won't catch every change, because there a ways of editing textbox content that do not involve any keypress. For example selecting a range of text then right-click-cut. Or dragging it. Or dropping text from another app into the textbox. Or changing a word via the browser's spell-check. Or...

So if you must detect every change, you have to poll for it. You could window.setInterval to check the field against its previous value every (say) second. You could also wire onkeyup to the same function so that changes that are caused by keypresses are reflected quicker.

Cumbersome? Yes. But it's that or just do it the normal HTML onchange way and don't try to instant-update.

bobince
  • 528,062
  • 107
  • 651
  • 834
  • 2
    These days the HTML5 `input` event is viable and works in the current versions of all major browsers. – Tim Down Apr 26 '12 at 23:26
14
$(document).on('input','#mytxtBox',function () { 
 console.log($('#mytxtBox').val());
});

You can use 'input' event to detect the content change in the textbox. Don't use 'live' to bind the event as it is deprecated in Jquery-1.7, So make use of 'on'.

NavaRajan
  • 1,850
  • 1
  • 17
  • 22
  • @NavaRajan Just tested it again in IE9. really does not work on backspace. – Flores Jun 06 '13 at 08:41
  • I want to NOT use .live, but the problem I'm having is that I've somehow gone "back to the future" and on a mvc3 project in which the team lead wants to stick with "out of the box" so not only EF 4.0 , but jquery 1.5.1 is being used THUS .on() was not in 1.5.1 , as it was added in jquery version 1.7 http://api.jquery.com/on/ – Tom Stickel Jul 03 '13 at 00:32
5

I assume that you are looking to do something interactive when the textbox changes (i.e. retrieve some data via ajax). I was looking for this same functionality. I know using a global isn't the most robust or elegant solution, but that is what I went with. Here is an example:

var searchValue = $('#Search').val();
$(function () {
    setTimeout(checkSearchChanged, 0.1);
});

function checkSearchChanged() {
    var currentValue = $('#Search').val();
    if ((currentValue) && currentValue != searchValue && currentValue != '') {
        searchValue = $('#Search').val();
        $('#submit').click();
    }
    else {
        setTimeout(checkSearchChanged, 0.1);
    }
}

One key thing to note here is that I am using setTimeout and not setInterval since I don't want to send multiple requests at the same time. This ensures that the timer "stops" when the form is submitted and "starts" when the request is complete. I do this by calling checkSearchChanged when my ajax call completes. Obviously you could expand this to check for minimum length, etc.

In my case, I am using ASP.Net MVC so you can see how to tie this in with MVC Ajax as well in the following post:

http://geekswithblogs.net/DougLampe/archive/2010/12/21/simple-interactive-search-with-jquery-and-asp.net-mvc.aspx

Doug Lampe
  • 1,426
  • 15
  • 8
4

I would recommend taking a look at jQuery UI autocomplete widget. They handled most of the cases there since their code base is more mature than most ones out there.

Below is a link to a demo page so you can verify it works. http://jqueryui.com/demos/autocomplete/#default

You will get the most benefit from reading the source and seeing how they solved it. You can find it here: https://github.com/jquery/jquery-ui/blob/master/ui/jquery.ui.autocomplete.js.

Basically they do it all, they bind to input, keydown, keyup, keypress, focus and blur. Then they have special handling for all sorts of keys like page up, page down, up arrow key and down arrow key. A timer is used before getting the contents of the textbox. When a user types a key that does not correspond to a command (up key, down key and so on) there is a timer that explorers the content after about 300 milliseconds. It looks like this in the code:

// switch statement in the 
switch( event.keyCode ) {
            //...
            case keyCode.ENTER:
            case keyCode.NUMPAD_ENTER:
                // when menu is open and has focus
                if ( this.menu.active ) {
                    // #6055 - Opera still allows the keypress to occur
                    // which causes forms to submit
                    suppressKeyPress = true;
                    event.preventDefault();
                    this.menu.select( event );
                }
                break;
            default:
                suppressKeyPressRepeat = true;
                // search timeout should be triggered before the input value is changed
                this._searchTimeout( event );
                break;
            }
// ...
// ...
_searchTimeout: function( event ) {
    clearTimeout( this.searching );
    this.searching = this._delay(function() { // * essentially a warpper for a setTimeout call *
        // only search if the value has changed
        if ( this.term !== this._value() ) { // * _value is a wrapper to get the value *
            this.selectedItem = null;
            this.search( null, event );
        }
    }, this.options.delay );
},

The reason to use a timer is so that the UI gets a chance to be updated. When Javascript is running the UI cannot be updated, therefore the call to the delay function. This works well for other situations such as keeping focus on the textbox (used by that code).

So you can either use the widget or copy the code into your own widget if you are not using jQuery UI (or in my case developing a custom widget).

Michael Yagudaev
  • 6,049
  • 3
  • 48
  • 53
2

do you consider using change event ?

$("#myTextBox").change(function() { alert("content changed"); });
Canavar
  • 47,715
  • 17
  • 91
  • 122
  • 5
    AFAIK, it is triggered only when the focus of the element is lost. Someone who is familiar with closures probably knows about this one. :) – simon Sep 26 '09 at 13:17
  • yes, this won't do - the change event is called only when the textbox loses focus. I want to handle the change right after the key was pressed. – olamundo Sep 26 '09 at 13:24
2

I'd like to ask why you are trying to detect when the content of the textbox changed in real time?

An alternative would be to set a timer (via setIntval?) and compare last saved value to the current one and then reset a timer. This would guarantee catching ANY change, whether caused by keys, mouse, some other input device you didn't consider, or even JavaScript changing the value (another possiblity nobody mentioned) from a different part of the app.

DVK
  • 126,886
  • 32
  • 213
  • 327
  • my situation (which led me to this question) is that i need to show an 'Update Cart' button when the quantity in a textbox is changed. the user has no idea they need to lose focus and may otherwise not see the button. – Simon_Weaver Nov 07 '09 at 04:47
  • Sorry, I'm not sure that this answers the question of "why not check for diffs on a schedule". Just check often enough (every 1/4th of a second) and the user won't know any difference. – DVK Nov 07 '09 at 14:21
2

Use the textchange event via customized jQuery shim for cross-browser input compatibility. http://benalpert.com/2013/06/18/a-near-perfect-oninput-shim-for-ie-8-and-9.html (most recently forked github: https://github.com/pandell/jquery-splendid-textchange/blob/master/jquery.splendid.textchange.js)

This handles all input tags including <textarea>content</textarea>, which does not always work with change keyup etc. (!) Only jQuery on("input propertychange") handles <textarea> tags consistently, and the above is a shim for all browsers that don't understand input event.

<!DOCTYPE html>
<html>
<head>
<script class="jsbin" src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
<script src="https://raw.githubusercontent.com/pandell/jquery-splendid-textchange/master/jquery.splendid.textchange.js"></script>
<meta charset=utf-8 />
<title>splendid textchange test</title>

<script> // this is all you have to do. using splendid.textchange.js

$('textarea').on("textchange",function(){ 
  yourFunctionHere($(this).val());    });  

</script>
</head>
<body>
  <textarea style="height:3em;width:90%"></textarea>
</body>
</html>

JS Bin test

This also handles paste, delete, and doesn't duplicate effort on keyup.

If not using a shim, use jQuery on("input propertychange") events.

// works with most recent browsers (use this if not using src="...splendid.textchange.js")

$('textarea').on("input propertychange",function(){ 
  yourFunctionHere($(this).val());    
});  
Ber
  • 123
  • 8
0

There's a complete working example here.

<html>
<title>jQuery Summing</title>
<head>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"> </script>
$(document).ready(function() {
$('.calc').on('input', function() {
var t1 = document.getElementById('txt1');
var t2 = document.getElementById('txt2');
var tot=0;
if (parseInt(t1.value))
tot += parseInt(t1.value);
if (parseInt(t2.value))
tot += parseInt(t2.value);
document.getElementById('txt3').value = tot;
});
});
</script>
</head>
<body>
<input type='text' class='calc' id='txt1'>
<input type='text' class='calc' id='txt2'>
<input type='text' id='txt3' readonly>
</body>
</html>
worldofjr
  • 3,868
  • 8
  • 37
  • 49
0

Something like this should work, mainly because focus and focusout would end up with two separate values. I'm using data here because it stores values in the element but doesn't touch the DOM. It is also an easy way to store the value connected to its element. You could just as easily use a higher-scoped variable.

var changed = false;

$('textbox').on('focus', function(e) {
    $(this).data('current-val', $(this).text();
});

$('textbox').on('focusout', function(e) {
    if ($(this).data('current-val') != $(this).text())
        changed = true;
    }
    console.log('Changed Result', changed);
}
smcjones
  • 5,490
  • 1
  • 23
  • 39
0

This Code detects whenever a textbox's content has changed by the user and modified by Javascript code.

var $myText = jQuery("#textbox");

$myText.data("value", $myText.val());

setInterval(function() {
    var data = $myText.data("value"),
    val = $myText.val();

    if (data !== val) {
        console.log("changed");
        $myText.data("value", val);
    }
}, 100);
Rahul Shukla
  • 7,365
  • 3
  • 15
  • 26
0
document.getElementById('txtrate' + rowCount).onchange = function () {            
       // your logic
};

This one works fine but triggers the event on click too which is not good. my system went into loop. while

$('#txtrate'+rowCount).bind('input', function() {
        //your logic
} );

works perfectly in my scenario. it only works when value is changed. instead of $ sign one can use document.getElementById too

Durgesh Kumar
  • 935
  • 10
  • 17