-
-
Notifications
You must be signed in to change notification settings - Fork 3.1k
/
dimensions.js
91 lines (83 loc) · 2.67 KB
/
dimensions.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
// @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,
};
}
}