From 886f036bc09cf66f8f3ee2303a54da80a1f14368 Mon Sep 17 00:00:00 2001 From: Justin Edelson Date: Fri, 5 Jan 2024 12:37:01 -0500 Subject: [PATCH 1/2] feat: add viewmedia RUM events for background images --- scripts/rum-enhancements.js | 38 +++++++++++++++++++++++++++++++++++++ scripts/scripts.js | 7 +++++++ 2 files changed, 45 insertions(+) create mode 100644 scripts/rum-enhancements.js diff --git a/scripts/rum-enhancements.js b/scripts/rum-enhancements.js new file mode 100644 index 0000000..f3e8676 --- /dev/null +++ b/scripts/rum-enhancements.js @@ -0,0 +1,38 @@ +/* + * Copyright 2024 Adobe. All rights reserved. + * This file is licensed to you under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under + * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS + * OF ANY KIND, either express or implied. See the License for the specific language + * governing permissions and limitations under the License. + */ +const { sampleRUM } = window.hlx.rum; + +function extractBackgroundImage(element) { + const matches = /^url\("?(.+)"?\)/.exec(element.style.backgroundImage); + return matches ? matches[1] : undefined; +} + +const backgroundImageObserver = (window.IntersectionObserver) + ? new IntersectionObserver((entries, observer) => { + entries + .filter((entry) => entry.isIntersecting) + .forEach((entry) => { + observer.unobserve(entry.target); // observe only once + const target = extractBackgroundImage(entry.target); + const source = sampleRUM.sourceselector(entry.target); + if (target) { + sampleRUM('viewmedia', { target, source }); + } + }); + }, { threshold: 0.25 }) : { observe: () => { } }; + +// eslint-disable-next-line import/prefer-default-export +export function observeBackgroundImages(elements) { + elements.forEach((element) => { + backgroundImageObserver.observe(element); + }); +} diff --git a/scripts/scripts.js b/scripts/scripts.js index cc9111f..d16a994 100644 --- a/scripts/scripts.js +++ b/scripts/scripts.js @@ -207,6 +207,12 @@ function initSidekick() { } } +async function customizeRUM() { + const { observeBackgroundImages } = await import('./rum-enhancements.js'); + + observeBackgroundImages(document.querySelectorAll('[style*="background-image"]')); +} + const { loadArea, setConfig } = await import(`${miloLibs}/utils/utils.js`); (async function loadPage() { @@ -220,5 +226,6 @@ const { loadArea, setConfig } = await import(`${miloLibs}/utils/utils.js`); await buildAutoBlocks(); overrideMiloBlocks(); await loadArea(); + await customizeRUM(); initSidekick(); }()); From e7176274308ee9982cb95c701dee1c6247a7d5d6 Mon Sep 17 00:00:00 2001 From: Justin Edelson Date: Fri, 5 Jan 2024 12:37:57 -0500 Subject: [PATCH 2/2] feat: add RUM viewmedia/viewblock events for dynamically loaded article cards --- scripts/rum-enhancements.js | 52 +++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/scripts/rum-enhancements.js b/scripts/rum-enhancements.js index f3e8676..ab232ab 100644 --- a/scripts/rum-enhancements.js +++ b/scripts/rum-enhancements.js @@ -36,3 +36,55 @@ export function observeBackgroundImages(elements) { backgroundImageObserver.observe(element); }); } + +class ArticleFeedObserver { + #feed; + + #observedElements = []; + + constructor(feed) { + this.#feed = feed; + } + + start() { + if (this.#feed.classList.contains('appear')) { + // the observer was started after the feed appeared, so observe the blocks and media now. + this.#triggerRUMObserve(); + this.#startChildMutationObserver(); + } else { + // otherwise, wait until the feed appears. + new MutationObserver((mutations, observer) => { + mutations.forEach((mutation) => { + if (mutation.type === 'attributes' && mutation.attributeName === 'class' && mutation.target.classList.contains('appear')) { + observer.disconnect(); + this.#triggerRUMObserve(); + this.#startChildMutationObserver(); + } + }); + }).observe(this.#feed, { attributes: true }); + } + } + + #triggerRUMObserve() { + const elementsToObserve = Array.from(this.#feed.querySelectorAll('.article-card, picture > img')) + .filter((element) => !this.#observedElements.includes(element)); + this.#observedElements.push(...elementsToObserve); + sampleRUM.observe(elementsToObserve); + } + + // handle dynamically added article cards by re-triggering RUM observation + // don't need to be super precise here, since we are tracking which elements + // have already been observed in #observe() + #startChildMutationObserver() { + const articleCards = this.#feed.querySelector('.article-cards'); + if (articleCards) { + new MutationObserver(() => { + this.#triggerRUMObserve(); + }).observe(articleCards, { childList: true }); + } + } +} + +document.querySelectorAll('.article-feed').forEach((articleFeed) => { + new ArticleFeedObserver(articleFeed).start(); +});