From 567da0f09bf59ab30c071782aefbfde8ce1e2298 Mon Sep 17 00:00:00 2001 From: Mason Ballengee Date: Fri, 22 Dec 2023 13:47:00 -0500 Subject: [PATCH] Use listener for hotkey support instead of VideoJS hotkeys --- src/components/MediaPlayer/MediaPlayer.js | 77 +---------------- .../MediaPlayer/VideoJS/VideoJSPlayer.js | 9 +- src/services/utility-helpers.js | 83 +++++++++++++++++++ 3 files changed, 89 insertions(+), 80 deletions(-) diff --git a/src/components/MediaPlayer/MediaPlayer.js b/src/components/MediaPlayer/MediaPlayer.js index 1eeef056..d8669e42 100644 --- a/src/components/MediaPlayer/MediaPlayer.js +++ b/src/components/MediaPlayer/MediaPlayer.js @@ -93,7 +93,7 @@ const MediaPlayer = ({ enableFileDownload = false, enablePIP = false }) => { clearCanvasMessageTimer(); } else { // Create a timer to advance to the next Canvas when autoplay is turned - // on when inaccessible message is been displayed + // on when inaccessible message is been displayed createCanvasMessageTimer(); } } @@ -102,7 +102,7 @@ const MediaPlayer = ({ enableFileDownload = false, enablePIP = false }) => { /** * Initialize the next Canvas to be viewed in the player instance * @param {Number} canvasId index of the Canvas to be loaded into the player - * @param {Boolean} fromStart flag to indicate how to start new player instance + * @param {Boolean} fromStart flag to indicate how to start new player instance */ const initCanvas = (canvasId, fromStart) => { clearCanvasMessageTimer(); @@ -256,7 +256,7 @@ const MediaPlayer = ({ enableFileDownload = false, enablePIP = false }) => { * Switch player when navigating across canvases * @param {Number} index canvas index to be loaded into the player * @param {Boolean} fromStart flag to indicate set player start time to zero or not - * @param {String} focusElement element to be focused within the player when using + * @param {String} focusElement element to be focused within the player when using * next or previous buttons with keyboard */ const switchPlayer = (index, fromStart, focusElement = '') => { @@ -319,77 +319,6 @@ const MediaPlayer = ({ enableFileDownload = false, enablePIP = false }) => { ? playerConfig.sources[srcIndex] : playerConfig.sources, tracks: playerConfig.tracks, - userActions: { - hotkeys: function (event) { - // event.which key code values found at: https://css-tricks.com/snippets/javascript/javascript-keycodes/ - - // Space and k toggle play/pause - if (event.which === 32 || event.which === 75) { - // Prevent default browser actions so that page does not react when hotkeys are used. - // e.g. pressing space will pause/play without scrolling the page down. - event.preventDefault(); - - if (this.paused()) { - this.play(); - } else { - this.pause(); - } - } - - // Adapted from https://github.com/videojs/video.js/blob/bad086dad68d3ff16dbe12e434c15e1ee7ac2875/src/js/control-bar/mute-toggle.js#L56 - // m toggles mute - if (event.which === 77) { - event.preventDefault(); - const vol = this.volume(); - const lastVolume = this.lastVolume_(); - - if (vol === 0) { - const volumeToSet = lastVolume < 0.1 ? 0.1 : lastVolume; - - this.volume(volumeToSet); - this.muted(false); - } else { - this.muted(this.muted() ? false : true); - } - } - - // f toggles fullscreen - // Fullscreen should only be available for videos - if (event.which === 70 && !this.isAudio()) { - event.preventDefault(); - - if (!this.isFullscreen()) { - this.requestFullscreen(); - } else { - this.exitFullscreen(); - } - } - - // Right arrow seeks 5 seconds ahead - if (event.which === 39) { - event.preventDefault(); - this.currentTime(this.currentTime() + 5); - } - - // Left arrow seeks 5 seconds back - if (event.which === 37) { - event.preventDefault(); - this.currentTime(this.currentTime() - 5); - } - - // Up arrow raises volume by 0.1 - if (event.which === 38) { - event.preventDefault(); - this.volume(this.volume() + 0.1); - } - - // Down arrow lowers volume by 0.1 - if (event.which === 40) { - event.preventDefault(); - this.volume(this.volume() - 0.1); - } - } - }, // Omit captions in the HLS manifest from loading html5: { nativeTextTracks: true, diff --git a/src/components/MediaPlayer/VideoJS/VideoJSPlayer.js b/src/components/MediaPlayer/VideoJS/VideoJSPlayer.js index 8cdb1960..07d3f2b4 100644 --- a/src/components/MediaPlayer/VideoJS/VideoJSPlayer.js +++ b/src/components/MediaPlayer/VideoJS/VideoJSPlayer.js @@ -19,7 +19,7 @@ import { getCanvasId, getCanvasIndex, } from '@Services/iiif-parser'; -import { checkSrcRange, getMediaFragment } from '@Services/utility-helpers'; +import { checkSrcRange, getMediaFragment, playerHotKeys } from '@Services/utility-helpers'; /** VideoJS custom components */ import VideoJSProgress from './components/js/VideoJSProgress'; @@ -153,6 +153,7 @@ function VideoJSPlayer({ return () => { if (currentPlayerRef.current != null) { currentPlayerRef.current.dispose(); + document.removeEventListener('keydown', playerHotKeys); setMounted(false); setIsReady(false); } @@ -168,11 +169,6 @@ function VideoJSPlayer({ player.on('ready', function () { console.log('Player ready'); - // Focus the player for hotkeys to work - if (playerFocusElement == '') { - player.focus(); - } - // Add class for volume panel in audio player to make it always visible if (!isVideo) { player.getChild('controlBar').getChild('VolumePanel').addClass('vjs-slider-active'); @@ -272,6 +268,7 @@ function VideoJSPlayer({ player.on('timeupdate', () => { handleTimeUpdate(); }); + document.addEventListener('keydown', playerHotKeys); } }, [player]); diff --git a/src/services/utility-helpers.js b/src/services/utility-helpers.js index 037b43e3..3b38052c 100644 --- a/src/services/utility-helpers.js +++ b/src/services/utility-helpers.js @@ -468,3 +468,86 @@ export function autoScroll(currentItem, containerRef) { containerRef.current.scrollTop = scrollHeight > inViewHeight ? scrollHeight - containerRef.current.clientHeight / 2 : 0; }; + +export function playerHotKeys() { + let player = document.getElementById('iiif-media-player'); + let playerInst = player?.player; + var inputs = ['input', 'textarea']; + var activeElement = document.activeElement; + + /** Trigger player hotkeys when focus is not on an input, textarea, or navigation tab */ + if(activeElement && (inputs.indexOf(activeElement.tagName.toLowerCase()) !== -1 || activeElement.role === "tab")) { + return; + } else { + var pressedKey = event.which + // event.which key code values found at: https://css-tricks.com/snippets/javascript/javascript-keycodes/ + switch(pressedKey) { + // Space and k toggle play/pause + case 32: + case 75: + // Prevent default browser actions so that page does not react when hotkeys are used. + // e.g. pressing space will pause/play without scrolling the page down. + event.preventDefault(); + if (playerInst.paused()) { + playerInst.play(); + } else { + playerInst.pause(); + } + break; + // f toggles fullscreen + case 70: + event.preventDefault(); + // Fullscreen should only be available for videos + if (!playerInst.isAudio()) { + if (!playerInst.isFullscreen()) { + playerInst.requestFullscreen(); + } else { + playerInst.exitFullscreen(); + } + } + break; + // Adapted from https://github.com/videojs/video.js/blob/bad086dad68d3ff16dbe12e434c15e1ee7ac2875/src/js/control-bar/mute-toggle.js#L56 + // m toggles mute + case 77: + event.preventDefault(); + + const vol = playerInst.volume(); + const lastVolume = playerInst.lastVolume_(); + + if (vol === 0) { + const volumeToSet = lastVolume < 0.1 ? 0.1 : lastVolume; + + playerInst.volume(volumeToSet); + playerInst.muted(false); + } else { + playerInst.muted(playerInst.muted() ? false : true); + } + break; + // Left arrow seeks 5 seconds back + case 37: + event.preventDefault(); + playerInst.currentTime(playerInst.currentTime() - 5); + break; + // Right arrow seeks 5 seconds ahead + case 39: + event.preventDefault(); + playerInst.currentTime(playerInst.currentTime() + 5); + break; + // Up arrow raises volume by 0.1 + case 38: + event.preventDefault(); + if (playerInst.muted()) { + playerInst.muted(false) + } + playerInst.volume(playerInst.volume() + 0.1); + break; + // Down arrow lowers volume by 0.1 + case 40: + event.preventDefault(); + playerInst.volume(playerInst.volume() - 0.1); + break; + default: + return; + } + } +}