UNPKG

higimo-scroll-spy

Version:

Компонент следит за тем, до какого элемента доскроллил клиент и передает сообщение в другой элемент

95 lines (75 loc) 1.87 kB
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