@@ -13,6 +13,7 @@ export default class Scrollspy extends React.Component {
13
13
style : PropTypes . object ,
14
14
componentTag : PropTypes . string ,
15
15
offset : PropTypes . number ,
16
+ rootEl : PropTypes . string ,
16
17
}
17
18
}
18
19
@@ -60,6 +61,22 @@ export default class Scrollspy extends React.Component {
60
61
return newArray
61
62
}
62
63
64
+ _isScrolled ( ) {
65
+ return this . _getScrollDimension ( ) . scrollTop > 0
66
+ }
67
+
68
+ _getScrollDimension ( ) {
69
+ const doc = document
70
+ const { rootEl } = this . props
71
+ const scrollTop = rootEl ? doc . querySelector ( rootEl ) . scrollTop : ( doc . documentElement . scrollTop || doc . body . parentNode . scrollTop || doc . body . scrollTop )
72
+ const scrollHeight = rootEl ? doc . querySelector ( rootEl ) . scrollHeight : ( doc . documentElement . scrollHeight || doc . body . parentNode . scrollHeight || doc . body . scrollHeight )
73
+
74
+ return {
75
+ scrollTop,
76
+ scrollHeight,
77
+ }
78
+ }
79
+
63
80
_getElemsViewState ( targets ) {
64
81
let elemsInView = [ ]
65
82
let elemsOutView = [ ]
@@ -81,9 +98,7 @@ export default class Scrollspy extends React.Component {
81
98
}
82
99
83
100
const isLastItem = i === max - 1
84
- const doc = document
85
- const body = document . body
86
- const isScrolled = ( doc . documentElement || body . parentNode || body ) . scrollTop > 0
101
+ const isScrolled = this . _isScrolled ( )
87
102
88
103
// https://github.com/makotot/react-scrollspy/pull/26#issue-167413769
89
104
const isLastShortItemAtBottom = this . _isAtBottom ( ) && this . _isInView ( currentContent ) && ! isInView && isLastItem && isScrolled
@@ -111,24 +126,32 @@ export default class Scrollspy extends React.Component {
111
126
if ( ! el ) {
112
127
return false
113
128
}
129
+
130
+ const { rootEl, offset } = this . props
131
+ let rootRect
132
+
133
+ if ( rootEl ) {
134
+ rootRect = document . querySelector ( rootEl ) . getBoundingClientRect ( )
135
+ }
136
+
114
137
const rect = el . getBoundingClientRect ( )
115
- const winH = window . innerHeight
116
- const doc = document
117
- const body = doc . body
118
- const scrollTop = ( doc . documentElement || body . parentNode || body ) . scrollTop
138
+ const winH = rootEl ? rootRect . height : window . innerHeight
139
+ const { scrollTop } = this . _getScrollDimension ( )
119
140
const scrollBottom = scrollTop + winH
120
- const elTop = rect . top + scrollTop + this . props . offset
141
+ const elTop = rootEl ?
142
+ rect . top + scrollTop - rootRect . top + offset
143
+ :
144
+ rect . top + scrollTop + offset
121
145
const elBottom = elTop + el . offsetHeight
122
146
123
147
return ( elTop < scrollBottom ) && ( elBottom > scrollTop )
124
148
}
125
149
126
150
_isAtBottom ( ) {
127
- const doc = document
128
- const body = doc . body
129
- const scrollTop = ( doc . documentElement || body . parentNode || body ) . scrollTop
130
- const scrollHeight = ( doc . documentElement || body . parentNode || body ) . scrollHeight
131
- const scrolledToBottom = ( scrollTop + window . innerHeight ) >= scrollHeight
151
+ const { rootEl } = this . props
152
+ const { scrollTop, scrollHeight } = this . _getScrollDimension ( )
153
+ const winH = rootEl ? document . querySelector ( rootEl ) . getBoundingClientRect ( ) . height : window . innerHeight
154
+ const scrolledToBottom = ( scrollTop + winH ) >= scrollHeight
132
155
133
156
return scrolledToBottom
134
157
}
@@ -143,8 +166,10 @@ export default class Scrollspy extends React.Component {
143
166
const scrolledPastItems = viewStatusList . map ( ( item ) => {
144
167
if ( item && ! hasFoundInView ) {
145
168
hasFoundInView = true
169
+
146
170
return false
147
171
}
172
+
148
173
return ! hasFoundInView
149
174
} )
150
175
@@ -153,6 +178,7 @@ export default class Scrollspy extends React.Component {
153
178
154
179
_spy ( targets ) {
155
180
const elemensViewState = this . _getElemsViewState ( targets )
181
+
156
182
this . setState ( {
157
183
inViewState : elemensViewState . viewStatusList ,
158
184
isScrolledPast : elemensViewState . scrolledPast
@@ -175,11 +201,15 @@ export default class Scrollspy extends React.Component {
175
201
176
202
componentDidMount ( ) {
177
203
this . _initFromProps ( )
178
- window . addEventListener ( 'scroll' , this . _handleSpy )
204
+ const el = this . props . rootEl ? document . querySelector ( this . props . rootEl ) : window
205
+
206
+ el . addEventListener ( 'scroll' , this . _handleSpy )
179
207
}
180
208
181
209
componentWillUnmount ( ) {
182
- window . removeEventListener ( 'scroll' , this . _handleSpy )
210
+ const el = this . props . rootEl ? document . querySelector ( this . props . rootEl ) : window
211
+
212
+ el . removeEventListener ( 'scroll' , this . _handleSpy )
183
213
}
184
214
185
215
componentWillReceiveProps ( ) {
0 commit comments