From 68ca1e890650aa012fcfc15fea0bb702c4075e76 Mon Sep 17 00:00:00 2001 From: Philipp Kunz Date: Wed, 20 Apr 2022 23:56:09 +0200 Subject: [PATCH] fix(core): update --- license | 1 + ts/domtools.classes.domtools.ts | 15 +-- ts/domtools.classes.keyboard.ts | 224 ++++++++++++++++++++++++++++++++ 3 files changed, 228 insertions(+), 12 deletions(-) create mode 100644 ts/domtools.classes.keyboard.ts diff --git a/license b/license index 72c2d21..d3a604f 100644 --- a/license +++ b/license @@ -1,4 +1,5 @@ Copyright (c) 2020 Lossless GmbH (hello@lossless.com) +Copyright (c) 2017 Nathan Friend (ts-keycode-enum) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/ts/domtools.classes.domtools.ts b/ts/domtools.classes.domtools.ts index 947c76a..7215363 100644 --- a/ts/domtools.classes.domtools.ts +++ b/ts/domtools.classes.domtools.ts @@ -6,6 +6,7 @@ import { TViewport } from './domtools.css.breakpoints.js'; import { Scroller } from './domtools.classes.scroller.js'; import { WebSetup } from '@pushrocks/websetup'; import { ThemeManager } from './domtools.classes.thememanager.js'; +import { Keyboard, Key } from './domtools.classes.keyboard.js'; export interface IDomToolsState { virtualViewport: TViewport; @@ -91,18 +92,8 @@ export class DomTools { /* some options */ }); // TODO: switch to scroller class public themeManager = new ThemeManager(this); - - /* private actionSetVirtualViewport = this.domToolsStatePart.createAction( - async (statePart, payload) => { - const currentState = statePart.getState(); - currentState.virtualViewport = payload; - return currentState; - } - ); - - public setVirtualViewport(environmentArg: TViewport) { - this.domToolsStatePart.dispatchAction(this.actionSetVirtualViewport, environmentArg); - } */ + public keyboard = new Keyboard(document.body); + public domToolsReady = plugins.smartpromise.defer(); public domReady = plugins.smartpromise.defer(); diff --git a/ts/domtools.classes.keyboard.ts b/ts/domtools.classes.keyboard.ts new file mode 100644 index 0000000..5ebb290 --- /dev/null +++ b/ts/domtools.classes.keyboard.ts @@ -0,0 +1,224 @@ +export enum Key { + Backspace = 8, + Tab = 9, + Enter = 13, + Shift = 16, + Ctrl = 17, + Alt = 18, + PauseBreak = 19, + CapsLock = 20, + Escape = 27, + Space = 32, + PageUp = 33, + PageDown = 34, + End = 35, + Home = 36, + + LeftArrow = 37, + UpArrow = 38, + RightArrow = 39, + DownArrow = 40, + + Insert = 45, + Delete = 46, + + Zero = 48, + ClosedParen = Zero, + One = 49, + ExclamationMark = One, + Two = 50, + AtSign = Two, + Three = 51, + PoundSign = Three, + Hash = PoundSign, + Four = 52, + DollarSign = Four, + Five = 53, + PercentSign = Five, + Six = 54, + Caret = Six, + Hat = Caret, + Seven = 55, + Ampersand = Seven, + Eight = 56, + Star = Eight, + Asterik = Star, + Nine = 57, + OpenParen = Nine, + + A = 65, + B = 66, + C = 67, + D = 68, + E = 69, + F = 70, + G = 71, + H = 72, + I = 73, + J = 74, + K = 75, + L = 76, + M = 77, + N = 78, + O = 79, + P = 80, + Q = 81, + R = 82, + S = 83, + T = 84, + U = 85, + V = 86, + W = 87, + X = 88, + Y = 89, + Z = 90, + + LeftWindowKey = 91, + RightWindowKey = 92, + SelectKey = 93, + + Numpad0 = 96, + Numpad1 = 97, + Numpad2 = 98, + Numpad3 = 99, + Numpad4 = 100, + Numpad5 = 101, + Numpad6 = 102, + Numpad7 = 103, + Numpad8 = 104, + Numpad9 = 105, + + Multiply = 106, + Add = 107, + Subtract = 109, + DecimalPoint = 110, + Divide = 111, + + F1 = 112, + F2 = 113, + F3 = 114, + F4 = 115, + F5 = 116, + F6 = 117, + F7 = 118, + F8 = 119, + F9 = 120, + F10 = 121, + F11 = 122, + F12 = 123, + + NumLock = 144, + ScrollLock = 145, + + SemiColon = 186, + Equals = 187, + Comma = 188, + Dash = 189, + Period = 190, + UnderScore = Dash, + PlusSign = Equals, + ForwardSlash = 191, + Tilde = 192, + GraveAccent = Tilde, + + OpenBracket = 219, + ClosedBracket = 221, + Quote = 222 +} + +type KeyCombo = Array + +/** + * @param {KeyboardEvent} event - pressed key event, in case of multi-key combos + * the last pressed key event is passed to this handler + */ +type Handler = (event: KeyboardEvent) => void + +export class Keyboard { + private mapCombosToHandlers = new Map(); + private pressedKeys = new Set(); + + constructor( + private domNode: Element | Document + ) { + this.startListening() + } + + on(keys: Key[] | KeyCombo[], callback: Handler) { + const combos = this.toCombos(keys) + + combos.forEach(combo => { + this.registerComboCallback(combo, callback) + }) + } + + startListening() { + this.domNode.addEventListener('keydown', this.handleKeyDown) + this.domNode.addEventListener('keyup', this.handleKeyUp) + } + + stopListening() { + this.domNode.removeEventListener('keydown', this.handleKeyDown) + this.domNode.removeEventListener('keyup', this.handleKeyUp) + } + + clear() { + this.stopListening() + this.mapCombosToHandlers.clear() + this.pressedKeys.clear() + } + + private handleKeyDown = (event: KeyboardEvent) => { + this.pressedKeys.add(event.keyCode) + + this.mapCombosToHandlers.forEach((handlers, combo) => { + if (this.isComboPressed(combo)) { + handlers.forEach(handler => handler(event)) + } + }) + } + + private handleKeyUp = (event: KeyboardEvent) => { + this.pressedKeys.delete(event.keyCode) + } + + private isComboPressed(combo: number[]) { + let result = true + + combo.forEach(key => { + if (!this.pressedKeys.has(key)) { + result = false + } + }) + + return result + } + + private registerComboCallback(combo: Array, callback: Handler) { + if (!this.mapCombosToHandlers.has(combo)) { + this.mapCombosToHandlers.set(combo, []) + } + + const handlers = this.mapCombosToHandlers.get(combo) + + handlers!.push(callback) + } + + private toCombos(keys: KeyCombo[] | Key[]) { + if (keys.length === 0) { + return [] + } + + const isKeys = !Array.isArray(keys[0]) + let combos: KeyCombo[] = [] + + if (isKeys) { + combos = (keys as Key[]).map(key => [key]) + } else { + combos = keys as KeyCombo[] + combos = combos.filter(combo => combo.length > 0) + } + + return combos + } +} \ No newline at end of file