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()
The getBoundingClientRect() method returns the size of an element and its position relative to the viewport. The getBoundingClientRect() method returns a DOMRect object with eight properties: left, top, right, bottom, x, y, width, height.
Border, padding and margin are not included.
getBoundingClientRect() gives a result relative to the viewport's top-left corner ( 0,0 ), not relative to an element's parent, whereas el.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With