From 97f4df3807a6ca34f3972f508c23ea4ce11eed51 Mon Sep 17 00:00:00 2001 From: Oliver Foster Date: Mon, 30 Sep 2024 14:27:35 +0100 Subject: [PATCH 1/2] fix client side library loading --- js/mediaLibrariesOverrides.js | 192 +++++++++++++++++----------------- js/mediaView.js | 25 +++-- 2 files changed, 113 insertions(+), 104 deletions(-) diff --git a/js/mediaLibrariesOverrides.js b/js/mediaLibrariesOverrides.js index a5017f5..6a8547c 100644 --- a/js/mediaLibrariesOverrides.js +++ b/js/mediaLibrariesOverrides.js @@ -1,125 +1,129 @@ import Adapt from 'core/js/adapt'; import device from 'core/js/device'; -import 'libraries/mediaelement-and-player'; -// /* -// * Default shortcut keys trap a screen reader user inside the player once in focus. These keys are unnecessary -// * as one may traverse the player in a linear fashion without needing to know or use shortcut keys. Below is -// * the removal of the default shortcut keys. -// * -// * The default seek interval functions are passed two different data types from mejs which they handle incorrectly. One -// * is a duration integer the other is the player object. The default functions error on slider key press and so break -// * accessibility. Below is a correction. -// */ +// wait for window.mejs to load +import('libraries/mediaelement-and-player') + .then(() => { + // /* + // * Default shortcut keys trap a screen reader user inside the player once in focus. These keys are unnecessary + // * as one may traverse the player in a linear fashion without needing to know or use shortcut keys. Below is + // * the removal of the default shortcut keys. + // * + // * The default seek interval functions are passed two different data types from mejs which they handle incorrectly. One + // * is a duration integer the other is the player object. The default functions error on slider key press and so break + // * accessibility. Below is a correction. + // */ -// Object.assign(window.mejs.MepDefaults, { -// keyActions: [], -// defaultSeekForwardInterval: duration => { -// if (typeof duration === 'object') return duration.duration * 0.05; -// return duration * 0.05; -// }, -// defaultSeekBackwardInterval: duration => { -// if (typeof duration === 'object') return duration.duration * 0.05; -// return duration * 0.05; -// } -// }); + // Object.assign(window.mejs.MepDefaults, { + // keyActions: [], + // defaultSeekForwardInterval: duration => { + // if (typeof duration === 'object') return duration.duration * 0.05; + // return duration * 0.05; + // }, + // defaultSeekBackwardInterval: duration => { + // if (typeof duration === 'object') return duration.duration * 0.05; + // return duration * 0.05; + // } + // }); -/** + /** * Fix for firefox fullscreen api * https://github.com/adaptlearning/adapt-contrib-media/issues/239 */ -const features = window.mejs.Features; -if (features.hasMozNativeFullScreen) { - const original = document.mozCancelFullScreen.bind(document); - document.mozCancelFullScreen = () => { - if (!document.mozFullScreenElement) return; - original(); - }; -} + const features = window.mejs.Features; + if (features.hasMozNativeFullScreen) { + const original = document.mozCancelFullScreen.bind(document); + document.mozCancelFullScreen = () => { + if (!document.mozFullScreenElement) return; + original(); + }; + } -/** + /** * Force the default language so that the aria-label can be localised from Adapt * Note: Do not change these, their names and values are required for mapping in mejs */ -window.mejs.i18n.lang = 'en-US'; -window.mejs.i18n['en-US'] = {}; -const ariaLabelMappings = { - playText: 'Play', - pauseText: 'Pause', - stopText: 'Stop', - audioPlayerText: 'Audio Player', - videoPlayerText: 'Video Player', - tracksText: 'Captions/Subtitles', - timeSliderText: 'Time Slider', - muteText: 'Mute Toggle', - unmuteStatusText: 'Unmute', - muteStatusText: 'Mute', - volumeSliderText: 'Volume Slider', - fullscreenText: 'Fullscreen', - goFullscreenText: 'Go Fullscreen', - turnOffFullscreenText: 'Turn off Fullscreen', - noneText: 'None', - skipBackText: 'Skip back %1 seconds', - allyVolumeControlText: 'Use Up/Down Arrow keys to increase or decrease volume.', - progessHelpText: 'Use Left/Right Arrow keys to advance one second, Up/Down arrows to advance ten seconds.' -}; + window.mejs.i18n.lang = 'en-US'; + window.mejs.i18n['en-US'] = {}; + const ariaLabelMappings = { + playText: 'Play', + pauseText: 'Pause', + stopText: 'Stop', + audioPlayerText: 'Audio Player', + videoPlayerText: 'Video Player', + tracksText: 'Captions/Subtitles', + timeSliderText: 'Time Slider', + muteText: 'Mute Toggle', + unmuteStatusText: 'Unmute', + muteStatusText: 'Mute', + volumeSliderText: 'Volume Slider', + fullscreenText: 'Fullscreen', + goFullscreenText: 'Go Fullscreen', + turnOffFullscreenText: 'Turn off Fullscreen', + noneText: 'None', + skipBackText: 'Skip back %1 seconds', + allyVolumeControlText: 'Use Up/Down Arrow keys to increase or decrease volume.', + progessHelpText: 'Use Left/Right Arrow keys to advance one second, Up/Down arrows to advance ten seconds.' + }; -Adapt.on('app:dataReady', () => { - // Populate the aria labels from the _global._components._media - const dynamicLabels = window.mejs.i18n['en-US']; - const fixedDefaults = window.mejs.MepDefaults; - const globals = Adapt.course.get('_globals')?._components?._media; - for (const k in ariaLabelMappings) { - dynamicLabels[ariaLabelMappings[k]] = globals[k] ?? ariaLabelMappings[k]; - fixedDefaults[k] = dynamicLabels[ariaLabelMappings[k]]; - } -}); + Adapt.on('app:dataReady', () => { + // Populate the aria labels from the _global._components._media + const dynamicLabels = window.mejs.i18n['en-US']; + const fixedDefaults = window.mejs.MepDefaults; + const globals = Adapt.course.get('_globals')?._components?._media; + for (const k in ariaLabelMappings) { + dynamicLabels[ariaLabelMappings[k]] = globals[k] ?? ariaLabelMappings[k]; + fixedDefaults[k] = dynamicLabels[ariaLabelMappings[k]]; + } + }); -/** + /** * Fullscreen hook * fixes a bug - https://github.com/adaptlearning/adapt_framework/issues/1478 * where the media player going into/coming out of full-screen mode would trigger inview on * components below it; we therefore need to switch off inview when entering full screen mode * and switch it back on again after exiting full screen mode */ -const mepPrototype = Object.assign({}, window.mejs.MediaElementPlayer.prototype); + const mepPrototype = Object.assign({}, window.mejs.MediaElementPlayer.prototype); -Object.assign(window.mejs.MediaElementPlayer.prototype, { - detectFullscreenMode() { - const vendorPrefix = this.getVendorPrefix(); - const fsEventName = 'on' + vendorPrefix + 'fullscreenchange'; + Object.assign(window.mejs.MediaElementPlayer.prototype, { + detectFullscreenMode() { + const vendorPrefix = this.getVendorPrefix(); + const fsEventName = 'on' + vendorPrefix + 'fullscreenchange'; - if (document[fsEventName] === null) { - document[fsEventName] = function fullScreenEventHandler() { + if (document[fsEventName] === null) { + document[fsEventName] = function fullScreenEventHandler() { - const elementName = (vendorPrefix === '' ? 'fullscreenElement' : vendorPrefix + 'FullscreenElement'); + const elementName = (vendorPrefix === '' ? 'fullscreenElement' : vendorPrefix + 'FullscreenElement'); - if (document[elementName] !== null) { - $.inview.lock('mediaelement'); - Adapt.trigger('media:fullscreen:enter'); - } else { - $.inview.unlock('mediaelement'); - Adapt.trigger('media:fullscreen:exit'); + if (document[elementName] !== null) { + $.inview.lock('mediaelement'); + Adapt.trigger('media:fullscreen:enter'); + } else { + $.inview.unlock('mediaelement'); + Adapt.trigger('media:fullscreen:exit'); + } + }; } - }; - } - return mepPrototype.detectFullscreenMode.apply(this, arguments); - }, + return mepPrototype.detectFullscreenMode.apply(this, arguments); + }, - /** + /** * because the fullscreen events and properties are still vendor-prefixed in some browsers... */ - getVendorPrefix() { - const browser = device.browser; + getVendorPrefix() { + const browser = device.browser; - if (browser === 'internet explorer') { - return 'ms'; - } + if (browser === 'internet explorer') { + return 'ms'; + } - if (browser === 'microsoft edge' || browser === 'safari') { - return 'webkit'; - } + if (browser === 'microsoft edge' || browser === 'safari') { + return 'webkit'; + } + + return ''; // Chrome, Opera and Firefox no longer require a vendor prefix + } + }); - return ''; // Chrome, Opera and Firefox no longer require a vendor prefix - } -}); + }); diff --git a/js/mediaView.js b/js/mediaView.js index 59a8247..32a33f5 100644 --- a/js/mediaView.js +++ b/js/mediaView.js @@ -1,20 +1,25 @@ import Adapt from 'core/js/adapt'; +import wait from 'core/js/wait'; import offlineStorage from 'core/js/offlineStorage'; import a11y from 'core/js/a11y'; // import device from 'core/js/device'; import logging from 'core/js/logging'; import ComponentView from 'core/js/views/componentView'; -import 'libraries/mediaelement-and-player'; import './mediaLibrariesOverrides'; -import('libraries/mediaelement-and-player') - .then(() => { - import('libraries/plugins/speed'); - import('libraries/plugins/speed-i18n'); - import('libraries/plugins/jump-forward'); - import('libraries/plugins/jump-forward-i18n'); - import('libraries/plugins/skip-back'); - import('libraries/plugins/skip-back-i18n'); - }); + +// instruct adapt to wait whilst loading client-side libraries +wait.for(async done => { + // wait for window.mejs to load + await import('libraries/mediaelement-and-player'); + // load plugins + import('libraries/plugins/speed'); + import('libraries/plugins/speed-i18n'); + import('libraries/plugins/jump-forward'); + import('libraries/plugins/jump-forward-i18n'); + import('libraries/plugins/skip-back'); + import('libraries/plugins/skip-back-i18n'); + done(); +}); class MediaView extends ComponentView { From 282d3bc9881030b2f475444f2aada7b683763235 Mon Sep 17 00:00:00 2001 From: Oliver Foster Date: Mon, 30 Sep 2024 14:29:06 +0100 Subject: [PATCH 2/2] Reversion --- js/mediaLibrariesOverrides.js | 196 +++++++++++++++++----------------- 1 file changed, 96 insertions(+), 100 deletions(-) diff --git a/js/mediaLibrariesOverrides.js b/js/mediaLibrariesOverrides.js index 6a8547c..acdeb5d 100644 --- a/js/mediaLibrariesOverrides.js +++ b/js/mediaLibrariesOverrides.js @@ -1,129 +1,125 @@ import Adapt from 'core/js/adapt'; import device from 'core/js/device'; +import 'libraries/mediaelement-and-player'; -// wait for window.mejs to load -import('libraries/mediaelement-and-player') - .then(() => { - // /* - // * Default shortcut keys trap a screen reader user inside the player once in focus. These keys are unnecessary - // * as one may traverse the player in a linear fashion without needing to know or use shortcut keys. Below is - // * the removal of the default shortcut keys. - // * - // * The default seek interval functions are passed two different data types from mejs which they handle incorrectly. One - // * is a duration integer the other is the player object. The default functions error on slider key press and so break - // * accessibility. Below is a correction. - // */ +// /* +// * Default shortcut keys trap a screen reader user inside the player once in focus. These keys are unnecessary +// * as one may traverse the player in a linear fashion without needing to know or use shortcut keys. Below is +// * the removal of the default shortcut keys. +// * +// * The default seek interval functions are passed two different data types from mejs which they handle incorrectly. One +// * is a duration integer the other is the player object. The default functions error on slider key press and so break +// * accessibility. Below is a correction. +// */ - // Object.assign(window.mejs.MepDefaults, { - // keyActions: [], - // defaultSeekForwardInterval: duration => { - // if (typeof duration === 'object') return duration.duration * 0.05; - // return duration * 0.05; - // }, - // defaultSeekBackwardInterval: duration => { - // if (typeof duration === 'object') return duration.duration * 0.05; - // return duration * 0.05; - // } - // }); +// Object.assign(window.mejs.MepDefaults, { +// keyActions: [], +// defaultSeekForwardInterval: duration => { +// if (typeof duration === 'object') return duration.duration * 0.05; +// return duration * 0.05; +// }, +// defaultSeekBackwardInterval: duration => { +// if (typeof duration === 'object') return duration.duration * 0.05; +// return duration * 0.05; +// } +// }); - /** +/** * Fix for firefox fullscreen api * https://github.com/adaptlearning/adapt-contrib-media/issues/239 */ - const features = window.mejs.Features; - if (features.hasMozNativeFullScreen) { - const original = document.mozCancelFullScreen.bind(document); - document.mozCancelFullScreen = () => { - if (!document.mozFullScreenElement) return; - original(); - }; - } +const features = window.mejs.Features; +if (features.hasMozNativeFullScreen) { + const original = document.mozCancelFullScreen.bind(document); + document.mozCancelFullScreen = () => { + if (!document.mozFullScreenElement) return; + original(); + }; +} - /** +/** * Force the default language so that the aria-label can be localised from Adapt * Note: Do not change these, their names and values are required for mapping in mejs */ - window.mejs.i18n.lang = 'en-US'; - window.mejs.i18n['en-US'] = {}; - const ariaLabelMappings = { - playText: 'Play', - pauseText: 'Pause', - stopText: 'Stop', - audioPlayerText: 'Audio Player', - videoPlayerText: 'Video Player', - tracksText: 'Captions/Subtitles', - timeSliderText: 'Time Slider', - muteText: 'Mute Toggle', - unmuteStatusText: 'Unmute', - muteStatusText: 'Mute', - volumeSliderText: 'Volume Slider', - fullscreenText: 'Fullscreen', - goFullscreenText: 'Go Fullscreen', - turnOffFullscreenText: 'Turn off Fullscreen', - noneText: 'None', - skipBackText: 'Skip back %1 seconds', - allyVolumeControlText: 'Use Up/Down Arrow keys to increase or decrease volume.', - progessHelpText: 'Use Left/Right Arrow keys to advance one second, Up/Down arrows to advance ten seconds.' - }; +window.mejs.i18n.lang = 'en-US'; +window.mejs.i18n['en-US'] = {}; +const ariaLabelMappings = { + playText: 'Play', + pauseText: 'Pause', + stopText: 'Stop', + audioPlayerText: 'Audio Player', + videoPlayerText: 'Video Player', + tracksText: 'Captions/Subtitles', + timeSliderText: 'Time Slider', + muteText: 'Mute Toggle', + unmuteStatusText: 'Unmute', + muteStatusText: 'Mute', + volumeSliderText: 'Volume Slider', + fullscreenText: 'Fullscreen', + goFullscreenText: 'Go Fullscreen', + turnOffFullscreenText: 'Turn off Fullscreen', + noneText: 'None', + skipBackText: 'Skip back %1 seconds', + allyVolumeControlText: 'Use Up/Down Arrow keys to increase or decrease volume.', + progessHelpText: 'Use Left/Right Arrow keys to advance one second, Up/Down arrows to advance ten seconds.' +}; - Adapt.on('app:dataReady', () => { - // Populate the aria labels from the _global._components._media - const dynamicLabels = window.mejs.i18n['en-US']; - const fixedDefaults = window.mejs.MepDefaults; - const globals = Adapt.course.get('_globals')?._components?._media; - for (const k in ariaLabelMappings) { - dynamicLabels[ariaLabelMappings[k]] = globals[k] ?? ariaLabelMappings[k]; - fixedDefaults[k] = dynamicLabels[ariaLabelMappings[k]]; - } - }); +Adapt.on('app:dataReady', () => { + // Populate the aria labels from the _global._components._media + const dynamicLabels = window.mejs.i18n['en-US']; + const fixedDefaults = window.mejs.MepDefaults; + const globals = Adapt.course.get('_globals')?._components?._media; + for (const k in ariaLabelMappings) { + dynamicLabels[ariaLabelMappings[k]] = globals[k] ?? ariaLabelMappings[k]; + fixedDefaults[k] = dynamicLabels[ariaLabelMappings[k]]; + } +}); - /** +/** * Fullscreen hook * fixes a bug - https://github.com/adaptlearning/adapt_framework/issues/1478 * where the media player going into/coming out of full-screen mode would trigger inview on * components below it; we therefore need to switch off inview when entering full screen mode * and switch it back on again after exiting full screen mode */ - const mepPrototype = Object.assign({}, window.mejs.MediaElementPlayer.prototype); +const mepPrototype = Object.assign({}, window.mejs.MediaElementPlayer.prototype); - Object.assign(window.mejs.MediaElementPlayer.prototype, { - detectFullscreenMode() { - const vendorPrefix = this.getVendorPrefix(); - const fsEventName = 'on' + vendorPrefix + 'fullscreenchange'; +Object.assign(window.mejs.MediaElementPlayer.prototype, { + detectFullscreenMode() { + const vendorPrefix = this.getVendorPrefix(); + const fsEventName = 'on' + vendorPrefix + 'fullscreenchange'; - if (document[fsEventName] === null) { - document[fsEventName] = function fullScreenEventHandler() { + if (document[fsEventName] === null) { + document[fsEventName] = function fullScreenEventHandler() { - const elementName = (vendorPrefix === '' ? 'fullscreenElement' : vendorPrefix + 'FullscreenElement'); + const elementName = (vendorPrefix === '' ? 'fullscreenElement' : vendorPrefix + 'FullscreenElement'); - if (document[elementName] !== null) { - $.inview.lock('mediaelement'); - Adapt.trigger('media:fullscreen:enter'); - } else { - $.inview.unlock('mediaelement'); - Adapt.trigger('media:fullscreen:exit'); - } - }; + if (document[elementName] !== null) { + $.inview.lock('mediaelement'); + Adapt.trigger('media:fullscreen:enter'); + } else { + $.inview.unlock('mediaelement'); + Adapt.trigger('media:fullscreen:exit'); } - return mepPrototype.detectFullscreenMode.apply(this, arguments); - }, + }; + } + return mepPrototype.detectFullscreenMode.apply(this, arguments); + }, - /** - * because the fullscreen events and properties are still vendor-prefixed in some browsers... - */ - getVendorPrefix() { - const browser = device.browser; + /** +* because the fullscreen events and properties are still vendor-prefixed in some browsers... +*/ + getVendorPrefix() { + const browser = device.browser; - if (browser === 'internet explorer') { - return 'ms'; - } - - if (browser === 'microsoft edge' || browser === 'safari') { - return 'webkit'; - } + if (browser === 'internet explorer') { + return 'ms'; + } - return ''; // Chrome, Opera and Firefox no longer require a vendor prefix - } - }); + if (browser === 'microsoft edge' || browser === 'safari') { + return 'webkit'; + } - }); + return ''; // Chrome, Opera and Firefox no longer require a vendor prefix + } +});