chore: use key property of KeyboardEvent

This commit is contained in:
Sam Potts 2022-04-18 22:32:52 +10:00
parent 1edec28d86
commit 3e35461e04
2 changed files with 81 additions and 86 deletions

19
src/js/controls.js vendored
View File

@ -404,7 +404,7 @@ const controls = {
'keydown keyup', 'keydown keyup',
(event) => { (event) => {
// We only care about space and ⬆️ ⬇️️ ➡️ // We only care about space and ⬆️ ⬇️️ ➡️
if (![32, 38, 39, 40].includes(event.which)) { if (!['Space', 'ArrowUp', 'ArrowDown', 'ArrowRight'].includes(event.key)) {
return; return;
} }
@ -420,13 +420,13 @@ const controls = {
const isRadioButton = matches(menuItem, '[role="menuitemradio"]'); const isRadioButton = matches(menuItem, '[role="menuitemradio"]');
// Show the respective menu // Show the respective menu
if (!isRadioButton && [32, 39].includes(event.which)) { if (!isRadioButton && ['Space', 'ArrowRight'].includes(event.key)) {
controls.showMenuPanel.call(this, type, true); controls.showMenuPanel.call(this, type, true);
} else { } else {
let target; let target;
if (event.which !== 32) { if (event.key !== 'Space') {
if (event.which === 40 || (isRadioButton && event.which === 39)) { if (event.key === 'ArrowDown' || (isRadioButton && event.key === 'ArrowRight')) {
target = menuItem.nextElementSibling; target = menuItem.nextElementSibling;
if (!is.element(target)) { if (!is.element(target)) {
@ -450,9 +450,7 @@ const controls = {
// Enter will fire a `click` event but we still need to manage focus // Enter will fire a `click` event but we still need to manage focus
// So we bind to keyup which fires after and set focus here // So we bind to keyup which fires after and set focus here
on.call(this, menuItem, 'keyup', (event) => { on.call(this, menuItem, 'keyup', (event) => {
if (event.which !== 13) { if (event.key !== 'Return') return;
return;
}
controls.focusFirstMenuItem.call(this, null, true); controls.focusFirstMenuItem.call(this, null, true);
}); });
@ -506,7 +504,7 @@ const controls = {
menuItem, menuItem,
'click keyup', 'click keyup',
(event) => { (event) => {
if (is.keyboardEvent(event) && event.which !== 32) { if (is.keyboardEvent(event) && event.key !== 'Space') {
return; return;
} }
@ -1139,7 +1137,7 @@ const controls = {
if (is.boolean(input)) { if (is.boolean(input)) {
show = input; show = input;
} else if (is.keyboardEvent(input) && input.which === 27) { } else if (is.keyboardEvent(input) && input.key === 'Escape') {
show = false; show = false;
} else if (is.event(input)) { } else if (is.event(input)) {
// If Plyr is in a shadowDOM, the event target is set to the component, instead of the // If Plyr is in a shadowDOM, the event target is set to the component, instead of the
@ -1527,8 +1525,7 @@ const controls = {
pane, pane,
'keydown', 'keydown',
(event) => { (event) => {
// We only care about <- if (event.key !== 'ArrowLeft') {
if (event.which !== 37) {
return; return;
} }

View File

@ -29,25 +29,25 @@ class Listeners {
handleKey(event) { handleKey(event) {
const { player } = this; const { player } = this;
const { elements } = player; const { elements } = player;
const code = event.keyCode ? event.keyCode : event.which; const { key, type, altKey, ctrlKey, metaKey, shiftKey } = event;
const pressed = event.type === 'keydown'; const pressed = type === 'keydown';
const repeat = pressed && code === this.lastKey; const repeat = pressed && key === this.lastKey;
// Bail if a modifier key is set // Bail if a modifier key is set
if (event.altKey || event.ctrlKey || event.metaKey || event.shiftKey) { if (altKey || ctrlKey || metaKey || shiftKey) {
return; return;
} }
// If the event is bubbled from the media element // If the event is bubbled from the media element
// Firefox doesn't get the keycode for whatever reason // Firefox doesn't get the key for whatever reason
if (!is.number(code)) { if (!key) {
return; return;
} }
// Seek by the number keys // Seek by increment
const seekByKey = () => { const seekByIncrement = (increment) => {
// Divide the max duration into 10th's and times by the number value // Divide the max duration into 10th's and times by the number value
player.currentTime = (player.duration / 10) * (code - 48); player.currentTime = (player.duration / 10) * increment;
}; };
// Handle the key on keydown // Handle the key on keydown
@ -65,113 +65,114 @@ class Listeners {
return; return;
} }
if (event.which === 32 && matches(focused, 'button, [role^="menuitem"]')) { if (event.key === 'Space' && matches(focused, 'button, [role^="menuitem"]')) {
return; return;
} }
} }
// Which keycodes should we prevent default // Which keys should we prevent default
const preventDefault = [32, 37, 38, 39, 40, 48, 49, 50, 51, 52, 53, 54, 56, 57, 67, 70, 73, 75, 76, 77, 79]; const preventDefault = [
'Space',
'ArrowLeft',
'ArrowUp',
'ArrowRight',
'ArrowDown',
// If the code is found prevent default (e.g. prevent scrolling for arrows) '0',
if (preventDefault.includes(code)) { '1',
'2',
'3',
'4',
'5',
'6',
'7',
'8',
'9',
'c',
'f',
'k',
'l',
'm',
];
// If the key is found prevent default (e.g. prevent scrolling for arrows)
if (preventDefault.includes(key)) {
event.preventDefault(); event.preventDefault();
event.stopPropagation(); event.stopPropagation();
} }
switch (code) { switch (key) {
case 48: case '0':
case 49: case '1':
case 50: case '2':
case 51: case '3':
case 52: case '4':
case 53: case '5':
case 54: case '6':
case 55: case '7':
case 56: case '8':
case 57: case '9':
// 0-9
if (!repeat) { if (!repeat) {
seekByKey(); seekByIncrement(parseInt(key, 10));
} }
break; break;
case 32: case 'Space':
case 75: case 'k':
// Space and K key
if (!repeat) { if (!repeat) {
silencePromise(player.togglePlay()); silencePromise(player.togglePlay());
} }
break; break;
case 38: case 'ArrowUp':
// Arrow up
player.increaseVolume(0.1); player.increaseVolume(0.1);
break; break;
case 40: case 'ArrowDown':
// Arrow down
player.decreaseVolume(0.1); player.decreaseVolume(0.1);
break; break;
case 77: case 'm':
// M key
if (!repeat) { if (!repeat) {
player.muted = !player.muted; player.muted = !player.muted;
} }
break; break;
case 39: case 'ArrowRight':
// Arrow forward
player.forward(); player.forward();
break; break;
case 37: case 'ArrowLeft':
// Arrow back
player.rewind(); player.rewind();
break; break;
case 70: case 'f':
// F key
player.fullscreen.toggle(); player.fullscreen.toggle();
break; break;
case 67: case 'c':
// C key
if (!repeat) { if (!repeat) {
player.toggleCaptions(); player.toggleCaptions();
} }
break; break;
case 76: case 'l':
// L key
player.loop = !player.loop; player.loop = !player.loop;
break; break;
/* case 73:
this.setLoop('start');
break;
case 76:
this.setLoop();
break;
case 79:
this.setLoop('end');
break; */
default: default:
break; break;
} }
// Escape is handle natively when in full screen // Escape is handle natively when in full screen
// So we only need to worry about non native // So we only need to worry about non native
if (code === 27 && !player.fullscreen.usingNative && player.fullscreen.active) { if (key === 'Escape' && !player.fullscreen.usingNative && player.fullscreen.active) {
player.fullscreen.toggle(); player.fullscreen.toggle();
} }
// Store last code for next cycle // Store last key for next cycle
this.lastKey = code; this.lastKey = key;
} else { } else {
this.lastKey = null; this.lastKey = null;
} }
@ -196,17 +197,18 @@ class Listeners {
setTabFocus = (event) => { setTabFocus = (event) => {
const { player } = this; const { player } = this;
const { elements } = player; const { elements } = player;
const { key, type, timeStamp } = event;
clearTimeout(this.focusTimer); clearTimeout(this.focusTimer);
// Ignore any key other than tab // Ignore any key other than tab
if (event.type === 'keydown' && event.which !== 9) { if (type === 'keydown' && key !== 'Tab') {
return; return;
} }
// Store reference to event timeStamp // Store reference to event timeStamp
if (event.type === 'keydown') { if (type === 'keydown') {
this.lastKeyDown = event.timeStamp; this.lastKeyDown = timeStamp;
} }
// Remove current classes // Remove current classes
@ -217,10 +219,10 @@ class Listeners {
}; };
// Determine if a key was pressed to trigger this event // Determine if a key was pressed to trigger this event
const wasKeyDown = event.timeStamp - this.lastKeyDown <= 20; const wasKeyDown = timeStamp - this.lastKeyDown <= 20;
// Ignore focus events if a key was pressed prior // Ignore focus events if a key was pressed prior
if (event.type === 'focus' && !wasKeyDown) { if (type === 'focus' && !wasKeyDown) {
return; return;
} }
@ -229,7 +231,7 @@ class Listeners {
// Delay the adding of classname until the focus has changed // Delay the adding of classname until the focus has changed
// This event fires before the focusin event // This event fires before the focusin event
if (event.type !== 'focusout') { if (type !== 'focusout') {
this.focusTimer = setTimeout(() => { this.focusTimer = setTimeout(() => {
const focused = document.activeElement; const focused = document.activeElement;
@ -661,15 +663,12 @@ class Listeners {
elements.buttons.settings, elements.buttons.settings,
'keyup', 'keyup',
(event) => { (event) => {
const code = event.which; if (!['Space', 'Enter'].includes(event.key)) {
// We only care about space and return
if (![13, 32].includes(code)) {
return; return;
} }
// Because return triggers a click anyway, all we need to do is set focus // Because return triggers a click anyway, all we need to do is set focus
if (code === 13) { if (event.key === 'Enter') {
controls.focusFirstMenuItem.call(player, null, true); controls.focusFirstMenuItem.call(player, null, true);
return; return;
} }
@ -689,7 +688,7 @@ class Listeners {
// Escape closes menu // Escape closes menu
this.bind(elements.settings.menu, 'keydown', (event) => { this.bind(elements.settings.menu, 'keydown', (event) => {
if (event.which === 27) { if (event.key === 'Escape') {
controls.toggleMenu.call(player, event); controls.toggleMenu.call(player, event);
} }
}); });
@ -704,10 +703,9 @@ class Listeners {
// Pause while seeking // Pause while seeking
this.bind(elements.inputs.seek, 'mousedown mouseup keydown keyup touchstart touchend', (event) => { this.bind(elements.inputs.seek, 'mousedown mouseup keydown keyup touchstart touchend', (event) => {
const seek = event.currentTarget; const seek = event.currentTarget;
const code = event.keyCode ? event.keyCode : event.which;
const attribute = 'play-on-seeked'; const attribute = 'play-on-seeked';
if (is.keyboardEvent(event) && code !== 39 && code !== 37) { if (is.keyboardEvent(event) && !['ArrowLeft', 'ArrowRight'].includes(event.key)) {
return; return;
} }