@samitouri / QOS-React-2 / commits / 025b07b610

[Flare] Ensure getAbsoluteBoundingClientRect aligns with offsetParent (#15720)

Dominic Gannaway committed May 23, 2019 at 13:51 UTC 025b07b61038300486b44c71f796a74cbdcd5d9f
2 files changed +24 -13
packages/react-events/src/Press.js
+23 -13
@@ -426,6 +426,18 @@ function calculateDelayMS(delay: ?number, min = 0, fallback = 0) {
426 return Math.max(min, maybeNumber != null ? maybeNumber : fallback);
427 }
428
429 +function isNodeFixedPositioned(node: Node | null | void): boolean {
430 + return (
431 + node != null &&
432 + (node: any).offsetParent === null &&
433 + !isNodeDocumentNode(node.parentNode)
434 + );
435 +}
436 +
437 +function isNodeDocumentNode(node: Node | null | void): boolean {
438 + return node != null && node.nodeType === Node.DOCUMENT_NODE;
439 +}
440 +
441 function getAbsoluteBoundingClientRect(
442 target: Element,
443 ): {left: number, right: number, bottom: number, top: number} {
@@ -440,25 +452,23 @@ function getAbsoluteBoundingClientRect(
452 const parent = node.parentNode;
453 const scrollTop = (node: any).scrollTop;
454 const scrollLeft = (node: any).scrollLeft;
443 - const isParentDocumentNode =
444 - parent != null && parent.nodeType === Node.DOCUMENT_NODE;
445 -
446 - // Check if the current node is fixed position, by using
447 - // offsetParent node for a fast-path. Then we need to
448 - // check if it's a scrollable container by checking if
449 - // either scrollLeft or scrollTop are not 0. If it is
450 - // a scrollable container and the parent node is not
451 - // the document, then we can stop traversing the tree.
455 +
456 + // We first need to check if it's a scrollable container by
457 + // checking if either scrollLeft or scrollTop are not 0.
458 + // Then we check if either the current node or its parent
459 + // are fixed position, using offsetParent node for a fast-path.
460 + // We need to check both as offsetParent accounts for both
461 + // itself and the parent; so we need to align with that API.
462 + // If these all pass, we can stop traversing the tree.
463 if (
453 - !isParentDocumentNode &&
454 - (node: any).offsetParent === null &&
455 - (scrollLeft !== 0 || scrollTop !== 0)
464 + (scrollLeft !== 0 || scrollTop !== 0) &&
465 + (isNodeFixedPositioned(parent) || isNodeFixedPositioned(node))
466 ) {
467 break;
468 }
469 offsetX += scrollLeft;
470 offsetY += scrollTop;
461 - if (isParentDocumentNode) {
471 + if (isNodeDocumentNode(parent)) {
472 break;
473 }
474 node = parent;
packages/react-events/src/__tests__/Press-test.internal.js
+1
@@ -1167,6 +1167,7 @@ describe('Event responder: Press', () => {
1167
1168 // The fixed container is not scrolled
1169 fixedDiv.scrollTop = 0;
1170 + fixedDiv.scrollLeft = 0;
1171 ref.current.getBoundingClientRect = getBoundingClientRectMock;
1172 // Emulate the <html> element being offset with scroll
1173 document.firstElementChild.scrollTop = 1000;