69 lines
2.6 KiB
Plaintext
69 lines
2.6 KiB
Plaintext
import getWindow from "./getWindow.js";
|
|
import getNodeName from "./getNodeName.js";
|
|
import getComputedStyle from "./getComputedStyle.js";
|
|
import { isHTMLElement, isShadowRoot } from "./instanceOf.js";
|
|
import isTableElement from "./isTableElement.js";
|
|
import getParentNode from "./getParentNode.js";
|
|
import getUAString from "../utils/userAgent.js";
|
|
|
|
function getTrueOffsetParent(element) {
|
|
if (!isHTMLElement(element) || // https://github.com/popperjs/popper-core/issues/837
|
|
getComputedStyle(element).position === 'fixed') {
|
|
return null;
|
|
}
|
|
|
|
return element.offsetParent;
|
|
} // `.offsetParent` reports `null` for fixed elements, while absolute elements
|
|
// return the containing block
|
|
|
|
|
|
function getContainingBlock(element) {
|
|
var isFirefox = /firefox/i.test(getUAString());
|
|
var isIE = /Trident/i.test(getUAString());
|
|
|
|
if (isIE && isHTMLElement(element)) {
|
|
// In IE 9, 10 and 11 fixed elements containing block is always established by the viewport
|
|
var elementCss = getComputedStyle(element);
|
|
|
|
if (elementCss.position === 'fixed') {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
var currentNode = getParentNode(element);
|
|
|
|
if (isShadowRoot(currentNode)) {
|
|
currentNode = currentNode.host;
|
|
}
|
|
|
|
while (isHTMLElement(currentNode) && ['html', 'body'].indexOf(getNodeName(currentNode)) < 0) {
|
|
var css = getComputedStyle(currentNode); // This is non-exhaustive but covers the most common CSS properties that
|
|
// create a containing block.
|
|
// https://developer.mozilla.org/en-US/docs/Web/CSS/Containing_block#identifying_the_containing_block
|
|
|
|
if (css.transform !== 'none' || css.perspective !== 'none' || css.contain === 'paint' || ['transform', 'perspective'].indexOf(css.willChange) !== -1 || isFirefox && css.willChange === 'filter' || isFirefox && css.filter && css.filter !== 'none') {
|
|
return currentNode;
|
|
} else {
|
|
currentNode = currentNode.parentNode;
|
|
}
|
|
}
|
|
|
|
return null;
|
|
} // Gets the closest ancestor positioned element. Handles some edge cases,
|
|
// such as table ancestors and cross browser bugs.
|
|
|
|
|
|
export default function getOffsetParent(element) {
|
|
var window = getWindow(element);
|
|
var offsetParent = getTrueOffsetParent(element);
|
|
|
|
while (offsetParent && isTableElement(offsetParent) && getComputedStyle(offsetParent).position === 'static') {
|
|
offsetParent = getTrueOffsetParent(offsetParent);
|
|
}
|
|
|
|
if (offsetParent && (getNodeName(offsetParent) === 'html' || getNodeName(offsetParent) === 'body' && getComputedStyle(offsetParent).position === 'static')) {
|
|
return window;
|
|
}
|
|
|
|
return offsetParent || getContainingBlock(element) || window;
|
|
} |