import getStyleComputedProperty from './getStyleComputedProperty';
|
import includeScroll from './includeScroll';
|
import getScrollParent from './getScrollParent';
|
import getBoundingClientRect from './getBoundingClientRect';
|
import runIsIE from './isIE';
|
import getClientRect from './getClientRect';
|
|
export default function getOffsetRectRelativeToArbitraryNode(children, parent, fixedPosition = false) {
|
const isIE10 = runIsIE(10);
|
const isHTML = parent.nodeName === 'HTML';
|
const childrenRect = getBoundingClientRect(children);
|
const parentRect = getBoundingClientRect(parent);
|
const scrollParent = getScrollParent(children);
|
|
const styles = getStyleComputedProperty(parent);
|
const borderTopWidth = parseFloat(styles.borderTopWidth, 10);
|
const borderLeftWidth = parseFloat(styles.borderLeftWidth, 10);
|
|
// In cases where the parent is fixed, we must ignore negative scroll in offset calc
|
if(fixedPosition && isHTML) {
|
parentRect.top = Math.max(parentRect.top, 0);
|
parentRect.left = Math.max(parentRect.left, 0);
|
}
|
let offsets = getClientRect({
|
top: childrenRect.top - parentRect.top - borderTopWidth,
|
left: childrenRect.left - parentRect.left - borderLeftWidth,
|
width: childrenRect.width,
|
height: childrenRect.height,
|
});
|
offsets.marginTop = 0;
|
offsets.marginLeft = 0;
|
|
// Subtract margins of documentElement in case it's being used as parent
|
// we do this only on HTML because it's the only element that behaves
|
// differently when margins are applied to it. The margins are included in
|
// the box of the documentElement, in the other cases not.
|
if (!isIE10 && isHTML) {
|
const marginTop = parseFloat(styles.marginTop, 10);
|
const marginLeft = parseFloat(styles.marginLeft, 10);
|
|
offsets.top -= borderTopWidth - marginTop;
|
offsets.bottom -= borderTopWidth - marginTop;
|
offsets.left -= borderLeftWidth - marginLeft;
|
offsets.right -= borderLeftWidth - marginLeft;
|
|
// Attach marginTop and marginLeft because in some circumstances we may need them
|
offsets.marginTop = marginTop;
|
offsets.marginLeft = marginLeft;
|
}
|
|
if (
|
isIE10 && !fixedPosition
|
? parent.contains(scrollParent)
|
: parent === scrollParent && scrollParent.nodeName !== 'BODY'
|
) {
|
offsets = includeScroll(offsets, parent);
|
}
|
|
return offsets;
|
}
|