forked from Gitlink/forgeplus-react
92 lines
2.7 KiB
Plaintext
92 lines
2.7 KiB
Plaintext
|
|
// @flow
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* Gets the dimensions of the element, accounting for API differences between
|
|||
|
|
* `window` and other DOM elements.
|
|||
|
|
*/
|
|||
|
|
|
|||
|
|
type Dimensions = {
|
|||
|
|
height: number,
|
|||
|
|
width: number,
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
// TODO Move this into WindowScroller and import from there
|
|||
|
|
type WindowScrollerProps = {
|
|||
|
|
serverHeight: number,
|
|||
|
|
serverWidth: number,
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
const isWindow = element => element === window;
|
|||
|
|
|
|||
|
|
const getBoundingBox = element => element.getBoundingClientRect();
|
|||
|
|
|
|||
|
|
export function getDimensions(
|
|||
|
|
scrollElement: ?Element,
|
|||
|
|
props: WindowScrollerProps,
|
|||
|
|
): Dimensions {
|
|||
|
|
if (!scrollElement) {
|
|||
|
|
return {
|
|||
|
|
height: props.serverHeight,
|
|||
|
|
width: props.serverWidth,
|
|||
|
|
};
|
|||
|
|
} else if (isWindow(scrollElement)) {
|
|||
|
|
const {innerHeight, innerWidth} = window;
|
|||
|
|
return {
|
|||
|
|
height: typeof innerHeight === 'number' ? innerHeight : 0,
|
|||
|
|
width: typeof innerWidth === 'number' ? innerWidth : 0,
|
|||
|
|
};
|
|||
|
|
} else {
|
|||
|
|
return getBoundingBox(scrollElement);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* Gets the vertical and horizontal position of an element within its scroll container.
|
|||
|
|
* Elements that have been “scrolled past” return negative values.
|
|||
|
|
* Handles edge-case where a user is navigating back (history) from an already-scrolled page.
|
|||
|
|
* In this case the body’s top or left position will be a negative number and this element’s top or left will be increased (by that amount).
|
|||
|
|
*/
|
|||
|
|
export function getPositionOffset(element: Element, container: Element) {
|
|||
|
|
if (isWindow(container) && document.documentElement) {
|
|||
|
|
const containerElement = document.documentElement;
|
|||
|
|
const elementRect = getBoundingBox(element);
|
|||
|
|
const containerRect = getBoundingBox(containerElement);
|
|||
|
|
return {
|
|||
|
|
top: elementRect.top - containerRect.top,
|
|||
|
|
left: elementRect.left - containerRect.left,
|
|||
|
|
};
|
|||
|
|
} else {
|
|||
|
|
const scrollOffset = getScrollOffset(container);
|
|||
|
|
const elementRect = getBoundingBox(element);
|
|||
|
|
const containerRect = getBoundingBox(container);
|
|||
|
|
return {
|
|||
|
|
top: elementRect.top + scrollOffset.top - containerRect.top,
|
|||
|
|
left: elementRect.left + scrollOffset.left - containerRect.left,
|
|||
|
|
};
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* Gets the vertical and horizontal scroll amount of the element, accounting for IE compatibility
|
|||
|
|
* and API differences between `window` and other DOM elements.
|
|||
|
|
*/
|
|||
|
|
export function getScrollOffset(element: Element) {
|
|||
|
|
if (isWindow(element) && document.documentElement) {
|
|||
|
|
return {
|
|||
|
|
top:
|
|||
|
|
'scrollY' in window
|
|||
|
|
? window.scrollY
|
|||
|
|
: document.documentElement.scrollTop,
|
|||
|
|
left:
|
|||
|
|
'scrollX' in window
|
|||
|
|
? window.scrollX
|
|||
|
|
: document.documentElement.scrollLeft,
|
|||
|
|
};
|
|||
|
|
} else {
|
|||
|
|
return {
|
|||
|
|
top: element.scrollTop,
|
|||
|
|
left: element.scrollLeft,
|
|||
|
|
};
|
|||
|
|
}
|
|||
|
|
}
|