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:
parent
d739ccd63f
commit
c364714c81
@ -311,6 +311,22 @@ class DocumentUtil {
|
|||||||
return !(browser === 'firefox' || browser === 'firefox-mobile') || os === 'mac';
|
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) {
|
static _getActiveButtons(event, array) {
|
||||||
let {buttons} = event;
|
let {buttons} = event;
|
||||||
if (typeof buttons === 'number' && buttons > 0) {
|
if (typeof buttons === 'number' && buttons > 0) {
|
||||||
@ -325,8 +341,6 @@ class DocumentUtil {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Private
|
|
||||||
|
|
||||||
_setImposterStyle(style, propertyName, value) {
|
_setImposterStyle(style, propertyName, value) {
|
||||||
style.setProperty(propertyName, value, 'important');
|
style.setProperty(propertyName, value, 'important');
|
||||||
}
|
}
|
||||||
|
@ -153,11 +153,10 @@ class HotkeyHandler extends EventDispatcher {
|
|||||||
// Private
|
// Private
|
||||||
|
|
||||||
_onKeyDown(e) {
|
_onKeyDown(e) {
|
||||||
const key = e.code;
|
const hotkeyInfo = this._hotkeys.get(e.code);
|
||||||
const hotkeyInfo = this._hotkeys.get(key);
|
|
||||||
if (typeof hotkeyInfo !== 'undefined') {
|
if (typeof hotkeyInfo !== 'undefined') {
|
||||||
const eventModifiers = DocumentUtil.getActiveModifiers(e);
|
const eventModifiers = DocumentUtil.getActiveModifiers(e);
|
||||||
if (this._invokeHandlers(eventModifiers, hotkeyInfo)) {
|
if (this._invokeHandlers(eventModifiers, hotkeyInfo, e.key)) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -165,9 +164,9 @@ class HotkeyHandler extends EventDispatcher {
|
|||||||
this.trigger('keydownNonHotkey', e);
|
this.trigger('keydownNonHotkey', e);
|
||||||
}
|
}
|
||||||
|
|
||||||
_invokeHandlers(modifiers, hotkeyInfo) {
|
_invokeHandlers(modifiers, hotkeyInfo, key) {
|
||||||
for (const {modifiers: handlerModifiers, action, argument} of hotkeyInfo.handlers) {
|
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);
|
const actionHandler = this._actions.get(action);
|
||||||
if (typeof actionHandler !== 'undefined') {
|
if (typeof actionHandler !== 'undefined') {
|
||||||
@ -223,4 +222,16 @@ class HotkeyHandler extends EventDispatcher {
|
|||||||
this._eventListeners.removeAllEventListeners();
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/* global
|
/* global
|
||||||
|
* DocumentUtil
|
||||||
* PopupMenu
|
* PopupMenu
|
||||||
* SelectorObserver
|
* SelectorObserver
|
||||||
*/
|
*/
|
||||||
@ -155,7 +156,7 @@ class SettingsDisplayController {
|
|||||||
_onKeyDown(e) {
|
_onKeyDown(e) {
|
||||||
switch (e.code) {
|
switch (e.code) {
|
||||||
case 'Escape':
|
case 'Escape':
|
||||||
if (!this._isElementAnInput(document.activeElement)) {
|
if (!DocumentUtil.isInputElementFocused()) {
|
||||||
this._closeTopMenuOrModal();
|
this._closeTopMenuOrModal();
|
||||||
e.preventDefault();
|
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) {
|
_setupDeferLoadIframe(element) {
|
||||||
const parent = this._getMoreContainer(element);
|
const parent = this._getMoreContainer(element);
|
||||||
if (parent === null) { return; }
|
if (parent === null) { return; }
|
||||||
|
@ -263,6 +263,7 @@
|
|||||||
<script src="/js/data/anki-util.js"></script>
|
<script src="/js/data/anki-util.js"></script>
|
||||||
<script src="/js/data/permissions-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-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/html-template-collection.js"></script>
|
||||||
<script src="/js/dom/panel-element.js"></script>
|
<script src="/js/dom/panel-element.js"></script>
|
||||||
<script src="/js/dom/popup-menu.js"></script>
|
<script src="/js/dom/popup-menu.js"></script>
|
||||||
|
Loading…
Reference in New Issue
Block a user