I have a function to assess whether an element (an iFrame) is within the viewport if the element is in view it returns true.
function isElementInViewport() {
var el = document.getElementById('postbid_if')
var rect = el.getBoundingClientRect();
var elemTop = rect.top;
var elemBottom = rect.bottom;
console.log("eleTom " + elemTop)
console.log("elemBottom " + elemBottom)
console.log("window.innerHeight " + (window.innerHeight + (window.top.innerHeight * 0.5)))
var isVisible = (elemTop >= 0) && (elemBottom <= (window.innerHeight + window.innerHeight * 0.5));
return isVisible;
}
This function works correctly when served directly on the page, but in the live environment when this function runs it's inside an iFrame and it looks like getBoundingClientRect()
is referencing the viewport of the iFrame rather than the main window?
Is there any way to use the main window viewport from within an iFrame with getBoundingClientRect()
Each iframe has his own scope so window inside iframe is different than the root window.
You can get root window by window.top
and with that knowledge you could calculate absolute position of current iframe. Here is a proper function:
function currentFrameAbsolutePosition() {
let currentWindow = window;
let currentParentWindow;
let positions = [];
let rect;
while (currentWindow !== window.top) {
currentParentWindow = currentWindow.parent;
for (let idx = 0; idx < currentParentWindow.frames.length; idx++)
if (currentParentWindow.frames[idx] === currentWindow) {
for (let frameElement of currentParentWindow.document.getElementsByTagName('iframe')) {
if (frameElement.contentWindow === currentWindow) {
rect = frameElement.getBoundingClientRect();
positions.push({x: rect.x, y: rect.y});
}
}
currentWindow = currentParentWindow;
break;
}
}
return positions.reduce((accumulator, currentValue) => {
return {
x: accumulator.x + currentValue.x,
y: accumulator.y + currentValue.y
};
}, { x: 0, y: 0 });
}
Now inside isElementInViewport
change these lines:
var elemTop = rect.top;
var elemBottom = rect.bottom;
to
var currentFramePosition = getCurrentFrameAbsolutePosition();
var elemTop = rect.top + currentFramePosition.y;
var elemBottom = rect.bottom + currentFramePosition.y;
and this should works.