File: components/OnViewportMixin.js
"use strict";
var React = require("react/addons");
/**
* This React component mixin adds onViewport callback prop. It's called when
* the component is scrolled to the visible viewport
*
* @namespace components
* @class OnViewportMixin
* @constructor
* @param {Object} props
* @param {Function} props.onViewport
* Called when the component appear in the viewport
*/
var OnViewportMixin = {
propTypes: {
onViewport: React.PropTypes.func.isRequired
},
componentDidMount: function() {
this._wasInViewport = false;
window.addEventListener("scroll", this._emitOnViewport);
window.addEventListener("resize", this._emitOnViewport);
this._emitOnViewport();
},
componentWillUnmount: function() {
window.removeEventListener("scroll", this._emitOnViewport);
window.removeEventListener("resize", this._emitOnViewport);
},
_emitOnViewport: function() {
if (typeof this.props.onViewport !== "function") return;
if (!this.isInViewport()) {
this._wasInViewport = false;
return;
}
// If was in viewport on the last time do not emit the same event again
if (this._wasInViewport) return;
this.props.onViewport(this.props);
this._wasInViewport = true;
},
/**
* Return true if the component is in the viewport ie. scrolled so the user
* can see it.
*
* src: https://gist.github.com/
* @method isInViewport
* @return {Boolean}
*/
isInViewport: function() {
if (!this.isMounted()) return false;
var rect = this.getDOMNode().getBoundingClientRect();
var html = document.documentElement;
return (
rect.top >= 0 &&
rect.left >= 0 &&
rect.bottom <= (window.innerHeight || html.clientHeight) &&
rect.right <= (window.innerWidth || html.clientWidth)
);
},
};
module.exports = OnViewportMixin;