Normalize and polyfill KeyboardEvent further, also MouseEvent+TouchEvent
KeyboardEvent now normalizes "charCode", "keyCode", "which" across all browsers KeyboardEvent has partial "key"-support for KeyDown/KeyUp and full "key"-support for KeyPress. KeyboardEvent, MouseEvent and TouchEvent now has "getModifierState", polyfill when not implemented.
Andreas Svensson committed
Jan 1, 2014 at 12:26 UTC
bf7826c68dcd9a6504605bb39cfbee6ad8af9a7c
7 files changed
+131
-13
docs/docs/ref-05-events.md
+5
-2
@@ -62,8 +62,9 @@ Properties:
62
63
```javascript
64
boolean altKey
65
-boolean ctrlKey
65
Number charCode
66
+boolean ctrlKey
67
+function getModifierState(key)
68
String key
69
Number keyCode
70
String locale
@@ -120,6 +121,7 @@ Number buttons
121
Number clientX
122
Number clientY
123
boolean ctrlKey
124
+function getModifierState(key)
125
boolean metaKey
126
Number pageX
127
Number pageY
@@ -147,6 +149,7 @@ Properties:
149
boolean altKey
150
DOMTouchList changedTouches
151
boolean ctrlKey
152
+function getModifierState(key)
153
boolean metaKey
154
boolean shiftKey
155
DOMTouchList targetTouches
@@ -181,8 +184,8 @@ onWheel
184
Properties:
185
186
```javascript
184
-Number deltaX
187
Number deltaMode
188
+Number deltaX
189
Number deltaY
190
Number deltaZ
191
```
src/browser/eventPlugins/SimpleEventPlugin.js
+7
-1
@@ -341,8 +341,14 @@ var SimpleEventPlugin = {
341
// @see http://www.w3.org/TR/html5/index.html#events-0
342
EventConstructor = SyntheticEvent;
343
break;
344
- case topLevelTypes.topKeyDown:
344
case topLevelTypes.topKeyPress:
345
+ // FireFox creates a keypress event for function keys too. This removes
346
+ // the unwanted keypress events.
347
+ if (nativeEvent.charCode === 0) {
348
+ return null;
349
+ }
350
+ /* falls through */
351
+ case topLevelTypes.topKeyDown:
352
case topLevelTypes.topKeyUp:
353
EventConstructor = SyntheticKeyboardEvent;
354
break;
src/browser/syntheticEvents/SyntheticKeyboardEvent.js
+33
-4
@@ -22,6 +22,7 @@
22
var SyntheticUIEvent = require('SyntheticUIEvent');
23
24
var getEventKey = require('getEventKey');
25
+var getEventModifierState = require('getEventModifierState');
26
27
/**
28
* @interface KeyboardEvent
@@ -36,11 +37,39 @@ var KeyboardEventInterface = {
37
metaKey: null,
38
repeat: null,
39
locale: null,
40
+ getModifierState: getEventModifierState,
41
// Legacy Interface
40
- 'char': null,
41
- charCode: null,
42
- keyCode: null,
43
- which: null
42
+ charCode: function(event) {
43
+ // `charCode` is the result of a KeyPress event and represents the value of
44
+ // the actual printable character.
45
+
46
+ // KeyPress is deprecated but its replacement is not yet final and not
47
+ // implemented in any major browser.
48
+ 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;
51
+ }
52
+ return 0;
53
+ },
54
+ keyCode: function(event) {
55
+ // `keyCode` is the result of a KeyDown/Up event and represents the value of
56
+ // physical keyboard key.
57
+
58
+ // The actual meaning of the value depends on the users' keyboard layout
59
+ // which cannot be detected. Assuming that it is a US keyboard layout
60
+ // provides a surprisingly accurate mapping for US and European users.
61
+ // Due to this, it is left to the user to implement at this time.
62
+ if (event.type === 'keydown' || event.type === 'keyup') {
63
+ return event.keyCode;
64
+ }
65
+ return 0;
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;
72
+ }
73
};
74
75
/**
src/browser/syntheticEvents/SyntheticMouseEvent.js
+3
@@ -22,6 +22,8 @@
22
var SyntheticUIEvent = require('SyntheticUIEvent');
23
var ViewportMetrics = require('ViewportMetrics');
24
25
+var getEventModifierState = require('getEventModifierState');
26
+
27
/**
28
* @interface MouseEvent
29
* @see http://www.w3.org/TR/DOM-Level-3-Events/
@@ -35,6 +37,7 @@ var MouseEventInterface = {
37
shiftKey: null,
38
altKey: null,
39
metaKey: null,
40
+ getEventModifierState: getEventModifierState,
41
button: function(event) {
42
// Webkit, Firefox, IE9+
43
// which: 1 2 3
src/browser/syntheticEvents/SyntheticTouchEvent.js
+4
-1
@@ -21,6 +21,8 @@
21
22
var SyntheticUIEvent = require('SyntheticUIEvent');
23
24
+var getEventModifierState = require('getEventModifierState');
25
+
26
/**
27
* @interface TouchEvent
28
* @see http://www.w3.org/TR/touch-events/
@@ -32,7 +34,8 @@ var TouchEventInterface = {
34
altKey: null,
35
metaKey: null,
36
ctrlKey: null,
35
- shiftKey: null
37
+ shiftKey: null,
38
+ getModifierState: getEventModifierState
39
};
40
41
/**
src/browser/ui/dom/getEventKey.js
+35
-5
@@ -19,8 +19,10 @@
19
20
"use strict";
21
22
+var invariant = require('invariant');
23
+
24
/**
23
- * Normalization of deprecated HTML5 "key" values
25
+ * Normalization of deprecated HTML5 `key` values
26
* @see https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent#Key_names
27
*/
28
var normalizeKey = {
@@ -39,7 +41,7 @@ var normalizeKey = {
41
};
42
43
/**
42
- * Translation from legacy "which/keyCode" to HTML5 "key"
44
+ * Translation from legacy `which`/`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
*/
@@ -77,9 +79,37 @@ var translateToKey = {
79
* @return {string} Normalized `key` property.
80
*/
81
function getEventKey(nativeEvent) {
80
- return 'key' in nativeEvent ?
81
- normalizeKey[nativeEvent.key] || nativeEvent.key :
82
- translateToKey[nativeEvent.which || nativeEvent.keyCode] || 'Unidentified';
82
+ if (nativeEvent.key) {
83
+ // Normalize inconsistent values reported by browsers due to
84
+ // implementations of a working draft specification.
85
+
86
+ // FireFox implements `key` but returns `MozPrintableKey` for all
87
+ // printable characters (normalized to `Unidentified`), ignore it.
88
+ var key = normalizeKey[nativeEvent.key] || nativeEvent.key;
89
+ if (key !== 'Unidentified') {
90
+ return key;
91
+ }
92
+ }
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;
101
+
102
+ // The enter-key is technically both printable and non-printable and can
103
+ // thus be captured by `keypress`, no other non-printable key should.
104
+ return charCode === 13 ? 'Enter' : String.fromCharCode(charCode);
105
+ }
106
+ if (nativeEvent.type === 'keydown' || nativeEvent.type === 'keyup') {
107
+ // While user keyboard layout determines the actual meaning of each
108
+ // `keyCode` value, almost all function keys have a universal value.
109
+ return translateToKey[nativeEvent.keyCode] || 'Unidentified';
110
+ }
111
+
112
+ invariant(false, "Unexpected keyboard event type: %s", nativeEvent.type);
113
}
114
115
module.exports = getEventKey;
src/browser/ui/dom/getEventModifierState.js
new
+44
@@ -0,0 +1,44 @@
1
+/**
2
+ * Copyright 2013 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 getEventModifierState
17
+ * @typechecks static-only
18
+ */
19
+
20
+"use strict";
21
+
22
+/**
23
+ * Translation from modifier key to the associated property in the event.
24
+ * @see http://www.w3.org/TR/DOM-Level-3-Events/#keys-Modifiers
25
+ */
26
+
27
+var modifierKeyToProp = {
28
+ 'alt': 'altKey',
29
+ 'control': 'ctrlKey',
30
+ 'meta': 'metaKey',
31
+ 'shift': 'shiftKey'
32
+};
33
+
34
+function getEventModifierState(nativeEvent) {
35
+ // IE8 does not implement getModifierState so we simply map it to the only
36
+ // modifier keys exposed by the event itself, does not support Lock-keys.
37
+ // Currently, all major browsers except Chrome seems to support Lock-keys.
38
+ return nativeEvent.getModifierState || function(keyArg) {
39
+ var keyProp = modifierKeyToProp[keyArg.toLowerCase()];
40
+ return keyProp && nativeEvent[keyProp];
41
+ };
42
+}
43
+
44
+module.exports = getEventModifierState;