373

When using jquery .change on an input the event will only be fired when the input loses focus

In my case, I need to make a call to the service (check if value is valid) as soon as the input value is changed. How could I accomplish this?

mikemaccana
  • 110,530
  • 99
  • 389
  • 494
Banshee
  • 15,376
  • 38
  • 128
  • 219
  • 3
    what kind of input? textbox? checkbox? radio? textarea? let's see what you've come up with so far – Patricia Jun 23 '11 at 18:27
  • Sorry, its a input of type text. And as I said, I have tried change but this does not fire the way I need(for every change on the text in the input). I have also tried keydown but to get this working I will have to keep track off if the input is "dirty" or not. – Banshee Jun 23 '11 at 18:34
  • 2
    if they are pressing a key, it's going to change 99% of the time, you could always do a check for the keys that wouldn't in the event handler. – Patricia Jun 23 '11 at 18:38

8 Answers8

566

UPDATED for clarification and example

examples: http://jsfiddle.net/pxfunc/5kpeJ/

Method 1. input event

In modern browsers use the input event. This event will fire when the user is typing into a text field, pasting, undoing, basically anytime the value changed from one value to another.

In jQuery do that like this

$('#someInput').bind('input', function() { 
    $(this).val() // get the current value of the input field.
});

starting with jQuery 1.7, replace bind with on:

$('#someInput').on('input', function() { 
    $(this).val() // get the current value of the input field.
});

Method 2. keyup event

For older browsers use the keyup event (this will fire once a key on the keyboard has been released, this event can give a sort of false positive because when "w" is released the input value is changed and the keyup event fires, but also when the "shift" key is released the keyup event fires but no change has been made to the input.). Also this method doesn't fire if the user right-clicks and pastes from the context menu:

$('#someInput').keyup(function() {
    $(this).val() // get the current value of the input field.
});

Method 3. Timer (setInterval or setTimeout)

To get around the limitations of keyup you can set a timer to periodically check the value of the input to determine a change in value. You can use setInterval or setTimeout to do this timer check. See the marked answer on this SO question: jQuery textbox change event or see the fiddle for a working example using focus and blur events to start and stop the timer for a specific input field

Community
  • 1
  • 1
MikeM
  • 27,227
  • 4
  • 64
  • 80
  • Could you explain more about this solution? How do I get the current value? An how do I get this to only run when changes is made to the current value? – Banshee Jun 27 '11 at 13:51
  • input event? there is no input event in jQuery (yet)...http://stackoverflow.com/q/11189136/104380 – vsync Feb 24 '13 at 18:52
  • For method 2 I usually bind to both keyup *and* change. That way in situations where input occurs without a keypress (like pasting) it will at least fire the event when the input loses focus. – rspeed Apr 18 '13 at 08:37
  • Docs for "input" event: http://www.whatwg.org/specs/web-apps/current-work/multipage/common-input-element-attributes.html#event-input-input – jackocnr Oct 14 '13 at 23:28
  • IE10/11 also react to 'input' if a placeholder is set. If you're expecting to judge the value of the input (eg, if val) it will break in IE10 and 11. No fix found yet. Example - http://jsfiddle.net/7Lbt8/2/ – Carson Dec 20 '13 at 18:05
  • found this http://jsfiddle.net/pxfunc/5kpeJ/ useful, like tutorial for those three methods – nickeyzzz Mar 14 '14 at 16:34
  • You can subscribe to keyup and change event at the same time. $("#txtZipCode").bind("keyup change", function (e) { showLocation($(this).val()); }); – Francisco Goldenstein Jun 04 '14 at 18:52
  • You should add 4th options, Using MutationObserver (better performance then timer) you can listen to the 'value' attribute change – Adi Darachi Jul 26 '16 at 09:45
  • 1
    @AdiDarachi MutationObserver will track changes to DOM elements. However, a user changing data in an input field does not trigger a MutationObserver change...I setup a test case, only a JS code change to the `innerText` or `value` attribute (simulating user input) will trigger a MutationObserver event https://jsfiddle.net/pxfunc/04chgpws/1/ (see the console.log for MutationObserver event logging). Do you have a different test case I can look at? – MikeM Jul 27 '16 at 18:11
  • my assumption was wrong, after further investigation Mutation will trigger in the following situations. 1. JS code change the value of the input (as you mentioned) 2. on blur event from the input after value change. And DOSE NOT ANSWER THIS QUESTION. – Adi Darachi Jul 28 '16 at 07:20
  • Very nice, unfortunately in Drupal the input is disabled after first keyup or on input events. – Robert-Dan Aug 01 '16 at 18:51
  • @MikeM will the first technique work if the input is from a non-keyboard entity like a barcode scanner? – seriousgeek Sep 30 '16 at 14:55
  • FYI: These events will fire with a blank value if the keyboard is used to select a date that is not valid. ie. Feb 30. https://stackoverflow.com/questions/48564568/html5-input-type-date-input-event-incorrectly-fires-with-empty-value/48564701#48564701 – Olmstov Feb 01 '18 at 14:18
