This commit is contained in:
Mo Bitar
2020-02-08 12:11:04 -06:00
parent 13dd41b9ab
commit f6ef4a39e2
26 changed files with 10885 additions and 2044 deletions

View File

@@ -1,42 +1,41 @@
export class KeyboardManager {
/** @public */
export const KeyboardKeys = {
Tab: "Tab",
Backspace: "Backspace",
Up: "ArrowUp",
Down: "ArrowDown",
};
/** @public */
export const KeyboardModifiers = {
Shift: "Shift",
Ctrl: "Control",
/** ⌘ key on Mac, ⊞ key on Windows */
Meta: "Meta",
Alt: "Alt",
};
/** @private */
const KeyboardKeyEvents = {
Down: "KeyEventDown",
Up: "KeyEventUp"
};
export class KeyboardManager {
constructor() {
this.observers = [];
KeyboardManager.KeyTab = "Tab";
KeyboardManager.KeyBackspace = "Backspace";
KeyboardManager.KeyUp = "ArrowUp";
KeyboardManager.KeyDown = "ArrowDown";
KeyboardManager.KeyModifierShift = "Shift";
KeyboardManager.KeyModifierCtrl = "Control";
// ⌘ key on Mac, ⊞ key on Windows
KeyboardManager.KeyModifierMeta = "Meta";
KeyboardManager.KeyModifierAlt = "Alt";
KeyboardManager.KeyEventDown = "KeyEventDown";
KeyboardManager.KeyEventUp = "KeyEventUp";
KeyboardManager.AllModifiers = [
KeyboardManager.KeyModifierShift,
KeyboardManager.KeyModifierCtrl,
KeyboardManager.KeyModifierMeta,
KeyboardManager.KeyModifierAlt
];
window.addEventListener('keydown', this.handleKeyDown.bind(this));
window.addEventListener('keyup', this.handleKeyUp.bind(this));
}
modifiersForEvent(event) {
const eventModifiers = KeyboardManager.AllModifiers.filter((modifier) => {
const allModifiers = Object.keys(KeyboardModifiers).map((key) => KeyboardModifiers[key]);
const eventModifiers = allModifiers.filter((modifier) => {
// For a modifier like ctrlKey, must check both event.ctrlKey and event.key.
// That's because on keyup, event.ctrlKey would be false, but event.key == Control would be true.
const matches = (
((event.ctrlKey || event.key == KeyboardManager.KeyModifierCtrl) && modifier === KeyboardManager.KeyModifierCtrl) ||
((event.metaKey || event.key == KeyboardManager.KeyModifierMeta) && modifier === KeyboardManager.KeyModifierMeta) ||
((event.altKey || event.key == KeyboardManager.KeyModifierAlt) && modifier === KeyboardManager.KeyModifierAlt) ||
((event.shiftKey || event.key == KeyboardManager.KeyModifierShift) && modifier === KeyboardManager.KeyModifierShift)
((event.ctrlKey || event.key === KeyboardModifiers.Ctrl) && modifier === KeyboardModifiers.Ctrl) ||
((event.metaKey || event.key === KeyboardModifiers.Meta) && modifier === KeyboardModifiers.Meta) ||
((event.altKey || event.key === KeyboardModifiers.Alt) && modifier === KeyboardModifiers.Alt) ||
((event.shiftKey || event.key === KeyboardModifiers.Shift) && modifier === KeyboardModifiers.Shift)
);
return matches;
@@ -45,50 +44,50 @@ export class KeyboardManager {
return eventModifiers;
}
eventMatchesKeyAndModifiers(event, key, modifiers = []) {
eventMatchesKeyAndModifiers(event, key, modifiers = []) {
const eventModifiers = this.modifiersForEvent(event);
if(eventModifiers.length != modifiers.length) {
if (eventModifiers.length !== modifiers.length) {
return false;
}
for(const modifier of modifiers) {
if(!eventModifiers.includes(modifier)) {
for (const modifier of modifiers) {
if (!eventModifiers.includes(modifier)) {
return false;
}
}
// Modifers match, check key
if(!key) {
if (!key) {
return true;
}
// In the browser, shift + f results in key 'f', but in Electron, shift + f results in 'F'
// In our case we don't differentiate between the two.
return key.toLowerCase() == event.key.toLowerCase();
return key.toLowerCase() === event.key.toLowerCase();
}
notifyObserver(event, keyEventType) {
for(const observer of this.observers) {
if(observer.element && event.target != observer.element) {
for (const observer of this.observers) {
if (observer.element && event.target !== observer.element) {
continue;
}
if(observer.elements && !observer.elements.includes(event.target)) {
if (observer.elements && !observer.elements.includes(event.target)) {
continue;
}
if(observer.notElement && observer.notElement == event.target) {
if (observer.notElement && observer.notElement === event.target) {
continue;
}
if(observer.notElementIds && observer.notElementIds.includes(event.target.id)) {
if (observer.notElementIds && observer.notElementIds.includes(event.target.id)) {
continue;
}
if(this.eventMatchesKeyAndModifiers(event, observer.key, observer.modifiers)) {
const callback = keyEventType == KeyboardManager.KeyEventDown ? observer.onKeyDown : observer.onKeyUp;
if(callback) {
if (this.eventMatchesKeyAndModifiers(event, observer.key, observer.modifiers)) {
const callback = keyEventType === KeyboardKeyEvents.Down ? observer.onKeyDown : observer.onKeyUp;
if (callback) {
callback(event);
}
}
@@ -96,15 +95,15 @@ export class KeyboardManager {
}
handleKeyDown(event) {
this.notifyObserver(event, KeyboardManager.KeyEventDown);
this.notifyObserver(event, KeyboardKeyEvents.Down);
}
handleKeyUp(event) {
this.notifyObserver(event, KeyboardManager.KeyEventUp);
this.notifyObserver(event, KeyboardKeyEvents.Up);
}
addKeyObserver({key, modifiers, onKeyDown, onKeyUp, element, elements, notElement, notElementIds}) {
const observer = {key, modifiers, onKeyDown, onKeyUp, element, elements, notElement, notElementIds};
addKeyObserver({ key, modifiers, onKeyDown, onKeyUp, element, elements, notElement, notElementIds }) {
const observer = { key, modifiers, onKeyDown, onKeyUp, element, elements, notElement, notElementIds };
this.observers.push(observer);
return observer;
}