keeweb/app/scripts/comp/browser/key-handler.js

140 lines
4.0 KiB
JavaScript

import { Events } from 'framework/events';
import { IdleTracker } from 'comp/browser/idle-tracker';
import { Keys } from 'const/keys';
import { FocusManager } from 'comp/app/focus-manager';
const shortcutKeyProp = navigator.platform.indexOf('Mac') >= 0 ? 'metaKey' : 'ctrlKey';
class KeyHandler {
SHORTCUT_ACTION = 1;
SHORTCUT_OPT = 2;
SHORTCUT_SHIFT = 4;
shortcuts = {};
init() {
$(document).bind('keypress', this.keypress.bind(this));
$(document).bind('keydown', this.keydown.bind(this));
this.shortcuts[Keys.DOM_VK_A] = [
{
handler: this.handleAKey,
thisArg: this,
shortcut: this.SHORTCUT_ACTION,
modal: true,
noPrevent: true
}
];
}
onKey(key, handler, thisArg, shortcut, modal, noPrevent) {
let keyShortcuts = this.shortcuts[key];
if (!keyShortcuts) {
this.shortcuts[key] = keyShortcuts = [];
}
keyShortcuts.push({
handler,
thisArg,
shortcut,
modal,
noPrevent
});
}
offKey(key, handler, thisArg) {
if (this.shortcuts[key]) {
this.shortcuts[key] = this.shortcuts[key].filter(
(sh) => sh.handler !== handler || sh.thisArg !== thisArg
);
}
}
isActionKey(e) {
return e[shortcutKeyProp];
}
keydown(e) {
IdleTracker.regUserAction();
const code = e.keyCode || e.which;
const keyShortcuts = this.shortcuts[code];
if (keyShortcuts && keyShortcuts.length) {
for (const sh of keyShortcuts) {
if (FocusManager.modal && sh.modal !== FocusManager.modal && sh.modal !== '*') {
e.stopPropagation();
continue;
}
const isActionKey = this.isActionKey(e);
switch (sh.shortcut) {
case this.SHORTCUT_ACTION:
if (!isActionKey) {
continue;
}
break;
case this.SHORTCUT_OPT:
if (!e.altKey) {
continue;
}
break;
case this.SHORTCUT_SHIFT:
if (!e.shiftKey) {
continue;
}
break;
case this.SHORTCUT_ACTION + this.SHORTCUT_OPT:
if (!e.altKey || !isActionKey) {
continue;
}
break;
default:
if (e.metaKey || e.ctrlKey || e.altKey || e.shiftKey) {
continue;
}
break;
}
sh.handler.call(sh.thisArg, e, code);
if (isActionKey && !sh.noPrevent) {
e.preventDefault();
}
if (e.isImmediatePropagationStopped()) {
break;
}
}
}
}
keypress(e) {
if (
!FocusManager.modal &&
e.which !== Keys.DOM_VK_RETURN &&
e.which !== Keys.DOM_VK_ESCAPE &&
e.which !== Keys.DOM_VK_TAB &&
!e.altKey &&
!e.ctrlKey &&
!e.metaKey
) {
Events.emit('keypress', e);
} else if (FocusManager.modal) {
Events.emit('keypress:' + FocusManager.modal, e);
}
}
reg() {
IdleTracker.regUserAction();
}
handleAKey(e) {
if (
e.target.tagName.toLowerCase() === 'input' &&
['password', 'text'].indexOf(e.target.type) >= 0
) {
e.stopImmediatePropagation();
} else {
e.preventDefault();
}
}
}
const instance = new KeyHandler();
export { instance as KeyHandler };