use event.key, available since Chrome 51

This commit is contained in:
tophf 2020-10-13 10:42:36 +03:00
parent 130b011940
commit 1ebf2aa8a2
9 changed files with 75 additions and 106 deletions

View File

@ -408,7 +408,7 @@ function showHelp(title = '', body) {
!event || !event ||
event.type === 'click' || event.type === 'click' ||
( (
event.which === 27 && event.key === 'Escape' &&
!event.altKey && !event.ctrlKey && !event.shiftKey && !event.metaKey && !event.altKey && !event.ctrlKey && !event.shiftKey && !event.metaKey &&
!$('.CodeMirror-hints, #message-box') && !$('.CodeMirror-hints, #message-box') &&
( (
@ -469,7 +469,7 @@ function showCodeMirrorPopup(title, html, options) {
popup.style.pointerEvents = 'auto'; popup.style.pointerEvents = 'auto';
const onKeyDown = event => { const onKeyDown = event => {
if (event.which === 9 && !event.ctrlKey && !event.altKey && !event.metaKey) { if (event.key === 'Tab' && !event.ctrlKey && !event.altKey && !event.metaKey) {
const search = $('#search-replace-dialog'); const search = $('#search-replace-dialog');
const area = search && search.contains(document.activeElement) ? search : popup; const area = search && search.contains(document.activeElement) ? search : popup;
moveFocus(area, event.shiftKey ? -1 : 1); moveFocus(area, event.shiftKey ? -1 : 1);

View File

@ -206,36 +206,32 @@ function createSection({
} }
function handleKeydown(cm, event) { function handleKeydown(cm, event) {
const key = event.which; if (event.shiftKey || event.altKey || event.metaKey) {
if (key < 37 || key > 40 || event.shiftKey || event.altKey || event.metaKey) {
return; return;
} }
const {key} = event;
const {line, ch} = cm.getCursor(); const {line, ch} = cm.getCursor();
switch (key) { switch (key) {
case 37: case 'ArrowLeft':
// arrow Left
if (line || ch) { if (line || ch) {
return; return;
} }
// fallthrough to arrow Up // fallthrough
case 38: case 'ArrowUp':
// arrow Up
cm = line === 0 && prevEditor(cm, false); cm = line === 0 && prevEditor(cm, false);
if (!cm) { if (!cm) {
return; return;
} }
event.preventDefault(); event.preventDefault();
event.stopPropagation(); event.stopPropagation();
cm.setCursor(cm.doc.size - 1, key === 37 ? 1e20 : ch); cm.setCursor(cm.doc.size - 1, key === 'ArrowLeft' ? 1e20 : ch);
break; break;
case 39: case 'ArrowRight':
// arrow Right
if (line < cm.doc.size - 1 || ch < cm.getLine(line).length - 1) { if (line < cm.doc.size - 1 || ch < cm.getLine(line).length - 1) {
return; return;
} }
// fallthrough to arrow Down // fallthrough
case 40: case 'ArrowDown':
// arrow Down
cm = line === cm.doc.size - 1 && nextEditor(cm, false); cm = line === cm.doc.size - 1 && nextEditor(cm, false);
if (!cm) { if (!cm) {
return; return;
@ -245,13 +241,6 @@ function createSection({
cm.setCursor(0, 0); cm.setCursor(0, 0);
break; break;
} }
// FIXME: what is this?
// const animation = (cm.getSection().firstElementChild.getAnimations() || [])[0];
// if (animation) {
// animation.playbackRate = -1;
// animation.currentTime = 2000;
// animation.play();
// }
} }
function showAppliesToHelp(event) { function showAppliesToHelp(event) {

View File

@ -20,6 +20,9 @@ for (const type of [NodeList, NamedNodeMap, HTMLCollection, HTMLAllCollection])
} }
} }
$.isTextLikeInput = el =>
el.localName === 'input' && /^(text|search|number)$/.test(el.type);
$.remove = (selector, base = document) => { $.remove = (selector, base = document) => {
const el = selector && typeof selector === 'string' ? $(selector, base) : selector; const el = selector && typeof selector === 'string' ? $(selector, base) : selector;
if (el) { if (el) {
@ -354,10 +357,10 @@ function focusAccessibility() {
]; ];
// try to find a focusable parent for this many parentElement jumps: // try to find a focusable parent for this many parentElement jumps:
const GIVE_UP_DEPTH = 4; const GIVE_UP_DEPTH = 4;
const isOutlineAllowed = ({localName, type}) =>
!focusAccessibility.ELEMENTS.includes(localName) ||
// allow outline on text/search inputs in addition to textareas // allow outline on text/search inputs in addition to textareas
localName === 'input' && /^(text|search|number)$/.test(type); const isOutlineAllowed = el =>
!focusAccessibility.ELEMENTS.includes(el.localName) ||
$.isTextLikeInput(el);
addEventListener('mousedown', suppressOutlineOnClick, {passive: true}); addEventListener('mousedown', suppressOutlineOnClick, {passive: true});
addEventListener('keydown', keepOutlineOnTab, {passive: true}); addEventListener('keydown', keepOutlineOnTab, {passive: true});
@ -375,7 +378,7 @@ function focusAccessibility() {
} }
function keepOutlineOnTab(event) { function keepOutlineOnTab(event) {
if (event.which === 9) { if (event.key === 'Tab') {
focusAccessibility.lastFocusedViaClick = false; focusAccessibility.lastFocusedViaClick = false;
setTimeout(keepOutlineOnTab, 0, true); setTimeout(keepOutlineOnTab, 0, true);
return; return;

View File

@ -24,12 +24,12 @@ onDOMready().then(() => {
document.body.appendChild(input); document.body.appendChild(input);
window.addEventListener('keydown', maybeRefocus, true); window.addEventListener('keydown', maybeRefocus, true);
function incrementalSearch({which}, immediately) { function incrementalSearch({key}, immediately) {
if (!immediately) { if (!immediately) {
debounce(incrementalSearch, 100, {}, true); debounce(incrementalSearch, 100, {}, true);
return; return;
} }
const direction = which === 38 ? -1 : which === 40 ? 1 : 0; const direction = key === 'ArrowUp' ? -1 : key === 'ArrowDown' ? 1 : 0;
const text = input.value.toLocaleLowerCase(); const text = input.value.toLocaleLowerCase();
if (!text.trim() || !direction && (text === prevText || focusedName.startsWith(text))) { if (!text.trim() || !direction && (text === prevText || focusedName.startsWith(text))) {
prevText = text; prevText = text;
@ -76,40 +76,31 @@ onDOMready().then(() => {
if (event.altKey || event.metaKey || $('#message-box')) { if (event.altKey || event.metaKey || $('#message-box')) {
return; return;
} }
const inTextInput = event.target.matches('[type=text], [type=search], [type=number]'); const inTextInput = $.isTextLikeInput(event.target);
const {which: k, key} = event; const {key, code, ctrlKey: ctrl} = event;
// `code` is independent of the current keyboard language
if ((code === 'KeyF' && ctrl && !event.shiftKey) ||
(code === 'Slash' || key === '/') && !ctrl && !inTextInput) {
// focus search field on "/" or Ctrl-F key // focus search field on "/" or Ctrl-F key
if (event.ctrlKey
? (event.code === 'KeyF' || !event.code && k === 70) && !event.shiftKey
: (key === '/' || !key && k === 191 && !event.shiftKey) && !inTextInput) {
event.preventDefault(); event.preventDefault();
$('#search').focus(); $('#search').focus();
return; return;
} }
if (event.ctrlKey || inTextInput) { if (ctrl || inTextInput) {
return; return;
} }
const time = performance.now(); const time = performance.now();
if ( if (key.length === 1) {
// 0-9
k >= 48 && k <= 57 ||
// a-z
k >= 65 && k <= 90 ||
// numpad keys
k >= 96 && k <= 111 ||
// marks
k >= 186
) {
input.focus(); input.focus();
if (time - prevTime > 1000) { if (time - prevTime > 1000) {
input.value = ''; input.value = '';
} }
prevTime = time; prevTime = time;
} else } else
if (k === 13 && focusedLink) { if (key === 'Enter' && focusedLink) {
focusedLink.dispatchEvent(new MouseEvent('click', {bubbles: true})); focusedLink.dispatchEvent(new MouseEvent('click', {bubbles: true}));
} else } else
if ((k === 38 || k === 40) && !event.shiftKey && if ((key === 'ArrowUp' || key === 'ArrowDown') && !event.shiftKey &&
time - prevTime < 5000 && incrementalSearch(event, true)) { time - prevTime < 5000 && incrementalSearch(event, true)) {
prevTime = time; prevTime = time;
} else } else

View File

@ -62,28 +62,28 @@ function messageBox({
resolveWith({button: this.buttonIndex}); resolveWith({button: this.buttonIndex});
}, },
key(event) { key(event) {
const {which, shiftKey, ctrlKey, altKey, metaKey, target} = event; const {key, shiftKey, ctrlKey, altKey, metaKey, target} = event;
if (shiftKey && which !== 9 || ctrlKey || altKey || metaKey) { if (shiftKey && key !== 'Tab' || ctrlKey || altKey || metaKey) {
return; return;
} }
switch (which) { switch (key) {
case 13: case 'Enter':
if (target.closest(focusAccessibility.ELEMENTS.join(','))) { if (target.closest(focusAccessibility.ELEMENTS.join(','))) {
return; return;
} }
break; break;
case 27: case 'Escape':
event.preventDefault(); event.preventDefault();
event.stopPropagation(); event.stopPropagation();
break; break;
case 9: case 'Tab':
moveFocus(messageBox.element, shiftKey ? -1 : 1); moveFocus(messageBox.element, shiftKey ? -1 : 1);
event.preventDefault(); event.preventDefault();
return; return;
default: default:
return; return;
} }
resolveWith(which === 13 ? {enter: true} : {esc: true}); resolveWith(key === 'Enter' ? {enter: true} : {esc: true});
}, },
scroll() { scroll() {
scrollTo(blockScroll.x, blockScroll.y); scrollTo(blockScroll.x, blockScroll.y);

View File

@ -298,7 +298,7 @@ function customizeHotkeys() {
} }
window.onkeydown = event => { window.onkeydown = event => {
if (event.keyCode === 27) { if (event.key === 'Escape') {
top.dispatchEvent(new CustomEvent('closeOptions')); top.dispatchEvent(new CustomEvent('closeOptions'));
} }
}; };

View File

@ -37,40 +37,27 @@ const hotkeys = (() => {
return; return;
} }
let entry; let entry;
const {which: k, key, code} = event; let {key, code, shiftKey} = event;
if (code.startsWith('Digit') || code.startsWith('Numpad') && code.length === 7) { if (key >= '0' && key <= '9') {
entry = entries[(Number(key) || 10) - 1];
} else if (code >= 'Digit0' && code <= 'Digit9') {
entry = entries[(Number(code.slice(-1)) || 10) - 1]; entry = entries[(Number(code.slice(-1)) || 10) - 1];
} else if (key === '`' || key === '*' || code === 'Backquote' || code === 'NumpadMultiply') {
} else if (
code === 'Backquote' || code === 'NumpadMultiply' ||
key && (key === '`' || key === '*') ||
k === 192 || k === 106) {
invertTogglables(); invertTogglables();
} else if (key === '-' || code === 'NumpadSubtract') {
} else if (
code === 'NumpadSubtract' ||
key && key === '-' ||
k === 109) {
toggleState(entries, 'enabled', false); toggleState(entries, 'enabled', false);
} else if (key === '+' || code === 'NumpadAdd') {
} else if (
code === 'NumpadAdd' ||
key && key === '+' ||
k === 107) {
toggleState(entries, 'disabled', true); toggleState(entries, 'disabled', true);
} else if (key.length === 1) {
} else if ( shiftKey = false; // typing ':' etc. needs Shift so we hide it here to avoid opening editor
// any single character key = key.toLocaleLowerCase();
key && key.length === 1 || entry = [...entries].find(e => e.innerText.toLocaleLowerCase().startsWith(key));
k >= 65 && k <= 90) {
const letter = new RegExp(key ? '^' + key : '^\\x' + k.toString(16), 'i');
entry = [...entries].find(entry => letter.test(entry.textContent));
} }
if (!entry) { if (!entry) {
return; return;
} }
const target = $(event.shiftKey ? '.style-edit-link' : '.checker', entry); const target = $(shiftKey ? '.style-edit-link' : '.checker', entry);
target.dispatchEvent(new MouseEvent('click', {cancelable: true})); target.dispatchEvent(new MouseEvent('click', {cancelable: true}));
} }

View File

@ -507,16 +507,15 @@ Object.assign(handleEvent, {
window.onkeydown = event => { window.onkeydown = event => {
const close = $('.menu-close', entry); const close = $('.menu-close', entry);
const checkbox = $('.exclude-by-domain-checkbox', entry); const checkbox = $('.exclude-by-domain-checkbox', entry);
const keyCode = event.keyCode || event.which; if (document.activeElement === close && (event.key === 'Tab') && !event.shiftKey) {
if (document.activeElement === close && (keyCode === 9) && !event.shiftKey) {
event.preventDefault(); event.preventDefault();
checkbox.focus(); checkbox.focus();
} }
if (document.activeElement === checkbox && (keyCode === 9) && event.shiftKey) { if (document.activeElement === checkbox && (event.key === 'Tab') && event.shiftKey) {
event.preventDefault(); event.preventDefault();
close.focus(); close.focus();
} }
if (keyCode === 27) { if (event.key === 'Escape') {
event.preventDefault(); event.preventDefault();
close.click(); close.click();
} }
@ -542,20 +541,20 @@ Object.assign(handleEvent, {
const close = $('.menu-close', entry); const close = $('.menu-close', entry);
const checkbox = $('.exclude-by-domain-checkbox', entry); const checkbox = $('.exclude-by-domain-checkbox', entry);
const confirmActive = $('#confirm[data-display="true"]'); const confirmActive = $('#confirm[data-display="true"]');
const keyCode = event.keyCode || event.which; const {key} = event;
if (document.activeElement === cancel && (keyCode === 9)) { if (document.activeElement === cancel && (key === 'Tab')) {
event.preventDefault(); event.preventDefault();
affirm.focus(); affirm.focus();
} }
if (document.activeElement === close && (keyCode === 9) && !event.shiftKey) { if (document.activeElement === close && (key === 'Tab') && !event.shiftKey) {
event.preventDefault(); event.preventDefault();
checkbox.focus(); checkbox.focus();
} }
if (document.activeElement === checkbox && (keyCode === 9) && event.shiftKey) { if (document.activeElement === checkbox && (key === 'Tab') && event.shiftKey) {
event.preventDefault(); event.preventDefault();
close.focus(); close.focus();
} }
if (keyCode === 27) { if (key === 'Escape') {
event.preventDefault(); event.preventDefault();
if (confirmActive) { if (confirmActive) {
box.dataset.display = false; box.dataset.display = false;

View File

@ -355,29 +355,29 @@
} }
function setFromKeyboard(event) { function setFromKeyboard(event) {
const {which, ctrlKey: ctrl, altKey: alt, shiftKey: shift, metaKey: meta} = event; const {key, ctrlKey: ctrl, altKey: alt, shiftKey: shift, metaKey: meta} = event;
switch (which) { switch (key) {
case 9: // Tab case 'Tab':
case 33: // PgUp case 'PageUp':
case 34: // PgDn case 'PageDown':
if (!ctrl && !alt && !meta) { if (!ctrl && !alt && !meta) {
const el = document.activeElement; const el = document.activeElement;
const inputs = $inputs[currentFormat]; const inputs = $inputs[currentFormat];
const lastInput = inputs[inputs.length - 1]; const lastInput = inputs[inputs.length - 1];
if (which === 9 && shift && el === inputs[0]) { if (key === 'Tab' && shift && el === inputs[0]) {
maybeFocus(lastInput); maybeFocus(lastInput);
} else if (which === 9 && !shift && el === lastInput) { } else if (key === 'Tab' && !shift && el === lastInput) {
maybeFocus(inputs[0]); maybeFocus(inputs[0]);
} else if (which !== 9 && !shift) { } else if (key !== 'Tab' && !shift) {
setFromFormatElement({shift: which === 33 || shift}); setFromFormatElement({shift: key === 'PageUp' || shift});
} else { } else {
return; return;
} }
event.preventDefault(); event.preventDefault();
} }
return; return;
case 38: // Up case 'ArrowUp':
case 40: // Down case 'ArrowDown':
if (!event.metaKey && if (!event.metaKey &&
document.activeElement.localName === 'input' && document.activeElement.localName === 'input' &&
document.activeElement.checkValidity()) { document.activeElement.checkValidity()) {
@ -389,8 +389,8 @@
function setFromKeyboardIncrement(event) { function setFromKeyboardIncrement(event) {
const el = document.activeElement; const el = document.activeElement;
const {which, ctrlKey: ctrl, altKey: alt, shiftKey: shift} = event; const {key, ctrlKey: ctrl, altKey: alt, shiftKey: shift} = event;
const dir = which === 38 ? 1 : -1; const dir = key === 'ArrowUp' ? 1 : -1;
let value, newValue; let value, newValue;
if (currentFormat === 'hex') { if (currentFormat === 'hex') {
value = el.value.trim(); value = el.value.trim();
@ -617,9 +617,9 @@
function onKeyDown(e) { function onKeyDown(e) {
if (!e.shiftKey && !e.ctrlKey && !e.altKey && !e.metaKey) { if (!e.shiftKey && !e.ctrlKey && !e.altKey && !e.metaKey) {
switch (e.which) { switch (e.key) {
case 13: case 'Enter':
case 27: case 'Escape':
e.preventDefault(); e.preventDefault();
e.stopPropagation(); e.stopPropagation();
hide(); hide();