Add new textChange event: input + IE shim #75
Conversation
IE8 doesn't support oninput and IE9 supports it badly but we can do almost a perfect shim by listening to a handful of different events (focus, blur, propertychange, selectionchange, keyup, keydown). This always triggers event handlers during the browser's event loop (not later in a setTimeout) and after the value property has been updated. The only case I know of where this doesn't fire the event immediately is if (in IE8) you modify the input value using JS and then the user does a key repeat, in which case we fire the event on the second keydown. Test Plan: Modify ballmer-peak example to add es5-shim and to use onTextChange instead of onInput. In IE8, IE9, and latest Chrome, make sure that the event is fired upon: * typing normally, * backspacing, * forward-deleting, * cutting, * pasting, * context-menu deleting, * dragging text to reorder characters. After modifying the example to change .value, make sure that the event is not fired as a result of the changes from JS (even when the input box is focused).
cc @yungsters |
|
||
// IE9 claims to support the input event but fails to trigger it when deleting | ||
// text, so we ignore its input events | ||
var isInputSupported = isEventSupported('input') && ( |
petehunt
Jun 10, 2013
Contributor
Please use ExecutionEnvironment.canUseDOM such that this module could be required and not fatal if there is no document symbol in scope. I'm not sure if it'll get required in practice or not, but a good idea nonetheless.
Please use ExecutionEnvironment.canUseDOM such that this module could be required and not fatal if there is no document symbol in scope. I'm not sure if it'll get required in practice or not, but a good idea nonetheless.
sophiebits
Jun 11, 2013
Author
Collaborator
Done. (I had canUseDOM originally but lost it somewhere along the way.)
Done. (I had canUseDOM originally but lost it somewhere along the way.)
var isInputSupported; | ||
if (ExecutionEnvironment.canUseDOM) { | ||
isInputSupported = isEventSupported('input') && ( | ||
!("documentMode" in document) || document.documentMode > 9 |
yungsters
Jun 12, 2013
Contributor
This check looks good to me.
This check looks good to me.
Yes, keep passing it along. It's up to the end user to do what they will with it, but I have a new set of "synthetic events" that will allow us to normalize the API for both DOM and custom events like the one you're adding. |
nativeEvent | ||
); | ||
EventPropagators.accumulateTwoPhaseDispatches(abstractEvent); | ||
EventPluginHub.enqueueAbstractEvents(abstractEvent); |
yungsters
Jun 12, 2013
Contributor
Add a comment about how propertychange
does not bubble so we cannot listen to this using top-level event delegation and have to enqueue and process manually. (By the way, @jordow, can you explain why we need two steps for enqueuing and processing instead of one?)
Add a comment about how propertychange
does not bubble so we cannot listen to this using top-level event delegation and have to enqueue and process manually. (By the way, @jordow, can you explain why we need two steps for enqueuing and processing instead of one?)
); | ||
|
||
Object.defineProperty(topLevelTarget, 'value', newValueProp); | ||
topLevelTarget.attachEvent('onpropertychange', handlePropertyChange); |
yungsters
Jun 12, 2013
Contributor
Change topLevelTarget.attachEvent
to activeElement.attachEvent
so it's easier for readers to find the detachEvent
call below.
Change topLevelTarget.attachEvent
to activeElement.attachEvent
so it's easier for readers to find the detachEvent
call below.
// changed from JS so we redefine a setter for `.value` that updates our | ||
// activeElementValue variable, allowing us to ignore those changes | ||
if (hasInputCapabilities(topLevelTarget)) { | ||
activeElement = topLevelTarget; |
yungsters
Jun 12, 2013
Contributor
I've always had the impression that focus and blur events are flakey (e.g. if the OS steals focus from the browser, etc.). Is it ever possible for the blur event to not get fired before another focus? If activeElement
, maybe we should do the cleanup below.
I've always had the impression that focus and blur events are flakey (e.g. if the OS steals focus from the browser, etc.). Is it ever possible for the blur event to not get fired before another focus? If activeElement
, maybe we should do the cleanup below.
|
||
} else { | ||
return; | ||
} |
yungsters
Jun 12, 2013
Contributor
The conditionals are correct, but a little hard to follow. Do you think this would be any better?
if (isInputSupported) {
if (topLevelType !== topLevelTypes.topInput) {
return;
}
// ...
} else {
if (topLevelType === topLevelTypes.topFocus) {
// ...
return;
}
if (topLevelType === topLevelTypes.topBlur) {
// ...
return;
}
if (topLevelType !== topLevelTypes.topSelectionChange &&
topLevelType !== topLevelTypes.topKeyUp &&
topLevelType !== topLevelTypes.topKeyDown) {
return;
}
// ...
}
Or better yet...
var extractEvents;
if (isInputSupported) {
extractEvents = function() {
// Modern browsers...
};
} else {
extractEvents = function() {
// IE<10...
};
}
The conditionals are correct, but a little hard to follow. Do you think this would be any better?
if (isInputSupported) {
if (topLevelType !== topLevelTypes.topInput) {
return;
}
// ...
} else {
if (topLevelType === topLevelTypes.topFocus) {
// ...
return;
}
if (topLevelType === topLevelTypes.topBlur) {
// ...
return;
}
if (topLevelType !== topLevelTypes.topSelectionChange &&
topLevelType !== topLevelTypes.topKeyUp &&
topLevelType !== topLevelTypes.topKeyDown) {
return;
}
// ...
}
Or better yet...
var extractEvents;
if (isInputSupported) {
extractEvents = function() {
// Modern browsers...
};
} else {
extractEvents = function() {
// IE<10...
};
}
Add new textChange event: input + IE shim
…orm elements Upgrade `TextChangeEventPlugin` to be the `onChange` event that React fires. In React, `onChange` will now fire when `input` fires for form elements in modern browsers. Handle this for: input[type=text] input[type=password] input[type=checkbox] input[type=radio] textarea select Support: - OSX Chrome - OSX Safari - OSX Firefox - Win 7 / IE8 - Win 7 / IE9 - Win 7 / IE10 Everything works but caret selection / placement differs from browser to browser. For <select> elements, the event is fired with `change`. This is a conscious decision, even though in some browsers (OSX firefox, IE), it can be argued that the event should fire more due to how the UI looks. Builds on facebook/react#75, which handled only text inputs.
Fix double-adding fibers when traversing
… frame type Lays groundwork for #75 by reducing the flamechart data passed around the app. Was also intended to help #50 by moving some division operations from the hot render loops into preprocessFlamechart, but any performance gains are negligible. * `yarn flow`: no errors in modified code * `yarn lint` * `yarn start`: no performance difference
… frame type Lays groundwork for #75 by reducing the flamechart data passed around the app. Was also intended to help #50 by moving some division operations from the hot render loops into preprocessFlamechart, but any performance gains are negligible. * `yarn flow`: no errors in modified code * `yarn lint` * `yarn start`: no performance difference
IE8 doesn't support oninput and IE9 supports it badly but we can do almost a perfect shim by listening to a handful of different events (focus, blur, propertychange, selectionchange, keyup, keydown).
This always triggers event handlers during the browser's event loop (not later in a setTimeout) and after the value property has been updated.
The only case I know of where this doesn't fire the event immediately is if (in IE8) you modify the input value using JS and then the user does a key repeat, in which case we fire the event on the second keydown.
Test Plan:
Modify ballmer-peak example to add es5-shim and to use onTextChange instead of onInput. In IE8, IE9, and latest Chrome, make sure that the event is fired upon:
After modifying the example to change .value, make sure that the event is not fired as a result of the changes from JS (even when the input box is focused).
Questions: