@samitouri / QOS-React-2 / commits / bf7826c68d

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;