Refactor ES6 module structure/split up Util

This commit restructures many of the ES6 modules, splitting them
up to actual export multiple functions instead of a single object.

It also splits up Util into multiple sub-modules, to make it easier
to maintain.

Finally, localisation is renamed to localization.
This commit is contained in:
Solly Ross
2017-02-04 21:26:00 -05:00
parent 6e744119f8
commit 6d6f0db0da
21 changed files with 5806 additions and 5838 deletions
+255 -273
View File
@@ -1,293 +1,277 @@
import KeyTable from "./keysym.js";
import keysyms from "./keysymdef.js";
export function substituteCodepoint(cp) {
// Any Unicode code points which do not have corresponding keysym entries
// can be swapped out for another code point by adding them to this table
var substitutions = {
// {S,s} with comma below -> {S,s} with cedilla
0x218 : 0x15e,
0x219 : 0x15f,
// {T,t} with comma below -> {T,t} with cedilla
0x21a : 0x162,
0x21b : 0x163
};
var KeyboardUtil = {};
var sub = substitutions[cp];
return sub ? sub : cp;
}
(function() {
"use strict";
function isMac() {
return navigator && !!(/mac/i).exec(navigator.platform);
}
function isWindows() {
return navigator && !!(/win/i).exec(navigator.platform);
}
function isLinux() {
return navigator && !!(/linux/i).exec(navigator.platform);
}
function substituteCodepoint(cp) {
// Any Unicode code points which do not have corresponding keysym entries
// can be swapped out for another code point by adding them to this table
var substitutions = {
// {S,s} with comma below -> {S,s} with cedilla
0x218 : 0x15e,
0x219 : 0x15f,
// {T,t} with comma below -> {T,t} with cedilla
0x21a : 0x162,
0x21b : 0x163
};
var sub = substitutions[cp];
return sub ? sub : cp;
}
function isMac() {
return navigator && !!(/mac/i).exec(navigator.platform);
}
function isWindows() {
return navigator && !!(/win/i).exec(navigator.platform);
}
function isLinux() {
return navigator && !!(/linux/i).exec(navigator.platform);
}
// Return true if a modifier which is not the specified char modifier (and is not shift) is down
function hasShortcutModifier(charModifier, currentModifiers) {
var mods = {};
for (var key in currentModifiers) {
if (parseInt(key) !== KeyTable.XK_Shift_L) {
mods[key] = currentModifiers[key];
}
// Return true if a modifier which is not the specified char modifier (and is not shift) is down
export function hasShortcutModifier(charModifier, currentModifiers) {
var mods = {};
for (var key in currentModifiers) {
if (parseInt(key) !== KeyTable.XK_Shift_L) {
mods[key] = currentModifiers[key];
}
}
var sum = 0;
for (var k in currentModifiers) {
if (mods[k]) {
++sum;
}
var sum = 0;
for (var k in currentModifiers) {
if (mods[k]) {
++sum;
}
if (hasCharModifier(charModifier, mods)) {
return sum > charModifier.length;
}
if (hasCharModifier(charModifier, mods)) {
return sum > charModifier.length;
}
else {
return sum > 0;
}
}
// Return true if the specified char modifier is currently down
export function hasCharModifier(charModifier, currentModifiers) {
if (charModifier.length === 0) { return false; }
for (var i = 0; i < charModifier.length; ++i) {
if (!currentModifiers[charModifier[i]]) {
return false;
}
}
return true;
}
// Helper object tracking modifier key state
// and generates fake key events to compensate if it gets out of sync
export function ModifierSync(charModifier) {
if (!charModifier) {
if (isMac()) {
// on Mac, Option (AKA Alt) is used as a char modifier
charModifier = [KeyTable.XK_Alt_L];
}
else if (isWindows()) {
// on Windows, Ctrl+Alt is used as a char modifier
charModifier = [KeyTable.XK_Alt_L, KeyTable.XK_Control_L];
}
else if (isLinux()) {
// on Linux, ISO Level 3 Shift (AltGr) is used as a char modifier
charModifier = [KeyTable.XK_ISO_Level3_Shift];
}
else {
return sum > 0;
charModifier = [];
}
}
// Return true if the specified char modifier is currently down
function hasCharModifier(charModifier, currentModifiers) {
if (charModifier.length === 0) { return false; }
var state = {};
state[KeyTable.XK_Control_L] = false;
state[KeyTable.XK_Alt_L] = false;
state[KeyTable.XK_ISO_Level3_Shift] = false;
state[KeyTable.XK_Shift_L] = false;
state[KeyTable.XK_Meta_L] = false;
for (var i = 0; i < charModifier.length; ++i) {
if (!currentModifiers[charModifier[i]]) {
return false;
}
function sync(evt, keysym) {
var result = [];
function syncKey(keysym) {
return {keysym: keysyms.lookup(keysym), type: state[keysym] ? 'keydown' : 'keyup'};
}
return true;
if (evt.ctrlKey !== undefined &&
evt.ctrlKey !== state[KeyTable.XK_Control_L] && keysym !== KeyTable.XK_Control_L) {
state[KeyTable.XK_Control_L] = evt.ctrlKey;
result.push(syncKey(KeyTable.XK_Control_L));
}
if (evt.altKey !== undefined &&
evt.altKey !== state[KeyTable.XK_Alt_L] && keysym !== KeyTable.XK_Alt_L) {
state[KeyTable.XK_Alt_L] = evt.altKey;
result.push(syncKey(KeyTable.XK_Alt_L));
}
if (evt.altGraphKey !== undefined &&
evt.altGraphKey !== state[KeyTable.XK_ISO_Level3_Shift] && keysym !== KeyTable.XK_ISO_Level3_Shift) {
state[KeyTable.XK_ISO_Level3_Shift] = evt.altGraphKey;
result.push(syncKey(KeyTable.XK_ISO_Level3_Shift));
}
if (evt.shiftKey !== undefined &&
evt.shiftKey !== state[KeyTable.XK_Shift_L] && keysym !== KeyTable.XK_Shift_L) {
state[KeyTable.XK_Shift_L] = evt.shiftKey;
result.push(syncKey(KeyTable.XK_Shift_L));
}
if (evt.metaKey !== undefined &&
evt.metaKey !== state[KeyTable.XK_Meta_L] && keysym !== KeyTable.XK_Meta_L) {
state[KeyTable.XK_Meta_L] = evt.metaKey;
result.push(syncKey(KeyTable.XK_Meta_L));
}
return result;
}
function syncKeyEvent(evt, down) {
var obj = getKeysym(evt);
var keysym = obj ? obj.keysym : null;
// first, apply the event itself, if relevant
if (keysym !== null && state[keysym] !== undefined) {
state[keysym] = down;
}
return sync(evt, keysym);
}
// Helper object tracking modifier key state
// and generates fake key events to compensate if it gets out of sync
function ModifierSync(charModifier) {
if (!charModifier) {
if (isMac()) {
// on Mac, Option (AKA Alt) is used as a char modifier
charModifier = [KeyTable.XK_Alt_L];
}
else if (isWindows()) {
// on Windows, Ctrl+Alt is used as a char modifier
charModifier = [KeyTable.XK_Alt_L, KeyTable.XK_Control_L];
}
else if (isLinux()) {
// on Linux, ISO Level 3 Shift (AltGr) is used as a char modifier
charModifier = [KeyTable.XK_ISO_Level3_Shift];
}
else {
charModifier = [];
}
}
return {
// sync on the appropriate keyboard event
keydown: function(evt) { return syncKeyEvent(evt, true);},
keyup: function(evt) { return syncKeyEvent(evt, false);},
// Call this with a non-keyboard event (such as mouse events) to use its modifier state to synchronize anyway
syncAny: function(evt) { return sync(evt);},
var state = {};
state[KeyTable.XK_Control_L] = false;
state[KeyTable.XK_Alt_L] = false;
state[KeyTable.XK_ISO_Level3_Shift] = false;
state[KeyTable.XK_Shift_L] = false;
state[KeyTable.XK_Meta_L] = false;
// is a shortcut modifier down?
hasShortcutModifier: function() { return hasShortcutModifier(charModifier, state); },
// if a char modifier is down, return the keys it consists of, otherwise return null
activeCharModifier: function() { return hasCharModifier(charModifier, state) ? charModifier : null; }
};
}
function sync(evt, keysym) {
var result = [];
function syncKey(keysym) {
return {keysym: keysyms.lookup(keysym), type: state[keysym] ? 'keydown' : 'keyup'};
}
if (evt.ctrlKey !== undefined &&
evt.ctrlKey !== state[KeyTable.XK_Control_L] && keysym !== KeyTable.XK_Control_L) {
state[KeyTable.XK_Control_L] = evt.ctrlKey;
result.push(syncKey(KeyTable.XK_Control_L));
}
if (evt.altKey !== undefined &&
evt.altKey !== state[KeyTable.XK_Alt_L] && keysym !== KeyTable.XK_Alt_L) {
state[KeyTable.XK_Alt_L] = evt.altKey;
result.push(syncKey(KeyTable.XK_Alt_L));
}
if (evt.altGraphKey !== undefined &&
evt.altGraphKey !== state[KeyTable.XK_ISO_Level3_Shift] && keysym !== KeyTable.XK_ISO_Level3_Shift) {
state[KeyTable.XK_ISO_Level3_Shift] = evt.altGraphKey;
result.push(syncKey(KeyTable.XK_ISO_Level3_Shift));
}
if (evt.shiftKey !== undefined &&
evt.shiftKey !== state[KeyTable.XK_Shift_L] && keysym !== KeyTable.XK_Shift_L) {
state[KeyTable.XK_Shift_L] = evt.shiftKey;
result.push(syncKey(KeyTable.XK_Shift_L));
}
if (evt.metaKey !== undefined &&
evt.metaKey !== state[KeyTable.XK_Meta_L] && keysym !== KeyTable.XK_Meta_L) {
state[KeyTable.XK_Meta_L] = evt.metaKey;
result.push(syncKey(KeyTable.XK_Meta_L));
}
return result;
}
function syncKeyEvent(evt, down) {
var obj = getKeysym(evt);
var keysym = obj ? obj.keysym : null;
// first, apply the event itself, if relevant
if (keysym !== null && state[keysym] !== undefined) {
state[keysym] = down;
}
return sync(evt, keysym);
}
return {
// sync on the appropriate keyboard event
keydown: function(evt) { return syncKeyEvent(evt, true);},
keyup: function(evt) { return syncKeyEvent(evt, false);},
// Call this with a non-keyboard event (such as mouse events) to use its modifier state to synchronize anyway
syncAny: function(evt) { return sync(evt);},
// is a shortcut modifier down?
hasShortcutModifier: function() { return hasShortcutModifier(charModifier, state); },
// if a char modifier is down, return the keys it consists of, otherwise return null
activeCharModifier: function() { return hasCharModifier(charModifier, state) ? charModifier : null; }
};
// Get a key ID from a keyboard event
// May be a string or an integer depending on the available properties
export function getKey(evt){
if ('keyCode' in evt && 'key' in evt) {
return evt.key + ':' + evt.keyCode;
}
// Get a key ID from a keyboard event
// May be a string or an integer depending on the available properties
function getKey(evt){
if ('keyCode' in evt && 'key' in evt) {
return evt.key + ':' + evt.keyCode;
}
else if ('keyCode' in evt) {
return evt.keyCode;
}
else {
return evt.key;
}
else if ('keyCode' in evt) {
return evt.keyCode;
}
else {
return evt.key;
}
}
// Get the most reliable keysym value we can get from a key event
// if char/charCode is available, prefer those, otherwise fall back to key/keyCode/which
function getKeysym(evt){
var codepoint;
if (evt.char && evt.char.length === 1) {
codepoint = evt.char.charCodeAt();
}
else if (evt.charCode) {
codepoint = evt.charCode;
}
else if (evt.keyCode && evt.type === 'keypress') {
// IE10 stores the char code as keyCode, and has no other useful properties
codepoint = evt.keyCode;
}
if (codepoint) {
return keysyms.fromUnicode(substituteCodepoint(codepoint));
}
// we could check evt.key here.
// Legal values are defined in http://www.w3.org/TR/DOM-Level-3-Events/#key-values-list,
// so we "just" need to map them to keysym, but AFAIK this is only available in IE10, which also provides evt.key
// so we don't *need* it yet
if (evt.keyCode) {
return keysyms.lookup(keysymFromKeyCode(evt.keyCode, evt.shiftKey));
}
if (evt.which) {
return keysyms.lookup(keysymFromKeyCode(evt.which, evt.shiftKey));
}
// Get the most reliable keysym value we can get from a key event
// if char/charCode is available, prefer those, otherwise fall back to key/keyCode/which
export function getKeysym(evt){
var codepoint;
if (evt.char && evt.char.length === 1) {
codepoint = evt.char.charCodeAt();
}
else if (evt.charCode) {
codepoint = evt.charCode;
}
else if (evt.keyCode && evt.type === 'keypress') {
// IE10 stores the char code as keyCode, and has no other useful properties
codepoint = evt.keyCode;
}
if (codepoint) {
return keysyms.fromUnicode(substituteCodepoint(codepoint));
}
// we could check evt.key here.
// Legal values are defined in http://www.w3.org/TR/DOM-Level-3-Events/#key-values-list,
// so we "just" need to map them to keysym, but AFAIK this is only available in IE10, which also provides evt.key
// so we don't *need* it yet
if (evt.keyCode) {
return keysyms.lookup(keysymFromKeyCode(evt.keyCode, evt.shiftKey));
}
if (evt.which) {
return keysyms.lookup(keysymFromKeyCode(evt.which, evt.shiftKey));
}
return null;
}
// Given a keycode, try to predict which keysym it might be.
// If the keycode is unknown, null is returned.
export function keysymFromKeyCode(keycode, shiftPressed) {
if (typeof(keycode) !== 'number') {
return null;
}
// Given a keycode, try to predict which keysym it might be.
// If the keycode is unknown, null is returned.
function keysymFromKeyCode(keycode, shiftPressed) {
if (typeof(keycode) !== 'number') {
return null;
}
// won't be accurate for azerty
if (keycode >= 0x30 && keycode <= 0x39) {
return keycode; // digit
}
if (keycode >= 0x41 && keycode <= 0x5a) {
// remap to lowercase unless shift is down
return shiftPressed ? keycode : keycode + 32; // A-Z
}
if (keycode >= 0x60 && keycode <= 0x69) {
return KeyTable.XK_KP_0 + (keycode - 0x60); // numpad 0-9
}
switch(keycode) {
case 0x20: return KeyTable.XK_space;
case 0x6a: return KeyTable.XK_KP_Multiply;
case 0x6b: return KeyTable.XK_KP_Add;
case 0x6c: return KeyTable.XK_KP_Separator;
case 0x6d: return KeyTable.XK_KP_Subtract;
case 0x6e: return KeyTable.XK_KP_Decimal;
case 0x6f: return KeyTable.XK_KP_Divide;
case 0xbb: return KeyTable.XK_plus;
case 0xbc: return KeyTable.XK_comma;
case 0xbd: return KeyTable.XK_minus;
case 0xbe: return KeyTable.XK_period;
}
return nonCharacterKey({keyCode: keycode});
// won't be accurate for azerty
if (keycode >= 0x30 && keycode <= 0x39) {
return keycode; // digit
}
if (keycode >= 0x41 && keycode <= 0x5a) {
// remap to lowercase unless shift is down
return shiftPressed ? keycode : keycode + 32; // A-Z
}
if (keycode >= 0x60 && keycode <= 0x69) {
return KeyTable.XK_KP_0 + (keycode - 0x60); // numpad 0-9
}
// if the key is a known non-character key (any key which doesn't generate character data)
// return its keysym value. Otherwise return null
function nonCharacterKey(evt) {
// evt.key not implemented yet
if (!evt.keyCode) { return null; }
var keycode = evt.keyCode;
if (keycode >= 0x70 && keycode <= 0x87) {
return KeyTable.XK_F1 + keycode - 0x70; // F1-F24
}
switch (keycode) {
case 8 : return KeyTable.XK_BackSpace;
case 13 : return KeyTable.XK_Return;
case 9 : return KeyTable.XK_Tab;
case 27 : return KeyTable.XK_Escape;
case 46 : return KeyTable.XK_Delete;
case 36 : return KeyTable.XK_Home;
case 35 : return KeyTable.XK_End;
case 33 : return KeyTable.XK_Page_Up;
case 34 : return KeyTable.XK_Page_Down;
case 45 : return KeyTable.XK_Insert;
case 37 : return KeyTable.XK_Left;
case 38 : return KeyTable.XK_Up;
case 39 : return KeyTable.XK_Right;
case 40 : return KeyTable.XK_Down;
case 16 : return KeyTable.XK_Shift_L;
case 17 : return KeyTable.XK_Control_L;
case 18 : return KeyTable.XK_Alt_L; // also: Option-key on Mac
case 224 : return KeyTable.XK_Meta_L;
case 225 : return KeyTable.XK_ISO_Level3_Shift; // AltGr
case 91 : return KeyTable.XK_Super_L; // also: Windows-key
case 92 : return KeyTable.XK_Super_R; // also: Windows-key
case 93 : return KeyTable.XK_Menu; // also: Windows-Menu, Command on Mac
default: return null;
}
switch(keycode) {
case 0x20: return KeyTable.XK_space;
case 0x6a: return KeyTable.XK_KP_Multiply;
case 0x6b: return KeyTable.XK_KP_Add;
case 0x6c: return KeyTable.XK_KP_Separator;
case 0x6d: return KeyTable.XK_KP_Subtract;
case 0x6e: return KeyTable.XK_KP_Decimal;
case 0x6f: return KeyTable.XK_KP_Divide;
case 0xbb: return KeyTable.XK_plus;
case 0xbc: return KeyTable.XK_comma;
case 0xbd: return KeyTable.XK_minus;
case 0xbe: return KeyTable.XK_period;
}
KeyboardUtil.hasShortcutModifier = hasShortcutModifier;
KeyboardUtil.hasCharModifier = hasCharModifier;
KeyboardUtil.ModifierSync = ModifierSync;
KeyboardUtil.getKey = getKey;
KeyboardUtil.getKeysym = getKeysym;
KeyboardUtil.keysymFromKeyCode = keysymFromKeyCode;
KeyboardUtil.nonCharacterKey = nonCharacterKey;
KeyboardUtil.substituteCodepoint = substituteCodepoint;
})();
return nonCharacterKey({keyCode: keycode});
}
KeyboardUtil.QEMUKeyEventDecoder = function(modifierState, next) {
// if the key is a known non-character key (any key which doesn't generate character data)
// return its keysym value. Otherwise return null
export function nonCharacterKey(evt) {
// evt.key not implemented yet
if (!evt.keyCode) { return null; }
var keycode = evt.keyCode;
if (keycode >= 0x70 && keycode <= 0x87) {
return KeyTable.XK_F1 + keycode - 0x70; // F1-F24
}
switch (keycode) {
case 8 : return KeyTable.XK_BackSpace;
case 13 : return KeyTable.XK_Return;
case 9 : return KeyTable.XK_Tab;
case 27 : return KeyTable.XK_Escape;
case 46 : return KeyTable.XK_Delete;
case 36 : return KeyTable.XK_Home;
case 35 : return KeyTable.XK_End;
case 33 : return KeyTable.XK_Page_Up;
case 34 : return KeyTable.XK_Page_Down;
case 45 : return KeyTable.XK_Insert;
case 37 : return KeyTable.XK_Left;
case 38 : return KeyTable.XK_Up;
case 39 : return KeyTable.XK_Right;
case 40 : return KeyTable.XK_Down;
case 16 : return KeyTable.XK_Shift_L;
case 17 : return KeyTable.XK_Control_L;
case 18 : return KeyTable.XK_Alt_L; // also: Option-key on Mac
case 224 : return KeyTable.XK_Meta_L;
case 225 : return KeyTable.XK_ISO_Level3_Shift; // AltGr
case 91 : return KeyTable.XK_Super_L; // also: Windows-key
case 92 : return KeyTable.XK_Super_R; // also: Windows-key
case 93 : return KeyTable.XK_Menu; // also: Windows-Menu, Command on Mac
default: return null;
}
}
export function QEMUKeyEventDecoder (modifierState, next) {
"use strict";
function sendAll(evts) {
@@ -333,7 +317,7 @@ KeyboardUtil.QEMUKeyEventDecoder = function(modifierState, next) {
var hasModifier = modifierState.hasShortcutModifier() || !!modifierState.activeCharModifier();
var isShift = evt.keyCode === 0x10 || evt.key === 'Shift';
var suppress = !isShift && (type !== 'keydown' || modifierState.hasShortcutModifier() || !!KeyboardUtil.nonCharacterKey(evt));
var suppress = !isShift && (type !== 'keydown' || modifierState.hasShortcutModifier() || !!nonCharacterKey(evt));
next(result);
return suppress;
@@ -357,7 +341,7 @@ KeyboardUtil.QEMUKeyEventDecoder = function(modifierState, next) {
};
};
KeyboardUtil.TrackQEMUKeyState = function(next) {
export function TrackQEMUKeyState (next) {
"use strict";
var state = [];
@@ -425,7 +409,7 @@ KeyboardUtil.TrackQEMUKeyState = function(next) {
// - marks each event with an 'escape' property if a modifier was down which should be "escaped"
// - generates a "stall" event in cases where it might be necessary to wait and see if a keypress event follows a keydown
// This information is collected into an object which is passed to the next() function. (one call per event)
KeyboardUtil.KeyEventDecoder = function(modifierState, next) {
export function KeyEventDecoder (modifierState, next) {
"use strict";
function sendAll(evts) {
for (var i = 0; i < evts.length; ++i) {
@@ -434,18 +418,18 @@ KeyboardUtil.KeyEventDecoder = function(modifierState, next) {
}
function process(evt, type) {
var result = {type: type};
var keyId = KeyboardUtil.getKey(evt);
var keyId = getKey(evt);
if (keyId) {
result.keyId = keyId;
}
var keysym = KeyboardUtil.getKeysym(evt);
var keysym = getKeysym(evt);
var hasModifier = modifierState.hasShortcutModifier() || !!modifierState.activeCharModifier();
// Is this a case where we have to decide on the keysym right away, rather than waiting for the keypress?
// "special" keys like enter, tab or backspace don't send keypress events,
// and some browsers don't send keypresses at all if a modifier is down
if (keysym && (type !== 'keydown' || KeyboardUtil.nonCharacterKey(evt) || hasModifier)) {
if (keysym && (type !== 'keydown' || nonCharacterKey(evt) || hasModifier)) {
result.keysym = keysym;
}
@@ -454,11 +438,11 @@ KeyboardUtil.KeyEventDecoder = function(modifierState, next) {
// Should we prevent the browser from handling the event?
// Doing so on a keydown (in most browsers) prevents keypress from being generated
// so only do that if we have to.
var suppress = !isShift && (type !== 'keydown' || modifierState.hasShortcutModifier() || !!KeyboardUtil.nonCharacterKey(evt));
var suppress = !isShift && (type !== 'keydown' || modifierState.hasShortcutModifier() || !!nonCharacterKey(evt));
// If a char modifier is down on a keydown, we need to insert a stall,
// so VerifyCharModifier knows to wait and see if a keypress is comnig
var stall = type === 'keydown' && modifierState.activeCharModifier() && !KeyboardUtil.nonCharacterKey(evt);
var stall = type === 'keydown' && modifierState.activeCharModifier() && !nonCharacterKey(evt);
// if a char modifier is pressed, get the keys it consists of (on Windows, AltGr is equivalent to Ctrl+Alt)
var active = modifierState.activeCharModifier();
@@ -512,7 +496,7 @@ KeyboardUtil.KeyEventDecoder = function(modifierState, next) {
// so when used with the '2' key, Ctrl-Alt counts as a char modifier (and should be escaped), but when used with 'D', it does not.
// The only way we can distinguish these cases is to wait and see if a keypress event arrives
// When we receive a "stall" event, wait a few ms before processing the next keydown. If a keypress has also arrived, merge the two
KeyboardUtil.VerifyCharModifier = function(next) {
export function VerifyCharModifier (next) {
"use strict";
var queue = [];
var timer = null;
@@ -569,7 +553,7 @@ KeyboardUtil.VerifyCharModifier = function(next) {
// in some cases, a single key may produce multiple keysyms, so the corresponding keyup event must release all of these chars
// key repeat events should be merged into a single entry.
// Because we can't always identify which entry a keydown or keyup event corresponds to, we sometimes have to guess
KeyboardUtil.TrackKeyState = function(next) {
export function TrackKeyState (next) {
"use strict";
var state = [];
@@ -653,7 +637,7 @@ KeyboardUtil.TrackKeyState = function(next) {
// Handles "escaping" of modifiers: if a char modifier is used to produce a keysym (such as AltGr-2 to generate an @),
// then the modifier must be "undone" before sending the @, and "redone" afterwards.
KeyboardUtil.EscapeModifiers = function(next) {
export function EscapeModifiers (next) {
"use strict";
return function(evt) {
if (evt.type !== 'keydown' || evt.escape === undefined) {
@@ -674,5 +658,3 @@ KeyboardUtil.EscapeModifiers = function(next) {
/* jshint shadow: false */
};
};
export default KeyboardUtil;