The change event does not fire when the keydown event (TAB key) changes the value of an element
This HTML code:
<input type="text" id="test" /> and JavaScript:
var $test = $('#test'); $test.on('keydown', function(event) { if (event.keyCode === 9) { $(event.target).val('change it!'); } }); $test.on('change', function(event) { alert('I am not called!'); }); if I type something at the input and press tab , why does the change event not fire? The keydown event fires and updates the input value.
If I remove the .val() call, then change fires.
At first I thought it was a jQuery problem (works with version 1.9.1), but confirmed that the same behavior happens if I use simple JavaScript.
change only works for changes made by the user. In other words, using JavaScript to change the value of an element in the background does not trigger change .
The tab does not actually change the contents of the element; he just switches focus. The coincidence, in a sense, of printing a tab to change the contents of an element (you can also click a button to update it indirectly, which also did not work change ).
The DOM specification explains why in your particular case, when you enter and enter, user input is discarded and no changes are made.
In particular:
Keyboard events defined in this specification occur in a specified order with respect to each other, for any given key:
- keydown
- keypress (only for keys that create a character value)
- Any default actions associated with this key.
- Keyup
When you press the tab key, keydown starts. Boom, your event handler is called! The content of the element is updated using the script - no change, because the script does it. User content is destroyed. Now it's time for the browser to perform the default actions associated with the tab: divert attention and see if the item has been changed by the user (to start onchange). No, it has been modified by the script! No change for shooting.
Thus, if you delete the line val() , you will notice two things.
- If you give the focus of an element and turn it off, then
changeis not performed - no changes have occurred since the tab does not change the contents of the field. - If you give focus to an element and type something and remove,
changetriggered, because during these default magic tab-related actions, the browser notices that the user has made changes.
Phew!
I never understood why (as other responders did), but I found a solution for you since you are already using jQuery. Just fire the change event yourself using its jQuery method instead of val ():
var test = $('#test'); test.on('keydown', function(event) { if (event.keyCode == 9) { $(event.target).change(function(){ this.value = 'change it!'; }); } }); test.on('change', function(event) { alert('I am not called!'); }); See fiddle .
You change the value before the keyup in the tab. In keyup a change event will be keyup . But since you changed the value during the keydown handler, by the time it loses focus, the value goes back to what it was before.
To see this, change your jquery from keydown to keyup and you will see that the event is triggered (and you will also see that there is a fire AND THEN keyup starts and changes the text back).