var React = require('react'); var _listeners = []; module.exports = { isInViewport: function() { var el = React.findDOMNode(this); if(!el) return false; var rect = el.getBoundingClientRect(); var viewportHeight = global.window.innerHeight || global.document.documentElement.clientHeight; var viewportWidth = global.window.innerWidth || global.document.documentElement.clientWidth; return ( rect.bottom >= 0 && rect.right >= 0 && rect.top <= viewportHeight && rect.left <= viewportWidth ); }, componentDidMount: function() { if(typeof this.onInViewport === 'function') { _listeners.push(this); if( this.isInViewport() ) { this.onInViewport(); } } }, componentWillUnmount: function() { var index = _listeners.indexOf(this); if(index !== -1) return _listeners.splice(index, 1); } }; var computeComponentsVisibilityDebounced = debounce(computeComponentsVisibility, 100); // Start listening for changes window.document.addEventListener('scroll', computeComponentsVisibilityDebounced, true); window.addEventListener('resize', computeComponentsVisibilityDebounced); function computeComponentsVisibility() { _listeners.forEach(function(listener) { if( listener.isInViewport() ) { listener.onInViewport(); } }); } function debounce(func, wait, immediate) { var timeout; return function() { var context = this, args = arguments; var later = function() { timeout = null; if (!immediate) func.apply(context, args); }; var callNow = immediate && !timeout; clearTimeout(timeout); timeout = setTimeout(later, wait); if (callNow) func.apply(context, args); }; }