higimo-scroll-spy
Version:
Компонент следит за тем, до какого элемента доскроллил клиент и передает сообщение в другой элемент
95 lines (75 loc) • 1.87 kB
JavaScript
import React from 'react'
import {Component} from 'react'
var debounce = require('throttle-debounce/debounce');
var deepcopy = require('deepcopy');
class MainContent extends Component {
constructor(props) {
super(props);
this.state = {
visible : 'default',
elem : {},
}
this.getChildren = this.getChildren.bind(this)
this.debounceVisibleHandler = debounce(200, this.isComponentVisible.bind(this))
}
getChildren() {
return React.Children.map(
this.props.children,
child => {
var props = {
update: this.updateElem.bind(this)
}
if (child.type.name === 'MetaContent') {
props.visible = this.state.visible
}
return React.cloneElement(child, props)
}
)
}
shouldComponentUpdate(nextProps, nextState) {
return nextState.visible !== this.state.visible
}
isComponentVisible() {
const browserTop = window.pageYOffset,
browserBottom = window.innerHeight,
bottomScrolling = browserTop + browserBottom - document.body.clientHeight,
inVisibleItems = []
for (const key in this.state.elem) {
const item = this.state.elem[key]
if (item.top >= 0 && item.top <= browserBottom) {
inVisibleItems.push(item)
}
}
inVisibleItems.sort((first, second) => {
return first.top > second.top
})
if (bottomScrolling > 0 && bottomScrolling < 20) {
inVisibleItems.reverse()
}
this.setState({
visible: (inVisibleItems.length ? inVisibleItems[0].name : 'default'),
})
}
updateElem(name, rect) {
var copy = deepcopy(this.state.elem)
copy[name] = {
name : name,
top : rect.top,
bottom : rect.bottom,
height : rect.height,
}
this.setState({
elem: copy,
}, () => {
this.debounceVisibleHandler.call(this)
})
}
render() {
return (
<div>
{this.getChildren()}
</div>
)
}
}
module.exports = MainContent