192

If you've got HTML5:

  • oninput (fires only when a change actually happens, but does so immediately)

Otherwise you need to check for all these events which might indicate a change to the input element's value:

  • onchange
  • onkeyup (not keydown or keypress as the input's value won't have the new keystroke in it yet)
  • onpaste (when supported)

and maybe:

  • onmouseup (I'm not sure about this one)
Alnitak
  • 334,560
  • 70
  • 407
  • 495
  • @naomik from my test it works for checkbox inputs; except IE/Edge. Some other exceptions may appear, but it's smarter to use onchange for those input types(IMHO). – HellBaby Mar 07 '17 at 14:48
89

With HTML5 and without using jQuery, you can using the input event:

var input = document.querySelector('input');

input.addEventListener('input', function()
{
    console.log('input changed to: ', input.value);
});

This will fire each time the input's text changes.

Supported in IE9+ and other browsers.

Try it live in a jsFiddle here.

Drew Noakes
  • 300,895
  • 165
  • 679
  • 742
  • 1
    Additional, [IE 9 does not fire an input event when the user deletes characters from an input (e.g. by pressing Backspace or Delete, or using the "Cut" operation)](http://caniuse.com/#feat=input-event). – xcatliu May 26 '16 at 05:15
  • 1
    'change' only fires on blur, not when the text changes. Use 'input' event to detect text changes. – Dermot Doherty Jan 27 '17 at 03:13
15

As others already suggested, the solution in your case is to sniff multiple events.
Plugins doing this job often listen for the following events:

$input.on('change keydown keypress keyup mousedown click mouseup', handler);

If you think it may fit, you can add focus, blur and other events too.
I suggest not to exceed in the events to listen, as it loads in the browser memory further procedures to execute according to the user's behaviour.

Attention: note that changing the value of an input element with JavaScript (e.g. through the jQuery .val() method) won't fire any of the events above.
(Reference: https://api.jquery.com/change/).

kvanbere
  • 3,289
  • 3
  • 27
  • 52
yodabar
  • 4,651
  • 2
  • 33
  • 38
  • i also recommend to add focusout to avoid problems with autocomplete – binar Jan 05 '16 at 11:29
  • I see. I searched, and focusout seems to be supported only by IE and partially by Chrome, am I right? – yodabar Jan 11 '16 at 00:23
  • 6
    Just as a mild addition, To fire the event from jQuery you can call the corresponding action after `.val()` e.g for a change event on an input field, you would do something like this... `$('#element').val(whatever).change()` – SourceVisor Sep 22 '16 at 04:15
3

// .blur is triggered when element loses focus

$('#target').blur(function() {
  alert($(this).val());
});

// To trigger manually use:

$('#target').blur();
Rubens
  • 14,478
  • 11
  • 63
  • 92
Kszili
  • 334
  • 3
  • 16
  • 1
    .change is as I said only thrown when the inout loses focus and the value is changed, I need to get a even as soon as the input(text) is changed (as soon as the text in the input is changed). Blur will only trigger when the input loses focus. – Banshee Jun 23 '11 at 18:33
2

If you want the event to be fired whenever something is changed within the element then you could use the keyup event.

Jivings
  • 22,834
  • 6
  • 60
  • 101
  • Okay but is this not more or less the same as the keydown? I will have to check if the input is "dirty" myself? – Banshee Jun 23 '11 at 18:37
  • @SnowJim if you only want to do stuff when the input actually changes, you've got to either use `onchange`, or track the state yourself. `keydown` doesn't work because it fires _before_ the input's state gets changed. – Alnitak Jun 23 '11 at 18:47
  • @Alnitak exacly and thats why I asking the question here. The onchange is not working, is it only thrown when leaving the input. – Banshee Jun 23 '11 at 20:13
  • The elephant in the room of course is mobile. Pretty sure no keyboard or mouse events are going be of much use there. :p – Askdesigners Jun 29 '14 at 11:29
  • @Askdesigners Keyup/down events should still work in the same fashion on mobile. – Jivings Jun 30 '14 at 07:36
1

There are jQuery events like keyup and keypress which you can use with input HTML Elements. You could additionally use the blur() event.

  • 1
    .change is as I said only thrown when the inout loses focus and the value is changed, I need to get a even as soon as the input(text) is changed (as soon as the text in the input is changed). Blur will only trigger when the input loses focus. – Banshee Jun 23 '11 at 18:33
  • 1
    you can't reliably check an input's value during a `keypress` event because the pressed key won't have changed that value yet. – Alnitak Jun 23 '11 at 18:40
0

This covers every change to an input using jQuery 1.7 and above:

$(".inputElement").on("input", null, null, callbackFunction);
rybo111
  • 12,240
  • 4
  • 61
  • 70