Fix hotkey input field conflict (#1963)

* Move comment

* Add DocumentUtil.isInputElement

* Use DocumentUtil.isInputElement

* Fix simple hotkeys (shift or no modifier) preventing text field input

* Improve input detection

* Validate key is an input character before blocking hotkey

* Simplify

* Fix incorrect property
This commit is contained in:
toasted-nutbread 2021-09-26 18:14:00 -04:00 committed by GitHub
parent d739ccd63f
commit c364714c81
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 35 additions and 20 deletions

View File

@ -311,6 +311,22 @@ class DocumentUtil {
return !(browser === 'firefox' || browser === 'firefox-mobile') || os === 'mac';
}
static isInputElementFocused() {
const element = document.activeElement;
if (element === null) { return false; }
const type = element.nodeName.toUpperCase();
switch (type) {
case 'INPUT':
case 'TEXTAREA':
case 'SELECT':
return true;
default:
return element.isContentEditable;
}
}
// Private
static _getActiveButtons(event, array) {
let {buttons} = event;
if (typeof buttons === 'number' && buttons > 0) {
@ -325,8 +341,6 @@ class DocumentUtil {
}
}
// Private
_setImposterStyle(style, propertyName, value) {
style.setProperty(propertyName, value, 'important');
}

View File

@ -153,11 +153,10 @@ class HotkeyHandler extends EventDispatcher {
// Private
_onKeyDown(e) {
const key = e.code;
const hotkeyInfo = this._hotkeys.get(key);
const hotkeyInfo = this._hotkeys.get(e.code);
if (typeof hotkeyInfo !== 'undefined') {
const eventModifiers = DocumentUtil.getActiveModifiers(e);
if (this._invokeHandlers(eventModifiers, hotkeyInfo)) {
if (this._invokeHandlers(eventModifiers, hotkeyInfo, e.key)) {
e.preventDefault();
return;
}
@ -165,9 +164,9 @@ class HotkeyHandler extends EventDispatcher {
this.trigger('keydownNonHotkey', e);
}
_invokeHandlers(modifiers, hotkeyInfo) {
_invokeHandlers(modifiers, hotkeyInfo, key) {
for (const {modifiers: handlerModifiers, action, argument} of hotkeyInfo.handlers) {
if (!this._areSame(handlerModifiers, modifiers)) { continue; }
if (!this._areSame(handlerModifiers, modifiers) || !this._isHotkeyPermitted(modifiers, key)) { continue; }
const actionHandler = this._actions.get(action);
if (typeof actionHandler !== 'undefined') {
@ -223,4 +222,16 @@ class HotkeyHandler extends EventDispatcher {
this._eventListeners.removeAllEventListeners();
}
}
_isHotkeyPermitted(modifiers, key) {
return !(
(modifiers.length === 0 || (modifiers.length === 1 && modifiers[0] === 'shift')) &&
DocumentUtil.isInputElementFocused() &&
this._isKeyCharacterInput(key)
);
}
_isKeyCharacterInput(key) {
return key.length === 1;
}
}

View File

@ -16,6 +16,7 @@
*/
/* global
* DocumentUtil
* PopupMenu
* SelectorObserver
*/
@ -155,7 +156,7 @@ class SettingsDisplayController {
_onKeyDown(e) {
switch (e.code) {
case 'Escape':
if (!this._isElementAnInput(document.activeElement)) {
if (!DocumentUtil.isInputElementFocused()) {
this._closeTopMenuOrModal();
e.preventDefault();
}
@ -357,18 +358,6 @@ class SettingsDisplayController {
}
}
_isElementAnInput(element) {
const type = element !== null ? element.nodeName.toUpperCase() : null;
switch (type) {
case 'INPUT':
case 'TEXTAREA':
case 'SELECT':
return true;
default:
return false;
}
}
_setupDeferLoadIframe(element) {
const parent = this._getMoreContainer(element);
if (parent === null) { return; }

View File

@ -263,6 +263,7 @@
<script src="/js/data/anki-util.js"></script>
<script src="/js/data/permissions-util.js"></script>
<script src="/js/dom/document-focus-controller.js"></script>
<script src="/js/dom/document-util.js"></script>
<script src="/js/dom/html-template-collection.js"></script>
<script src="/js/dom/panel-element.js"></script>
<script src="/js/dom/popup-menu.js"></script>