From 4f901caa2d28cf0ae4b2b0bfe4d5ec24ed758ee0 Mon Sep 17 00:00:00 2001 From: M Fahru Date: Fri, 26 Jan 2024 04:00:54 -0700 Subject: [PATCH] [website-redesign] Set autoplay video configuration according to specification (#16683) * Set autoplay video configuration according to specification: - Do not autoplay video initially - If the video is visible on the viewport (with a threshold of 80% of the video is visible), autoplay video, and everytime it autoplays, set the video starting point to 0 - If the video is not visible on the viewport (with a threshold of 80% of the video is not visible), pause the video - If user screen stops at video that's currently in autoplay, the autoplay will stop after it endedand replay every 15 seconds. - For user with reduced motion preference, show video controls. * Add a comment explaining error in firefox if user is pressing the seek bar relatively fast. It seems to be a bug specific to firefox. * Reduce the threshold to 70% of the visible video on the screen. 0.7 value will make the video autoplays instantly for the `new-design-registration` variant since the video on that variant will not be shown fully on the screen at initial homepage load (in desktop screen). * Set attribute without empty string, fix video that lacked data attribute * Remove duplicated autoplay video setup on homepage * Remove autoplay pause/reset on scroll away, don't play if not visible Refactors the autoplay-video code and removes the pause/reset on scroll away while also keeping track of the video elements visibility so that the video doesn't immediately start playing after 15s if not visible. We also prevent trying to call .play() before the video is in a "canplay" state. If the video is not ready, then add an event listener for the "canplay" event and only play() once this is fired. We only do this once to avoid adding duplicate listeners. We also check that the video is not playing before calling play(), because it could still be in playback if we scroll out of view and then back into view. * Refactor autoplay-video to match style of similar JS enhancement implementations * Move autoplay-video from shared/utils to features/ --------- Co-authored-by: Thomas Mees Co-authored-by: Thomas GitOrigin-RevId: 13011af04baaeba4b8053478a09e3e4d7c960d5c --- .../js/features/autoplay-video/index.js | 64 +++++++++++++++++++ services/web/frontend/js/marketing.js | 1 + 2 files changed, 65 insertions(+) create mode 100644 services/web/frontend/js/features/autoplay-video/index.js diff --git a/services/web/frontend/js/features/autoplay-video/index.js b/services/web/frontend/js/features/autoplay-video/index.js new file mode 100644 index 0000000000..5d0a6f04fa --- /dev/null +++ b/services/web/frontend/js/features/autoplay-video/index.js @@ -0,0 +1,64 @@ +function setup(videoEl) { + const reducedMotionReduce = window.matchMedia( + '(prefers-reduced-motion: reduce)' + ) + + if (reducedMotionReduce.matches) { + // TODO: on firefox, if user enters this mode, video can throw error + // in console, if user seeks the control seek bar relatively fast + // AbortError: The fetching process for the media resource was aborted by the user agent at the user's request. + // this is only a problem in firefox (tested in macOS), chrome and safari is fine + videoEl.setAttribute('controls', '') + + return + } + + const DELAY_BEFORE_REPLAY = 15 * 1000 + // 0.7 will enable the autoplay on the desktop main homepage video for users + // with the `new-design-registration` variant + const INTERSECTION_THRESHOLD = 0.7 + + let videoIsVisible + let canPlayListenerAdded + + videoEl.addEventListener('ended', () => { + setTimeout(() => { + videoEl.currentTime = 0 + if (videoIsVisible) { + videoEl.play() + } + }, DELAY_BEFORE_REPLAY) + }) + + const observer = new IntersectionObserver( + function onIntersecting(changes) { + for (const change of changes) { + if (change.isIntersecting) { + videoIsVisible = true + if (videoEl.readyState >= videoEl.HAVE_FUTURE_DATA) { + if (videoEl.paused && !videoEl.ended) { + videoEl.play() + } + } else { + if (!canPlayListenerAdded) { + canPlayListenerAdded = true + videoEl.addEventListener('canplay', function playWhenReady() { + videoEl.play() + videoEl.removeEventListener('canplay', playWhenReady) + }) + } + } + } else { + videoIsVisible = false + } + } + }, + { + threshold: INTERSECTION_THRESHOLD, + } + ) + + observer.observe(videoEl) +} + +document.querySelectorAll('[data-ol-autoplay-video]').forEach(setup) diff --git a/services/web/frontend/js/marketing.js b/services/web/frontend/js/marketing.js index 69ede04916..c79a6aece6 100644 --- a/services/web/frontend/js/marketing.js +++ b/services/web/frontend/js/marketing.js @@ -11,6 +11,7 @@ import './features/event-tracking' import './features/fallback-image' import './features/multi-submit' import './features/cookie-banner' +import './features/autoplay-video' $('[data-ol-lang-selector-tooltip]').tooltip({ trigger: 'hover' }) $('[data-toggle="tooltip"]').tooltip()