@@ -11,6 +11,7 @@ export class Scrollspy extends React.Component {
11
11
style : React . PropTypes . object ,
12
12
componentTag : React . PropTypes . string ,
13
13
offset : React . PropTypes . number ,
14
+ rootNode : React . PropTypes . node ,
14
15
}
15
16
}
16
17
@@ -21,6 +22,7 @@ export class Scrollspy extends React.Component {
21
22
style : { } ,
22
23
componentTag : 'ul' ,
23
24
offset : 0 ,
25
+ rootNode : document . documentElement ,
24
26
}
25
27
}
26
28
@@ -68,7 +70,8 @@ export class Scrollspy extends React.Component {
68
70
}
69
71
70
72
const isLastItem = i === max - 1
71
- const isScrolled = ( document . documentElement . scrollTop || document . body . scrollTop ) > 0
73
+ const isScrolled = this . _rootNode . scrollTop > 0
74
+
72
75
73
76
// https://github.com/makotot/react-scrollspy/pull/26#issue-167413769
74
77
if ( this . _isAtBottom ( ) && this . _isInView ( currentContent ) && ! isInView && isLastItem && isScrolled ) {
@@ -95,22 +98,21 @@ export class Scrollspy extends React.Component {
95
98
return false
96
99
}
97
100
const rect = el . getBoundingClientRect ( )
98
- const winH = window . innerHeight
99
- const doc = document
100
- const scrollTop = doc . documentElement . scrollTop || doc . body . scrollTop
101
- const scrollBottom = scrollTop + winH
101
+ const root = this . _rootNode
102
+ const rootRect = root . getBoundingClientRect ( )
103
+ const scrollTop = root . scrollTop
104
+ const scrollBottom = scrollTop + rootRect . height
102
105
const elTop = rect . top + scrollTop + this . props . offset
103
106
const elBottom = elTop + el . offsetHeight
104
107
105
108
return ( elTop < scrollBottom ) && ( elBottom > scrollTop )
106
109
}
107
110
108
111
_isAtBottom ( ) {
109
- const doc = document
110
- const body = doc . body
111
- const scrollTop = ( doc . documentElement && doc . documentElement . scrollTop ) || body . scrollTop
112
- const scrollHeight = ( doc . documentElement && doc . documentElement . scrollHeight ) || body . scrollHeight
113
- const scrolledToBottom = ( scrollTop + window . innerHeight ) >= scrollHeight
112
+ const rect = this . _rootNode . getBoundingClientRect ( )
113
+ const scrollTop = this . _rootNode . scrollTop
114
+ const scrollHeight = this . _rootNode . scrollHeight
115
+ const scrolledToBottom = scrollTop + rect . height >= scrollHeight
114
116
115
117
return scrolledToBottom
116
118
}
@@ -142,36 +144,42 @@ export class Scrollspy extends React.Component {
142
144
}
143
145
144
146
_handleSpy ( ) {
145
- let timer
146
-
147
- if ( timer ) {
148
- clearTimeout ( timer )
149
- timer = null
150
- }
151
- timer = setTimeout ( this . _spy . bind ( this ) , 100 )
147
+ setTimeout ( ( ) => this . _spy ( ) , 100 )
152
148
}
153
149
154
- _initFromProps ( ) {
155
- const targetItems = this . _initSpyTarget ( this . props . items )
150
+ _initFromProps ( props ) {
151
+ const targetItems = this . _initSpyTarget ( props . items )
156
152
157
153
this . setState ( {
158
154
targetItems,
159
155
} )
160
156
161
- this . _spy ( targetItems )
157
+ setTimeout ( ( ) => this . _spy ( targetItems ) , 100 )
158
+ }
159
+
160
+ get _rootNode ( ) {
161
+ return this . props . rootNode || document . documentElement
162
162
}
163
163
164
164
componentDidMount ( ) {
165
- this . _initFromProps ( )
166
- window . addEventListener ( 'scroll' , this . _handleSpy )
165
+ this . _initFromProps ( this . props )
166
+ this . _rootNode . addEventListener ( 'scroll' , this . _handleSpy )
167
167
}
168
168
169
169
componentWillUnmount ( ) {
170
- window . removeEventListener ( 'scroll' , this . _handleSpy )
170
+ this . _rootNode . removeEventListener ( 'scroll' , this . _handleSpy )
171
171
}
172
172
173
- componentWillReceiveProps ( ) {
174
- this . _initFromProps ( )
173
+ componentWillReceiveProps ( nextProps ) {
174
+ this . _rootNode . removeEventListener ( 'scroll' , this . _handleSpy )
175
+
176
+ if ( nextProps . rootNode ) {
177
+ nextProps . rootNode . addEventListener ( 'scroll' , this . _handleSpy )
178
+ } else {
179
+ document . documentElement . addEventListener ( 'scroll' , this . _handleSpy )
180
+ }
181
+
182
+ this . _initFromProps ( nextProps )
175
183
}
176
184
177
185
render ( ) {
0 commit comments