You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

68 lines
2.6 KiB

2 months ago
  1. import getWindow from "./getWindow.js";
  2. import getNodeName from "./getNodeName.js";
  3. import getComputedStyle from "./getComputedStyle.js";
  4. import { isHTMLElement, isShadowRoot } from "./instanceOf.js";
  5. import isTableElement from "./isTableElement.js";
  6. import getParentNode from "./getParentNode.js";
  7. import getUAString from "../utils/userAgent.js";
  8. function getTrueOffsetParent(element) {
  9. if (!isHTMLElement(element) || // https://github.com/popperjs/popper-core/issues/837
  10. getComputedStyle(element).position === 'fixed') {
  11. return null;
  12. }
  13. return element.offsetParent;
  14. } // `.offsetParent` reports `null` for fixed elements, while absolute elements
  15. // return the containing block
  16. function getContainingBlock(element) {
  17. var isFirefox = /firefox/i.test(getUAString());
  18. var isIE = /Trident/i.test(getUAString());
  19. if (isIE && isHTMLElement(element)) {
  20. // In IE 9, 10 and 11 fixed elements containing block is always established by the viewport
  21. var elementCss = getComputedStyle(element);
  22. if (elementCss.position === 'fixed') {
  23. return null;
  24. }
  25. }
  26. var currentNode = getParentNode(element);
  27. if (isShadowRoot(currentNode)) {
  28. currentNode = currentNode.host;
  29. }
  30. while (isHTMLElement(currentNode) && ['html', 'body'].indexOf(getNodeName(currentNode)) < 0) {
  31. var css = getComputedStyle(currentNode); // This is non-exhaustive but covers the most common CSS properties that
  32. // create a containing block.
  33. // https://developer.mozilla.org/en-US/docs/Web/CSS/Containing_block#identifying_the_containing_block
  34. 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') {
  35. return currentNode;
  36. } else {
  37. currentNode = currentNode.parentNode;
  38. }
  39. }
  40. return null;
  41. } // Gets the closest ancestor positioned element. Handles some edge cases,
  42. // such as table ancestors and cross browser bugs.
  43. export default function getOffsetParent(element) {
  44. var window = getWindow(element);
  45. var offsetParent = getTrueOffsetParent(element);
  46. while (offsetParent && isTableElement(offsetParent) && getComputedStyle(offsetParent).position === 'static') {
  47. offsetParent = getTrueOffsetParent(offsetParent);
  48. }
  49. if (offsetParent && (getNodeName(offsetParent) === 'html' || getNodeName(offsetParent) === 'body' && getComputedStyle(offsetParent).position === 'static')) {
  50. return window;
  51. }
  52. return offsetParent || getContainingBlock(element) || window;
  53. }