Lightbox: pin and size to visible viewport when framed
The staff-report iframe is expanded to full content height (no nested scrollbar), so a modal <dialog> centered in its viewport landed in the middle of the whole document and sat off-screen unless the parent page was scrolled there. Cross-origin means the iframe can't read the parent's scroll position itself. Tab.tpl now broadcasts the iframe's visible slice (webform-mw-viewport, rAF-throttled on scroll/resize/load and after each height change), and AttachmentLightbox pins to that slice and fills its height. Falls back to a fixed box when no viewport message arrives (older extension), and standalone mode keeps native centering at a taller 85vh. Extension bumped to 0.3.1 (template change -> re-copy + cv flush on prod). PRODUCTION_CUTOVER.md change log updated.
This commit is contained in:
@@ -17,7 +17,7 @@
|
||||
<url desc="Main Extension Page">https://github.com/joelbrock/WebForm-mw</url>
|
||||
</urls>
|
||||
<releaseDate>2026-06-05</releaseDate>
|
||||
<version>0.3.0</version>
|
||||
<version>0.3.1</version>
|
||||
<develStage>beta</develStage>
|
||||
<compatibility>
|
||||
<ver>5.50</ver>
|
||||
|
||||
@@ -22,7 +22,41 @@
|
||||
// Add a little headroom so the report's own bottom padding isn't clipped.
|
||||
var h = Math.max(600, Math.floor(d.height) + 24);
|
||||
frame.style.height = h + 'px';
|
||||
// Geometry changed — tell the child where its visible slice now is.
|
||||
scheduleViewport();
|
||||
}, false);
|
||||
|
||||
// The iframe is expanded to full content height, so the report has no
|
||||
// internal scroll context. A modal opened inside it (the attachment
|
||||
// lightbox) would center in the full iframe and sit off-screen. Broadcast
|
||||
// the iframe's currently-visible region (in the child's own content
|
||||
// coordinates) so the lightbox can pin and size itself to it. The child
|
||||
// listens for 'webform-mw-viewport'.
|
||||
var ticking = false;
|
||||
var raf = window.requestAnimationFrame || function (cb) { return setTimeout(cb, 16); };
|
||||
function postViewport() {
|
||||
ticking = false;
|
||||
if (!frame.contentWindow) return;
|
||||
var r = frame.getBoundingClientRect();
|
||||
var winH = window.innerHeight || document.documentElement.clientHeight;
|
||||
var visibleTop = Math.max(0, r.top);
|
||||
var visibleBottom = Math.min(winH, r.bottom);
|
||||
frame.contentWindow.postMessage({
|
||||
type: 'webform-mw-viewport',
|
||||
// px from the iframe's content top down to the first visible row.
|
||||
top: Math.max(0, -r.top),
|
||||
height: Math.max(0, visibleBottom - visibleTop)
|
||||
}, APP_ORIGIN || '*');
|
||||
}
|
||||
function scheduleViewport() {
|
||||
if (ticking) return;
|
||||
ticking = true;
|
||||
raf(postViewport);
|
||||
}
|
||||
window.addEventListener('scroll', scheduleViewport, { passive: true });
|
||||
window.addEventListener('resize', scheduleViewport);
|
||||
window.addEventListener('load', scheduleViewport);
|
||||
scheduleViewport();
|
||||
})();
|
||||
</script>
|
||||
{else}
|
||||
|
||||
Reference in New Issue
Block a user