fix: receive XBlock visibility from the Learning MFE (#35491)
This commit is contained in:
@@ -109,7 +109,13 @@ export class ViewedEventTracker {
|
||||
constructor() {
|
||||
this.elementViewings = new Set();
|
||||
this.handlers = [];
|
||||
this.registerDomHandlers();
|
||||
if (window === window.parent) {
|
||||
// Preview (legacy LMS frontend).
|
||||
this.registerDomHandlers();
|
||||
} else {
|
||||
// Learning MFE.
|
||||
window.addEventListener('message', this.handleVisibilityMessage.bind(this));
|
||||
}
|
||||
}
|
||||
|
||||
/** Add an element to track. */
|
||||
@@ -121,7 +127,11 @@ export class ViewedEventTracker {
|
||||
(el, event) => this.callHandlers(el, event),
|
||||
),
|
||||
);
|
||||
this.updateVisible();
|
||||
// Update visibility status immediately after adding the element (in case it's already visible).
|
||||
// We don't need this for the Learning MFE because it will send a message once the iframe is loaded.
|
||||
if (window === window.parent) {
|
||||
this.updateVisible();
|
||||
}
|
||||
}
|
||||
|
||||
/** Register a new handler to be called when an element has been viewed. */
|
||||
@@ -177,4 +187,36 @@ export class ViewedEventTracker {
|
||||
handler(el, event);
|
||||
});
|
||||
}
|
||||
|
||||
/** Handle a unit.visibilityStatus message from the Learning MFE. */
|
||||
handleVisibilityMessage(event) {
|
||||
if (event.data.type === 'unit.visibilityStatus') {
|
||||
const { topPosition, viewportHeight } = event.data.data;
|
||||
|
||||
this.elementViewings.forEach((elv) => {
|
||||
const rect = elv.getBoundingRect();
|
||||
let visible = false;
|
||||
|
||||
// Convert iframe-relative rect coordinates to be relative to the parent's viewport.
|
||||
const elTopPosition = rect.top + topPosition;
|
||||
const elBottomPosition = rect.bottom + topPosition;
|
||||
|
||||
// Check if the element is visible in the parent's viewport.
|
||||
if (elTopPosition < viewportHeight && elTopPosition >= 0) {
|
||||
elv.markTopSeen();
|
||||
visible = true;
|
||||
}
|
||||
if (elBottomPosition <= viewportHeight && elBottomPosition > 0) {
|
||||
elv.markBottomSeen();
|
||||
visible = true;
|
||||
}
|
||||
|
||||
if (visible) {
|
||||
elv.handleVisible();
|
||||
} else {
|
||||
elv.handleNotVisible();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user