Skip to content

Commit

Permalink
feat: observe all mutatiosn to capture late added medias
Browse files Browse the repository at this point in the history
  • Loading branch information
kptdobe committed Aug 15, 2024
1 parent 0155de4 commit 6d3e13a
Show file tree
Hide file tree
Showing 3 changed files with 81 additions and 10 deletions.
24 changes: 17 additions & 7 deletions modules/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ function trackCheckpoint(checkpoint, data, t) {
}

function processQueue() {
while (queue.length) {
while (queue && queue.length) {
const ck = queue.shift();
trackCheckpoint(...ck);
}
Expand Down Expand Up @@ -147,22 +147,22 @@ function addLoadResourceTracking() {
observer.observe({ type: 'resource', buffered: true });
}

function activateBlocksMutationObserver() {
function activateMutationObserver() {
if (!mutationObserver || mutationObserver.active) {
return;
}
mutationObserver.active = true;
mutationObserver.observe(
document.body,
// eslint-disable-next-line object-curly-newline
{ subtree: true, attributes: true, attributeFilter: ['data-block-status'] },
{ subtree: true, attributes: false, childList: true },
);
}

function getIntersectionObsever(checkpoint) {
/* c8 ignore next */
if (!window.IntersectionObserver) return null;
activateBlocksMutationObserver();
activateMutationObserver();
const observer = new IntersectionObserver((entries) => {
try {
entries
Expand All @@ -188,19 +188,21 @@ function addViewBlockTracking(element) {
}
}

const observedMedia = new Set();
function addViewMediaTracking(parent) {
const mediaobserver = getIntersectionObsever('viewmedia');
if (mediaobserver) {
parent.querySelectorAll('img, video, audio, iframe').forEach((m) => {
if (!m.closest('div .block') || m.closest('div[data-block-status="loaded"]')) {
if (!observedMedia.has(m)) {
observedMedia.add(m);
mediaobserver.observe(m);
}
});
}
}

function addFormTracking(parent) {
activateBlocksMutationObserver();
activateMutationObserver();
parent.querySelectorAll('form').forEach((form) => {
form.removeEventListener('submit', formSubmitListener); // listen only once
form.addEventListener('submit', formSubmitListener);
Expand All @@ -209,11 +211,19 @@ function addFormTracking(parent) {

const addObserver = (ck, fn, block) => DEFAULT_TRACKING_EVENTS.includes(ck) && fn(block);
function mutationsCallback(mutations) {
mutations.filter((m) => m.type === 'attributes' && m.attributeName === 'data-block-status')
// block specific mutations
mutations
.filter((m) => m.type === 'attributes' && m.attributeName === 'data-block-status')
.filter((m) => m.target.dataset.blockStatus === 'loaded')
.forEach((m) => {
addObserver('form', addFormTracking, m.target);
addObserver('viewblock', addViewBlockTracking, m.target);
});

// media mutations
mutations
.forEach((m) => {
// filtering will be done in the observer
addObserver('viewmedia', addViewMediaTracking, m.target);
});
}
Expand Down
64 changes: 64 additions & 0 deletions test/it/img.delayed.test.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
<html>

<head>
<title>Test Runner</title>
</head>

<body>
<script type="module">
import { runTests } from '@web/test-runner-mocha';
import { expect } from '@esm-bundle/chai';

runTests(async () => {
describe('HTML IMG Tests', () => {

it('rum enhancer reports image, even if added later', async () => {
let called = false;
let imagesSeen = '';
window.hlx = {
rum: {
sampleRUM: (checkpoint, data) => {
called = true;
if (checkpoint === 'viewmedia') {
imagesSeen = data.target;
console.log('viewmedia', data.target);
}
}
}
};

const script = document.createElement('script');
script.src = new URL('/modules/index.js', window.location).href;
script.type = 'module';
document.head.appendChild(script);

await new Promise((resolve) => {
script.onload = resolve;
});

// wait one second for the script to run
await new Promise((resolve) => {
setTimeout(resolve, 1000);
});

const img = document.createElement('img');
img.src = 'https://www.example.com/loadlater.jpg';
img.alt = 'loadlater example image';
document.body.appendChild(img);

// wait one second for the script to run
await new Promise((resolve) => {
setTimeout(resolve, 1000);
});

expect(called).to.be.true;
expect(imagesSeen, 'img inserted later triggers viewmedia').to.equal('https://www.example.com/loadlater.jpg');

});

});
});
</script>
</body>

</html>
3 changes: 0 additions & 3 deletions test/it/img.test.html
Original file line number Diff line number Diff line change
Expand Up @@ -47,10 +47,7 @@
const anotherImage = document.createElement('img');
anotherImage.src = 'https://www.example.com/loadlater.jpg';
document.body.appendChild(anotherImage);
// at the moment, this is not being tracked because it is not
// happening in a block. We only have mutation observers on blocks
});

});
});
</script>
Expand Down

0 comments on commit 6d3e13a

Please sign in to comment.