Last active
September 8, 2016 10:25
-
-
Save schovi/e3780466f550877c9c16 to your computer and use it in GitHub Desktop.
Usage of https://github.com/Pomax/react-onclickoutside as ES6 decorator
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
import React from 'react'; | |
const IGNORE_CLASS = 'ignore-react-onclickoutside'; | |
export default function clickOutside(BaseComponent) { | |
return class ClickOutside extends React.Component { | |
static displayName = `${BaseComponent.name}ClickOutside`; | |
constructor(props) { | |
super(props) | |
} | |
componentDidMount() { | |
const component = this.refs.component | |
const componentHandler = component.onClickOutside | |
if(!componentHandler) | |
throw new Error("Component lacks a onClickOutside(event) function for processing outside click events."); | |
const makeHandler = (localNode, eventHandler) => { | |
return (evt) => { | |
var source = evt.target; | |
var found = false; | |
// If source=local then this event came from "somewhere" | |
// inside and should be ignored. We could handle this with | |
// a layered approach, too, but that requires going back to | |
// thinking in terms of Dom node nesting, running counter | |
// to React's "you shouldn't care about the DOM" philosophy. | |
while(source.parentNode) { | |
found = (source === localNode || source.classList.contains(IGNORE_CLASS)); | |
if(found) return; | |
source = source.parentNode; | |
} | |
eventHandler(evt); | |
} | |
} | |
this.__outsideClickHandler = makeHandler(React.findDOMNode(this), componentHandler.bind(component)); | |
// If there is a truthy disableOnClickOutside property for this | |
// component, don't immediately start listening for outside events. | |
if (!this.props.disableOnClickOutside) { | |
this.enableOnClickOutside(); | |
} | |
} | |
componentWillUnmount() { | |
this.disableOnClickOutside(); | |
this.__outsideClickHandler = undefined; | |
this.__callback = undefined | |
} | |
/** | |
* Can be called to explicitly enable event listening | |
* for clicks and touches outside of this element. | |
*/ | |
enableOnClickOutside() { | |
const fn = this.__outsideClickHandler; | |
document.addEventListener("mousedown", fn); | |
document.addEventListener("touchstart", fn); | |
} | |
handleClickOutside(ev) { | |
handler && handler(ev) | |
} | |
/** | |
* Can be called to explicitly disable event listening | |
* for clicks and touches outside of this element. | |
*/ | |
disableOnClickOutside() { | |
const fn = this.__outsideClickHandler; | |
document.removeEventListener("mousedown", fn); | |
document.removeEventListener("touchstart", fn); | |
} | |
render() { | |
return <BaseComponent {...this.props} ref="component"/>; | |
} | |
}; | |
} |
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
import React from 'react'; | |
import clickOutside from './click_outside_decorator' | |
@clickOutside | |
export default class MyComponent extends React.Component { | |
onClickOutside() { | |
console.log("Click outside") | |
} | |
onClickInside() { | |
console.log("Click inside") | |
} | |
render() { | |
return ( | |
<div onClick={this.onClickInside}> | |
... | |
</div> | |
); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Where this variable is coming from: https://gist.github.com/schovi/e3780466f550877c9c16#file-click_outside_decorator-js-L70
?