Improve normalization of charCode, fix FF not reporting Enter
Andreas Svensson committed
Jul 30, 2014 at 00:34 UTC
b83076468da57e2fcaf18f2f21c20bc34a0aa077
4 files changed
+78
-18
src/browser/eventPlugins/SimpleEventPlugin.js
+5
-2
@@ -31,6 +31,8 @@ var SyntheticTouchEvent = require('SyntheticTouchEvent');
31
var SyntheticUIEvent = require('SyntheticUIEvent');
32
var SyntheticWheelEvent = require('SyntheticWheelEvent');
33
34
+var getEventCharCode = require('getEventCharCode');
35
+
36
var invariant = require('invariant');
37
var keyOf = require('keyOf');
38
@@ -343,8 +345,9 @@ var SimpleEventPlugin = {
345
break;
346
case topLevelTypes.topKeyPress:
347
// FireFox creates a keypress event for function keys too. This removes
346
- // the unwanted keypress events.
347
- if (nativeEvent.charCode === 0) {
348
+ // the unwanted keypress events. Enter is however both printable and
349
+ // non-printable. One would expect Tab to be as well (but it isn't).
350
+ if (getEventCharCode(nativeEvent) === 0) {
351
return null;
352
}
353
/* falls through */
src/browser/syntheticEvents/SyntheticKeyboardEvent.js
+12
-7
@@ -21,6 +21,7 @@
21
22
var SyntheticUIEvent = require('SyntheticUIEvent');
23
24
+var getEventCharCode = require('getEventCharCode');
25
var getEventKey = require('getEventKey');
26
var getEventModifierState = require('getEventModifierState');
27
@@ -43,11 +44,10 @@ var KeyboardEventInterface = {
44
// `charCode` is the result of a KeyPress event and represents the value of
45
// the actual printable character.
46
46
- // KeyPress is deprecated but its replacement is not yet final and not
47
- // implemented in any major browser.
47
+ // KeyPress is deprecated, but its replacement is not yet final and not
48
+ // implemented in any major browser. Only KeyPress has charCode.
49
if (event.type === 'keypress') {
49
- // IE8 does not implement "charCode", but "keyCode" has the correct value.
50
- return 'charCode' in event ? event.charCode : event.keyCode;
50
+ return getEventCharCode(event);
51
}
52
return 0;
53
},
@@ -66,9 +66,14 @@ var KeyboardEventInterface = {
66
},
67
which: function(event) {
68
// `which` is an alias for either `keyCode` or `charCode` depending on the
69
- // type of the event. There is no need to determine the type of the event
70
- // as `keyCode` and `charCode` are either aliased or default to zero.
71
- return event.keyCode || event.charCode;
69
+ // type of the event.
70
+ if (event.type === 'keypress') {
71
+ return getEventCharCode(event);
72
+ }
73
+ if (event.type === 'keydown' || event.type === 'keyup') {
74
+ return event.keyCode;
75
+ }
76
+ return 0;
77
}
78
};
79
src/browser/ui/dom/getEventCharCode.js
new
+57
@@ -0,0 +1,57 @@
1
+/**
2
+ * Copyright 2013-2014 Facebook, Inc.
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ *
16
+ * @providesModule getEventCharCode
17
+ * @typechecks static-only
18
+ */
19
+
20
+"use strict";
21
+
22
+/**
23
+ * `charCode` represents the actual "character code" and is safe to use with
24
+ * `String.fromCharCode`. As such, only keys that correspond to printable
25
+ * characters produce a valid `charCode`, the only exception to this is Enter.
26
+ * The Tab-key is considered non-printable and does not have a `charCode`,
27
+ * presumably because it does not produce a tab-character in browsers.
28
+ *
29
+ * @param {object} nativeEvent Native browser event.
30
+ * @return {string} Normalized `charCode` property.
31
+ */
32
+function getEventCharCode(nativeEvent) {
33
+ var charCode;
34
+ var keyCode = nativeEvent.keyCode;
35
+
36
+ if ('charCode' in nativeEvent) {
37
+ charCode = nativeEvent.charCode;
38
+
39
+ // FF does not set `charCode` for the Enter-key, check against `keyCode`.
40
+ if (charCode === 0 && keyCode === 13) {
41
+ charCode = 13;
42
+ }
43
+ } else {
44
+ // IE8 does not implement `charCode`, but `keyCode` has the correct value.
45
+ charCode = keyCode;
46
+ }
47
+
48
+ // Some non-printable keys are reported in `charCode`/`keyCode`, discard them.
49
+ // Must not discard the (non-)printable Enter-key.
50
+ if (charCode >= 32 || charCode === 13) {
51
+ return charCode;
52
+ }
53
+
54
+ return 0;
55
+}
56
+
57
+module.exports = getEventCharCode;
src/browser/ui/dom/getEventKey.js
+4
-9
@@ -19,7 +19,7 @@
19
20
"use strict";
21
22
-var invariant = require('invariant');
22
+var getEventCharCode = require('getEventCharCode');
23
24
/**
25
* Normalization of deprecated HTML5 `key` values
@@ -41,7 +41,7 @@ var normalizeKey = {
41
};
42
43
/**
44
- * Translation from legacy `which`/`keyCode` to HTML5 `key`
44
+ * Translation from legacy `keyCode` to HTML5 `key`
45
* Only special keys supported, all others depend on keyboard layout or browser
46
* @see https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent#Key_names
47
*/
@@ -93,11 +93,7 @@ function getEventKey(nativeEvent) {
93
94
// Browser does not implement `key`, polyfill as much of it as we can.
95
if (nativeEvent.type === 'keypress') {
96
- // Create the character from the `charCode` ourselves and use as an almost
97
- // perfect replacement.
98
- var charCode = 'charCode' in nativeEvent ?
99
- nativeEvent.charCode :
100
- nativeEvent.keyCode;
96
+ var charCode = getEventCharCode(nativeEvent);
97
98
// The enter-key is technically both printable and non-printable and can
99
// thus be captured by `keypress`, no other non-printable key should.
@@ -108,8 +104,7 @@ function getEventKey(nativeEvent) {
104
// `keyCode` value, almost all function keys have a universal value.
105
return translateToKey[nativeEvent.keyCode] || 'Unidentified';
106
}
111
-
112
- invariant(false, "Unexpected keyboard event type: %s", nativeEvent.type);
107
+ return '';
108
}
109
110
module.exports = getEventKey;