Created
March 30, 2015 11:59
-
-
Save B-Stefan/ef800cd0f8b10597d5df to your computer and use it in GitHub Desktop.
Alternative visibility sensor for react.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** @jsx React.DOM */ | |
'use strict'; | |
import React = require('react'); | |
export interface VisibilitySensorProps{ | |
active:boolean | |
delay: number | |
onChange(isVisible:boolean):void | |
children:any[] | string | |
} | |
class VisibilitySensorManager { | |
private allInstances:VisibilitySensor[] = []; | |
public addInstance(instance:VisibilitySensor){ | |
this.allInstances.push(instance); | |
if(this.allInstances.length == 1){ | |
this.startWatch() | |
} | |
} | |
public removeInstance(instance:VisibilitySensor){ | |
var index = this.allInstances.indexOf(instance); | |
if (index > -1) { | |
this.allInstances.splice(index, 1); | |
} | |
if(this.allInstances.length == 0){ | |
this.stopWatch() | |
} | |
} | |
private interval:any; | |
private startWatch(){ | |
if (this.interval) { | |
return; | |
} | |
var self = this; | |
this.interval = setInterval(function(){ | |
self.allInstances.forEach(function(item,index){ | |
item.check.bind(item)() | |
}) | |
}, VisibilitySensor.defaultProps.delay); | |
} | |
private stopWatch(){ | |
this.interval = clearInterval(this.interval); | |
} | |
} | |
export class VisibilitySensor extends React.Component<VisibilitySensorProps,any,any> { | |
static defaultProps={ | |
active: true, | |
delay: 200 | |
}; | |
private static manager = new VisibilitySensorManager(); | |
private manager: VisibilitySensorManager = VisibilitySensor.manager; | |
private lastValue:any; | |
private interval: any; | |
constructor (props, context) { | |
super(props, context) | |
} | |
componentDidMount () { | |
if (this.props.active) { | |
this.manager.addInstance(this); | |
} | |
} | |
componentWillUnmount (){ | |
this.manager.removeInstance(this); | |
} | |
componentWillReceiveProps(nextProps:VisibilitySensorProps) { | |
if (nextProps.active != this.props.active) { | |
if(nextProps.active){ | |
this.lastValue = null; | |
this.manager.addInstance(this); | |
}else { | |
this.manager.removeInstance(this); | |
} | |
} | |
} | |
check () { | |
var el = React.findDOMNode(this); | |
var rect = el.getBoundingClientRect(); | |
//Element is visible | |
if(this.lastValue == true){ | |
var isVisible = ( | |
rect.left >= 0 && | |
rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) && | |
rect.right <= (window.innerWidth || document.documentElement.clientWidth) | |
); | |
}else { | |
var isVisible = ( | |
rect.top >= 0 && | |
rect.left >= 0 && | |
rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) && | |
rect.right <= (window.innerWidth || document.documentElement.clientWidth) | |
); | |
} | |
// notify the parent when the value changes | |
if (this.lastValue !== isVisible) { | |
this.lastValue = isVisible; | |
this.props.onChange(isVisible); | |
} | |
} | |
render(){ | |
return ( | |
React.createElement('div', null, [this.props.children]) | |
); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Based on React 0.13 and Typescript 1.5
Used with infinityScroll list Component to fade in elements that in the user viewport, based on:
https://github.com/joshwnj/react-visibility-sensor