Skip to content

Commit

Permalink
[Flare] Ensure getAbsoluteBoundingClientRect aligns with offsetParent (
Browse files Browse the repository at this point in the history
  • Loading branch information
trueadm committed May 23, 2019
1 parent 61f6224 commit 025b07b
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 13 deletions.
36 changes: 23 additions & 13 deletions packages/react-events/src/Press.js
Original file line number Diff line number Diff line change
Expand Up @@ -426,6 +426,18 @@ function calculateDelayMS(delay: ?number, min = 0, fallback = 0) {
return Math.max(min, maybeNumber != null ? maybeNumber : fallback);
}

function isNodeFixedPositioned(node: Node | null | void): boolean {
return (
node != null &&
(node: any).offsetParent === null &&
!isNodeDocumentNode(node.parentNode)
);
}

function isNodeDocumentNode(node: Node | null | void): boolean {
return node != null && node.nodeType === Node.DOCUMENT_NODE;
}

function getAbsoluteBoundingClientRect(
target: Element,
): {left: number, right: number, bottom: number, top: number} {
Expand All @@ -440,25 +452,23 @@ function getAbsoluteBoundingClientRect(
const parent = node.parentNode;
const scrollTop = (node: any).scrollTop;
const scrollLeft = (node: any).scrollLeft;
const isParentDocumentNode =
parent != null && parent.nodeType === Node.DOCUMENT_NODE;

// Check if the current node is fixed position, by using
// offsetParent node for a fast-path. Then we need to
// check if it's a scrollable container by checking if
// either scrollLeft or scrollTop are not 0. If it is
// a scrollable container and the parent node is not
// the document, then we can stop traversing the tree.

// We first need to check if it's a scrollable container by
// checking if either scrollLeft or scrollTop are not 0.
// Then we check if either the current node or its parent
// are fixed position, using offsetParent node for a fast-path.
// We need to check both as offsetParent accounts for both
// itself and the parent; so we need to align with that API.
// If these all pass, we can stop traversing the tree.
if (
!isParentDocumentNode &&
(node: any).offsetParent === null &&
(scrollLeft !== 0 || scrollTop !== 0)
(scrollLeft !== 0 || scrollTop !== 0) &&
(isNodeFixedPositioned(parent) || isNodeFixedPositioned(node))
) {
break;
}
offsetX += scrollLeft;
offsetY += scrollTop;
if (isParentDocumentNode) {
if (isNodeDocumentNode(parent)) {
break;
}
node = parent;
Expand Down
1 change: 1 addition & 0 deletions packages/react-events/src/__tests__/Press-test.internal.js
Original file line number Diff line number Diff line change
Expand Up @@ -1167,6 +1167,7 @@ describe('Event responder: Press', () => {

// The fixed container is not scrolled
fixedDiv.scrollTop = 0;
fixedDiv.scrollLeft = 0;
ref.current.getBoundingClientRect = getBoundingClientRectMock;
// Emulate the <html> element being offset with scroll
document.firstElementChild.scrollTop = 1000;
Expand Down

0 comments on commit 025b07b

Please sign in to comment.