From 858cdbc220011e4794314df657772b58a2a0bb3c Mon Sep 17 00:00:00 2001 From: Joey Arhar Date: Tue, 27 Jul 2021 20:34:26 -0700 Subject: [PATCH 1/2] Polyfill legacy offsetParent behavior The spec for offsetParent was changed here: https://github.com/w3c/csswg-drafts/issues/159 This change was implemented in Safari and Firefox, but hasn't been implemented in Chrome, until now: https://chromium-review.googlesource.com/c/chromium/src/+/2775208 When I made this change in chrome, it broke some chrome:// internal pages which use paper-tooltip: https://bugs.chromium.org/p/chromium/issues/detail?id=1200750 https://bugs.chromium.org/p/chromium/issues/detail?id=1202105 This patch fixes paper-tooltip to use the new offsetParent behavior by adding a polyfill for the old offsetParent behavior. The issues reported in the above bugs would also occur in Firefox and Safari, but nobody ever found out because those chrome:// pages were obviously never tested in Firefox or Safari. --- paper-tooltip.js | 46 +++++++++++++++++++++++++++++++++++++++-- test/basic.html | 53 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 97 insertions(+), 2 deletions(-) diff --git a/paper-tooltip.js b/paper-tooltip.js index 220ae34..af1f958 100644 --- a/paper-tooltip.js +++ b/paper-tooltip.js @@ -435,13 +435,16 @@ Polymer({ * @return {void} */ updatePosition: function() { - if (!this._target || !this.offsetParent) + if (!this._target) + return; + var offsetParent = this._composedOffsetParent(); + if (!offsetParent) return; var offset = this.offset; // If a marginTop has been provided by the user (pre 1.0.3), use it. if (this.marginTop != 14 && this.offset == 14) offset = this.marginTop; - var parentRect = this.offsetParent.getBoundingClientRect(); + var parentRect = offsetParent.getBoundingClientRect(); var targetRect = this._target.getBoundingClientRect(); var thisRect = this.getBoundingClientRect(); var horizontalCenterOffset = (targetRect.width - thisRect.width) / 2; @@ -587,5 +590,44 @@ Polymer({ } this.unlisten(this.$.tooltip, 'animationend', '_onAnimationEnd'); this.unlisten(this, 'mouseenter', 'hide'); + }, + + /** + * Polyfills the old offsetParent behavior from before the spec was changed: + * https://github.com/w3c/csswg-drafts/issues/159 + */ + _composedOffsetParent: function() { + let offsetParent = this.offsetParent; + let ancestor = this; + let foundInsideSlot = false; + while (ancestor && ancestor !== offsetParent) { + const assignedSlot = ancestor.assignedSlot; + if (assignedSlot) { + let newOffsetParent = assignedSlot.offsetParent; + + if (getComputedStyle(assignedSlot)['display'] === 'contents') { + const hadStyleAttribute = assignedSlot.hasAttribute('style'); + const oldDisplay = assignedSlot.style.display; + assignedSlot.style.display = getComputedStyle(ancestor).display; + + newOffsetParent = assignedSlot.offsetParent; + + assignedSlot.style.display = oldDisplay; + if (!hadStyleAttribute) { + assignedSlot.removeAttribute('style'); + } + } + + ancestor = assignedSlot; + if (offsetParent !== newOffsetParent) { + offsetParent = newOffsetParent; + foundInsideSlot = true; + } + } else if (ancestor.host && foundInsideSlot) { + break; + } + ancestor = ancestor.host || ancestor.parentNode; + } + return offsetParent; } }); diff --git a/test/basic.html b/test/basic.html index fe86f40..2b22680 100644 --- a/test/basic.html +++ b/test/basic.html @@ -118,6 +118,17 @@ + + + +