Skip to content

Commit 9b5b842

Browse files
bu1kaAljullu
authored andcommitted
added support container with overflow (#28)
1 parent b743022 commit 9b5b842

File tree

2 files changed

+92
-20
lines changed

2 files changed

+92
-20
lines changed

src/hoc/trackWindowScroll.js

+56-20
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,15 @@
11
import React from 'react';
2+
import ReactDom from 'react-dom';
23
import { PropTypes } from 'prop-types';
34
import debounce from 'lodash.debounce';
45
import throttle from 'lodash.throttle';
56
import isIntersectionObserverAvailable from '../utils/intersection-observer';
7+
import getScrollElement from '../utils/get-scroll-element';
8+
9+
const getScrollX = () => typeof window === 'undefined' ?
10+
0 : (window.scrollX || window.pageXOffset);
11+
const getScrollY = () => typeof window === 'undefined' ?
12+
0 : (window.scrollY || window.pageYOffset);
613

714
const trackWindowScroll = (BaseComponent) => {
815
class ScrollAwareComponent extends React.Component {
@@ -23,48 +30,76 @@ const trackWindowScroll = (BaseComponent) => {
2330

2431
this.state = {
2532
scrollPosition: {
26-
x: (typeof window === 'undefined' ?
27-
0 :
28-
(window.scrollX || window.pageXOffset)
29-
),
30-
y: (typeof window === 'undefined' ?
31-
0 :
32-
(window.scrollY || window.pageYOffset)
33-
),
33+
x: getScrollX(),
34+
y: getScrollY(),
3435
},
3536
};
37+
38+
this.baseComponentRef = React.createRef();
3639
}
3740

3841
componentDidMount() {
39-
if (typeof window == 'undefined' || isIntersectionObserverAvailable()) {
42+
this.addListeners();
43+
}
44+
45+
componentWillUnmount() {
46+
this.removeListeners();
47+
}
48+
49+
componentDidUpdate() {
50+
if (typeof window === 'undefined' || isIntersectionObserverAvailable()) {
51+
return;
52+
}
53+
54+
const scrollElement = getScrollElement(
55+
ReactDom.findDOMNode(this.baseComponentRef.current)
56+
);
57+
58+
if (scrollElement !== this.scrollElement) {
59+
this.removeListeners();
60+
this.addListeners();
61+
}
62+
}
63+
64+
addListeners() {
65+
if (typeof window === 'undefined' || isIntersectionObserverAvailable()) {
4066
return;
4167
}
42-
window.addEventListener('scroll', this.delayedScroll);
68+
69+
this.scrollElement = getScrollElement(
70+
ReactDom.findDOMNode(this.baseComponentRef.current)
71+
);
72+
73+
this.scrollElement.addEventListener('scroll', this.delayedScroll);
4374
window.addEventListener('resize', this.delayedScroll);
75+
76+
if (this.scrollElement !== window) {
77+
window.addEventListener('scroll', this.delayedScroll);
78+
}
4479
}
4580

46-
componentWillUnmount() {
81+
removeListeners() {
4782
if (typeof window == 'undefined' || isIntersectionObserverAvailable()) {
4883
return;
4984
}
50-
window.removeEventListener('scroll', this.delayedScroll);
85+
86+
this.scrollElement.removeEventListener('scroll', this.delayedScroll);
5187
window.removeEventListener('resize', this.delayedScroll);
88+
89+
if (this.scrollElement !== window) {
90+
window.removeEventListener('scroll', this.delayedScroll);
91+
}
5292
}
5393

5494
onChangeScroll() {
5595
if (isIntersectionObserverAvailable()) {
5696
return;
5797
}
98+
5899
this.setState({
59100
scrollPosition: {
60-
x: (typeof window == 'undefined' ?
61-
0 :
62-
(window.scrollX || window.pageXOffset)
63-
),
64-
y: (typeof window === 'undefined' ?
65-
0 :
66-
(window.scrollY || window.pageYOffset)
67-
),
101+
x: getScrollX(),
102+
y: getScrollY(),
68103
},
69104
});
70105
}
@@ -76,6 +111,7 @@ const trackWindowScroll = (BaseComponent) => {
76111

77112
return (
78113
<BaseComponent
114+
ref={this.baseComponentRef}
79115
scrollPosition={scrollPosition}
80116
{...props} />
81117
);

src/utils/get-scroll-element.js

+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
// copyright https://github.com/loktar00/react-lazy-load/blob/master/src/utils/parentScroll.js
2+
3+
const style = (element, prop) =>
4+
typeof getComputedStyle === 'undefined' ? element.style[prop] :
5+
getComputedStyle(element, null).getPropertyValue(prop);
6+
7+
const overflow = (element) =>
8+
style(element, 'overflow') +
9+
style(element, 'overflow-y') +
10+
style(element, 'overflow-x');
11+
12+
const scrollParent = (element) => {
13+
if (!(element instanceof HTMLElement)) {
14+
return window;
15+
}
16+
17+
let parent = element;
18+
19+
while (parent) {
20+
if (parent === document.body ||
21+
parent === document.documentElement ||
22+
!parent.parentNode) {
23+
break;
24+
}
25+
26+
if (/(scroll|auto)/.test(overflow(parent))) {
27+
return parent;
28+
}
29+
30+
parent = parent.parentNode;
31+
}
32+
33+
return window;
34+
};
35+
36+
export default scrollParent;

0 commit comments

Comments
 (0)