/** * Computed the boundaries limits and return them */ import { Offsets } from '../models'; import { findCommonOffsetParent } from './findCommonOffsetParent'; import { getFixedPositionOffsetParent } from './getFixedPositionOffsetParent'; import { getOffsetRectRelativeToArbitraryNode } from './getOffsetRectRelativeToArbitraryNode'; import { getParentNode } from './getParentNode'; import { getScrollParent } from './getScrollParent'; import { getViewportOffsetRectRelativeToArtbitraryNode } from './getViewportOffsetRectRelativeToArtbitraryNode'; import { getWindowSizes } from './getWindowSizes'; import { isFixed } from './isFixed'; import { isNumber } from './isNumeric'; export function getBoundaries( target: HTMLElement, host: HTMLElement, padding = 0, boundariesElement: string, fixedPosition = false ): Partial { // NOTE: 1 DOM access here let boundaries: Partial = { top: 0, left: 0 }; const offsetParent = fixedPosition ? getFixedPositionOffsetParent(target) : findCommonOffsetParent(target, host); // Handle viewport case if (boundariesElement === 'viewport') { boundaries = getViewportOffsetRectRelativeToArtbitraryNode(offsetParent, fixedPosition); } else { // Handle other cases based on DOM element used as boundaries let boundariesNode; if (boundariesElement === 'scrollParent') { boundariesNode = getScrollParent(getParentNode(host)); if (boundariesNode.nodeName === 'BODY') { boundariesNode = target.ownerDocument.documentElement; } } else if (boundariesElement === 'window') { boundariesNode = target.ownerDocument.documentElement; } else { boundariesNode = boundariesElement; } const offsets = getOffsetRectRelativeToArbitraryNode( boundariesNode, offsetParent, fixedPosition ); // In case of HTML, we need a different computation if (offsets && boundariesNode.nodeName === 'HTML' && !isFixed(offsetParent)) { const { height, width } = getWindowSizes(target.ownerDocument); if (isNumber(boundaries.top) && isNumber(offsets.top) && isNumber(offsets.marginTop)) { boundaries.top += offsets.top - offsets.marginTop; } if (isNumber(boundaries.top)) { boundaries.bottom = Number(height) + Number(offsets.top); } if (isNumber(boundaries.left) && isNumber(offsets.left) && isNumber(offsets.marginLeft)) { boundaries.left += offsets.left - offsets.marginLeft; } if (isNumber(boundaries.top)) { boundaries.right = Number(width) + Number(offsets.left); } } else if (offsets) { // for all the other DOM elements, this one is good boundaries = offsets; } } // Add paddings if (isNumber(boundaries.left)) { boundaries.left += padding; } if (isNumber(boundaries.top)) { boundaries.top += padding; } if (isNumber(boundaries.right)) { boundaries.right -= padding; } if (isNumber(boundaries.bottom)) { boundaries.bottom -= padding; } return boundaries; }