Skip to content

Instantly share code, notes, and snippets.

@alexaivars
Created June 4, 2015 21:57
Show Gist options
  • Save alexaivars/56df0273c2439e4d9783 to your computer and use it in GitHub Desktop.
Save alexaivars/56df0273c2439e4d9783 to your computer and use it in GitHub Desktop.
sticky wrapper
'use strict';
var React = require('react');
var util = {
// findPos() by quirksmode.org
// Finds the absolute position of an element on a page
findPos: function (obj) {
/*jshint -W084 */
var curleft = 0,
curtop = 0;
if (obj.offsetParent) {
do {
curleft += obj.offsetLeft;
curtop += obj.offsetTop;
} while (obj = obj.offsetParent);
}
return [curleft, curtop];
},
// getPageScroll() by quirksmode.org
// Finds the scroll position of a page
getPageScroll: function () {
var xScroll, yScroll;
if (window.self && window.self.pageYOffset) {
yScroll = window.self.pageYOffset;
xScroll = window.self.pageXOffset;
} else if (document.documentElement && document.documentElement.scrollTop) {
yScroll = document.documentElement.scrollTop;
xScroll = document.documentElement.scrollLeft;
} else if (document.body) {// all other Explorers
yScroll = document.body.scrollTop;
xScroll = document.body.scrollLeft;
}
return [xScroll, yScroll];
},
// Finds the position of an element relative to the viewport.
findPosRelativeToViewport: function (obj) {
var objPos = this.findPos(obj);
var scroll = this.getPageScroll();
return [ objPos[0] - scroll[0], objPos[1] - scroll[1] ];
}
};
class Sticky extends React.Component {
constructor(props) {
super(props);
this.state = {
fix: false
};
}
componentDidMount() {
window.addEventListener('scroll', this.handleScroll.bind(this), false);
window.addEventListener('resize', this.handleResize.bind(this));
}
componentWillUnmount() {
window.removeEventListener('scroll', this.handleScroll.bind(this), false);
window.removeEventListener('resize', this.handleResize.bind(this));
}
handleResize(){
this.checkPositions();
}
handleScroll() {
this.checkPositions();
}
checkPositions(){
var pos = util.findPosRelativeToViewport(React.findDOMNode(this));
if (pos[1]<=this.props.offsetTop){
this.setState({fix: true});
} else {
this.setState({fix: false});
}
}
render() {
var divStyle;
if (this.state.fix) {
divStyle = {
display: 'block',
position: 'fixed',
top: this.props.offsetTop
};
return (
<div style={{zIndex : this.props.zIndex, position:'relative', width:'100%'}}>
<div ref='original' key='original' className={this.props.className} style={divStyle} >{this.props.children}</div>
</div>
);
} else {
divStyle = {
display: 'block',
position: 'relative'
};
return (
<div style={{zIndex : this.props.zIndex, position:'relative', width:'100%'}}>
<div ref='original' key='original' style={divStyle}>{this.props.children}</div>
</div>
);
}
}
}
Sticky.defaultProps = {
offsetTop: 0,
className: '',
zIndex: 9999
};
Sticky.propTypes = {
offsetTop: React.PropTypes.number,
zIndex: React.PropTypes.number,
className: React.PropTypes.string
};
module.exports = Sticky;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment