Last active
March 8, 2016 13:28
-
-
Save Logiraptor/1c8526db6018c7786897 to your computer and use it in GitHub Desktop.
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
// Ignore these imports | |
import React from 'react'; | |
import ReactDOM from 'react-dom'; | |
// Usage: | |
// 1. render a Popup anywhere in the app. | |
// 2. pass trigger and content props | |
// - trigger is the clickable element which shows/hides the content | |
// 3. register a global onClick listener **once** that calls Popup.hidePopups. | |
// - Navbar.js.jsx is a reasonable place for this. | |
// To test this, we'll need to do a few things: | |
// | |
// render Popup, call toggleContent | |
// expect props.content to be rendered inside props.trigger only when appropriate | |
// | |
// click on the rendered trigger element and expect toggleContent to have been called | |
// | |
// call Popup.hidePopups and expect component.hideContent to have been called. | |
var Popup = React.createClass({ | |
// Here, we keep track of all rendered popups in a static array | |
// This is so we can hide them all when an outside click occurs. | |
statics: { | |
popups: [], | |
hidePopups: function(event) { | |
_.map(Popup.popups, function(popup) { | |
popup.hideContent(event); | |
}); | |
} | |
}, | |
propTypes: { | |
trigger: React.PropTypes.element.isRequired, | |
content: React.PropTypes.node.isRequired | |
}, | |
getInitialState: function() { | |
return { | |
status: false | |
} | |
}, | |
componentDidMount: function() { | |
Popup.popups.push(this); | |
}, | |
componentWillUnmount: function() { | |
Popup.popups = _.without(Popup.popups, this); | |
}, | |
hideContent: function(event) { | |
this.setState({ | |
status: false | |
}); | |
}, | |
toggleContent: function(event) { | |
event.stopPropagation(); | |
this.setState({ | |
status: !this.state.status | |
}) | |
}, | |
render: function() { | |
var triggerChildren = [this.props.trigger.props.children]; | |
if (this.state.status) { | |
triggerChildren = triggerChildren.concat([this.props.content]); | |
} | |
return React.cloneElement( | |
this.props.trigger, | |
{ | |
onClick: this.toggleContent | |
}, | |
triggerChildren | |
); | |
} | |
}) | |
var App = React.createClass({ | |
render: function() { | |
var trigger = (<span>Click Me</span>); | |
var content = (<div>Popup!</div>); | |
return ( | |
<span onClick={Popup.hidePopups}> | |
Hello, World! | |
<Popup trigger={trigger} content={content}/> | |
</span> | |
); | |
} | |
}); | |
ReactDOM.render(<App/>, document.getElementById('app')); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment