mirror of
https://github.com/facebook/react.git
synced 2025-11-01 09:12:30 +00:00
Repair spacebar textInput
Browsers that natively support the `textInput` event appear to have a bug: when preventing default behavior for a `textInput` event occurring for a spacebar keypress, the character is prevented from being inserted **but the browser scrolls down**. Minimal repro example: http://jsfiddle.net/salier/bX4fw/ This is ridiculous, since scrolling makes no sense when the user is focused in a textinput or contenteditable. Preventing default at the `textInput` stage should mean to prevent the character from being inserted, and should have no impact at all on scrolling behavior. I have filed this as a Chromium bug (https://code.google.com/p/chromium/issues/detail?id=355103) but I'm not going to hold out much hope that they'll fix it. To resolve this, I'm special-casing the spacebar character at the plugin level, in `BeforeInputEventPlugin`. I looked for ways to do this at the component level, but it seems to me that this is simply a browser bug and it's cleaner to handle it there. In browsers that can use the native `textInput` event, I'm checking the code of the pressed key. If it's the spacebar, we dispatch the synthetic event as if there were no native `textInput` event -- as if we were running Firefox. Then, if the synthetic event is not canceled and we make it through to the native `textInput` event, bail if the character data is a space character.
This commit is contained in:
committed by
Paul O’Shannessy
parent
09333a3819
commit
5476f9168b
@@ -26,12 +26,15 @@ var SyntheticInputEvent = require('SyntheticInputEvent');
|
||||
|
||||
var keyOf = require('keyOf');
|
||||
|
||||
var useBeforeInputEvent = (
|
||||
var canUseTextInputEvent = (
|
||||
ExecutionEnvironment.canUseDOM &&
|
||||
'TextEvent' in window &&
|
||||
!('documentMode' in document)
|
||||
);
|
||||
|
||||
var SPACEBAR_CODE = 32;
|
||||
var SPACEBAR_CHAR = String.fromCharCode(SPACEBAR_CODE);
|
||||
|
||||
var topLevelTypes = EventConstants.topLevelTypes;
|
||||
|
||||
// Events and their corresponding property names.
|
||||
@@ -100,13 +103,48 @@ var BeforeInputEventPlugin = {
|
||||
|
||||
var chars;
|
||||
|
||||
if (useBeforeInputEvent) {
|
||||
// For browsers that support `textInput` events natively, don't do
|
||||
// anything with keypress, composition, etc.
|
||||
if (topLevelType !== topLevelTypes.topTextInput) {
|
||||
return;
|
||||
if (canUseTextInputEvent) {
|
||||
switch (topLevelType) {
|
||||
case topLevelTypes.topKeyPress:
|
||||
/**
|
||||
* If native `textInput` events are available, our goal is to make
|
||||
* use of them. However, there is a special case: the spacebar key.
|
||||
* In Webkit, preventing default on a spacebar `textInput` event
|
||||
* cancels character insertion, but it *also* causes the browser
|
||||
* to fall back to its default spacebar behavior of scrolling the
|
||||
* page.
|
||||
*
|
||||
* Tracking at:
|
||||
* https://code.google.com/p/chromium/issues/detail?id=355103
|
||||
*
|
||||
* To avoid this issue, use the keypress event as if no `textInput`
|
||||
* event is available.
|
||||
*/
|
||||
var which = nativeEvent.which;
|
||||
if (which !== SPACEBAR_CODE) {
|
||||
return;
|
||||
}
|
||||
|
||||
chars = String.fromCharCode(which);
|
||||
break;
|
||||
|
||||
case topLevelTypes.topTextInput:
|
||||
// Record the characters to be added to the DOM.
|
||||
chars = nativeEvent.data;
|
||||
|
||||
// If it's a spacebar character, assume that we have already handled
|
||||
// it at the keypress level and bail immediately.
|
||||
if (chars === SPACEBAR_CHAR) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Otherwise, carry on.
|
||||
break;
|
||||
|
||||
default:
|
||||
// For other native event types, do nothing.
|
||||
return;
|
||||
}
|
||||
chars = nativeEvent.data;
|
||||
} else {
|
||||
switch (topLevelType) {
|
||||
case topLevelTypes.topPaste:
|
||||
|
||||
Reference in New Issue
Block a user