Skip to content

Commit

Permalink
fix: receive XBlock visibility from the Learning MFE
Browse files Browse the repository at this point in the history
  • Loading branch information
Agrendalath committed Sep 25, 2024
1 parent b75c2db commit 8461749
Showing 1 changed file with 44 additions and 2 deletions.
46 changes: 44 additions & 2 deletions lms/static/completion/js/ViewedEvent.js
Original file line number Diff line number Diff line change
Expand Up @@ -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. */
Expand All @@ -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. */
Expand Down Expand Up @@ -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();
}
});
}
}
}

0 comments on commit 8461749

Please sign in to comment.