Skip to content
This repository was archived by the owner on Aug 7, 2021. It is now read-only.

Commit b67c922

Browse files
authored
Merge pull request #59 from makotot/issue-48
add roolEl props
2 parents fbcc0cb + 59f8c79 commit b67c922

File tree

2 files changed

+49
-15
lines changed

2 files changed

+49
-15
lines changed

src/js/app.jsx

+4
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,10 @@ const App = React.createClass({
132132
<td className="c-table__data">offset</td>
133133
<td className="c-table__data">Offset value that adjusts to determine the elements are in the viewport [optional].</td>
134134
</tr>
135+
<tr>
136+
<td className="c-table__data">rootEl</td>
137+
<td className="c-table__data">Name of the element of scrollable container that can be used with <code>{'querySelector'}</code> [optional].</td>
138+
</tr>
135139
</tbody>
136140
</table>
137141
</div>

src/js/lib/Scrollspy.jsx

+45-15
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ export default class Scrollspy extends React.Component {
1313
style: PropTypes.object,
1414
componentTag: PropTypes.string,
1515
offset: PropTypes.number,
16+
rootEl: PropTypes.string,
1617
}
1718
}
1819

@@ -60,6 +61,22 @@ export default class Scrollspy extends React.Component {
6061
return newArray
6162
}
6263

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+
6380
_getElemsViewState (targets) {
6481
let elemsInView = []
6582
let elemsOutView = []
@@ -81,9 +98,7 @@ export default class Scrollspy extends React.Component {
8198
}
8299

83100
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()
87102

88103
// https://github.com/makotot/react-scrollspy/pull/26#issue-167413769
89104
const isLastShortItemAtBottom = this._isAtBottom() && this._isInView(currentContent) && !isInView && isLastItem && isScrolled
@@ -111,24 +126,32 @@ export default class Scrollspy extends React.Component {
111126
if (!el) {
112127
return false
113128
}
129+
130+
const { rootEl, offset } = this.props
131+
let rootRect
132+
133+
if (rootEl) {
134+
rootRect = document.querySelector(rootEl).getBoundingClientRect()
135+
}
136+
114137
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()
119140
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
121145
const elBottom = elTop + el.offsetHeight
122146

123147
return (elTop < scrollBottom) && (elBottom > scrollTop)
124148
}
125149

126150
_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
132155

133156
return scrolledToBottom
134157
}
@@ -143,8 +166,10 @@ export default class Scrollspy extends React.Component {
143166
const scrolledPastItems = viewStatusList.map((item) => {
144167
if (item && !hasFoundInView) {
145168
hasFoundInView = true
169+
146170
return false
147171
}
172+
148173
return !hasFoundInView
149174
})
150175

@@ -153,6 +178,7 @@ export default class Scrollspy extends React.Component {
153178

154179
_spy (targets) {
155180
const elemensViewState = this._getElemsViewState(targets)
181+
156182
this.setState({
157183
inViewState: elemensViewState.viewStatusList,
158184
isScrolledPast: elemensViewState.scrolledPast
@@ -175,11 +201,15 @@ export default class Scrollspy extends React.Component {
175201

176202
componentDidMount () {
177203
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)
179207
}
180208

181209
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)
183213
}
184214

185215
componentWillReceiveProps () {

0 commit comments

Comments
 (0)