-
Notifications
You must be signed in to change notification settings - Fork 27.4k
fix(inputs): improve "input" event emulation for legacy browsers #9623
Conversation
I'm sorry, but I wasn't able to verify your Contributor License Agreement (CLA) signature. CLA signature is required for any code contributions to AngularJS. Please sign our CLA and ensure that the CLA signature email address and the email address in this PR's commits match. If you signed the CLA as a corporation, please let us know the company's name. Thanks a bunch! PS: If you signed the CLA in the past then most likely the email addresses don't match. Please sign the CLA again or update the email address in the commit of this PR. |
@mary-poppins I completed the CLA form today before I submitted this PR. As far as I can tell, there are two email addresses on the agreement. [redacted]. The latter address is the one I use for github. Please let me know if you need anything else. |
@cvn mary-poppins is a robot that periodically updates these things. If you signed with the second email listed, you should be good here |
Thanks, @caitp. I figured it was a bot, but wanted to be polite, just in case. |
CLA signature verified! Thank you! Someone from the team will now triage your PR and it will be processed based on the determined priority (doc updates and fixes with tests are prioritized over other changes). |
4dd5a20
to
998c61c
Compare
@cvn do you have an easier demo of the issue (without the placeholder stuff etc.), maybe on http://plnkr.co or http://jsfiddle.net/? |
@jbedard Thanks for taking a look. This issue is directly related to #1206, so I'm going to post the fiddle from there instead of simplifying mine: http://jsfiddle.net/symblify/XL6RX/1/ In that fiddle, running in IE8/9, pressing tab while focused on a field will set it $dirty unnecessarily. This bug and my bug have the same cause: the tab key triggers a call to The first commit I submitted only addressed the symptoms of my bug, but I've pushed changes that address the key handling instead. This solves it closer to the source. The code is based on work by @jbdutton, @symblify, and @montgomery1944 in the #1206 thread. Let me know what you think. |
var divElm = document.createElement('div'); | ||
eventSupport[event] = 'on' + event in divElm; | ||
var elm = document.createElement('input'); | ||
eventSupport[event] = 'on' + event in elm; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Was there a case where this change was required?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@jbedard This allows Opera versions with the Presto engine to use the real "input" event instead of the emulation. Opera Desktop and Mobile up through versions 12 and all versions of Opera Mini only have the input event on form elements (inputs, textareas, and selects). I learned about this from a tip by @montgomery1944 in the #1206 thread.
Here's a test result from Opera 12.16 mac that confirms this: http://i.imgur.com/Carhv3n.png. Opera's support for the input event is pretty good, in my testing. The only flaws I found are that it will fire an input event when pressing the "enter" key in a single-line field.
EDIT: I didn't consider divs with the contenteditable attribute until now. These are supported in Presto, but without the input event. See table here. In other words, Opera's support for the input event is incomplete and we shouldn't rely on it. Forget about this change.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think old Presto versions of opera are too old and unsupported anyway...
I think I'd like to do this once we can write proper integration tests in #9697. But overall I'd prefer not adding more listeners and keycode combinations. I think I have a way of doing that but I'd really like a better way to test it... |
Landed #9265, which is supposed to fix this problem too. |
If it involves listening for a zillion different event types, it's a non-starter. We aren't merging that. |
#9265 fixed a few issues I found based on this discussion but I think there's at least one still broken. If you tab out of an input without making a change, but some other code then modifies the value, then it will think the modification was caused by the tab key. Is that the issue still remaining @cvn? But that one requires more event listeners... |
@jbedard That issue with the tab key you've described is still present after #9265. That PR also adds the issue I discussed above where highlighting an m and typing m does not result in a listener() call. I consider this significant because the same action in a browser with the input event will cause a listener() call. I've pushed a commit that I believe will improve the emulation and reduce edge cases. It fixes both of the problems I just mentioned. cvn@b43c14d It does add a keypress event, but I think it's the best way, since it helps us filter down the keys that trigger listener() without having to add a ton of keys (tab, caps lock, etc) to the keydown check. #9265's technique is another way to solve this, but it introduced the "m" issue, which my new commit resolves. @jbedard @caitp Let me know what you think. I've done a lot of testing, and can offer some reasons for my decisions if you're curious about anything. And sorry about the deleted comment a few hours ago, I spoke too soon. :) |
@cvn so that's where your comment went :P (EDIT: and now it moved!) For the highlighting |
@jbedard The listener() function currently uses A specific edge case I can think of is that if your input's model is set to "m ", and the user highlights m and types m, in modern browsers the input will update to "m" and in IE, with the current fix in 9265, it will stay at "m ". You can verify that modern browsers will trim the space here http://jsbin.com/pokod/2/edit. And it's plausible that more logic could be added to the listener() in the future. I think the more accurate the emulation, the less edge cases are possible, and the cost of the additional listener here is worth it. |
The trim case is a good example. I still think the situation is much better then before (and IE is more consistent :). If we can fix more issues without adding more listeners that would be great, but imo these remaining two issues might not be worth it... |
If you don't think the additional listener is worthwhile, then I think at least we should add tab to the list of filtered keys in the keydown handler. This will resolve the tab key issue and leave the "m" issue as the only one that I'm aware of. I've added a commit with just this change: https://github.com/cvn/angular.js/commit/117c92e03c973ea090dddb2996464b6349015fbb |
I think https://github.com/cvn/angular.js/commit/117c92e03c973ea090dddb2996464b6349015fbb would be good actually. Unless I'm forgetting something. If the tab key ever causes a change it should also cause a blur + change event and the change event will capture it, right? Maybe just add a unit test that demonstrates that as well? |
Regarding the |
You are correct, that if tab key causes input, like with autofill, it will also cause change + blur events. I just tested this in IE11. I wouldn't mind adding a unit test, but there's no way to trigger a specific key in unit tests as far as I'm aware. The closest approximation to IE's autofill behavior is something like As for the |
I think you're right about the tests. I don't see any way to trigger a keydown event with the tabKey. Maybe you can just add support for a Regarding the |
Hello,
In IE versions that use the keydown handler to check for changes to an input, there is a bug when pressing the tab key that will update the input after the change and blur events.
This PR fixes this behavior
by cancelling the keydown handler, and updating immediately on change/blur.See a demo of the bug here (only affects IE8/IE9): http://codepen.io/cvn/full/lvjJr/
Here is a fixed demo with the changes from this PR applied to angular.js: http://codepen.io/cvn/full/cgLns/
Currently, this bug only impacts IE8 & 9, but if PR #9265 lands, it will affect all versions of IE.
Issue #1206 may be related, but I'm not sure about this.
I'm submitting this PR to master, but I think it makes sense to include in both 1.2 and 1.3 branches.
Please let me know what you think.