react-onclickoutside
Advanced tools
Comparing version 5.3.3 to 5.4.0
29
index.js
@@ -36,3 +36,3 @@ /** | ||
*/ | ||
var generateOutsideCheck = function(componentNode, componentInstance, ignoreClass, preventDefault, stopPropagation) { | ||
var generateOutsideCheck = function(componentNode, componentInstance, eventHandler, ignoreClass, preventDefault, stopPropagation) { | ||
return function(evt) { | ||
@@ -60,3 +60,3 @@ if (preventDefault) { | ||
if(current !== document) return; | ||
componentInstance.handleClickOutside.bind(componentInstance, evt)(); | ||
eventHandler(evt); | ||
} | ||
@@ -69,3 +69,5 @@ }; | ||
* in order to impart onOutsideClick listening to an | ||
* arbitrary component. | ||
* arbitrary component. It gets called at the end of the | ||
* bootstrapping code to yield an instance of the | ||
* onClickOutsideHOC function defined inside setupHOC(). | ||
*/ | ||
@@ -75,3 +77,3 @@ function setupHOC(root, React, ReactDOM) { | ||
// The actual Component-wrapping HOC: | ||
return function(Component) { | ||
return function onClickOutsideHOC(Component, config) { | ||
var wrapComponentWithOnClickOutsideHandling = React.createClass({ | ||
@@ -106,5 +108,14 @@ statics: { | ||
var instance = this.getInstance(); | ||
var clickOutsideHandler; | ||
if(typeof instance.handleClickOutside !== "function") { | ||
throw new Error("Component lacks a handleClickOutside(event) function for processing outside click events."); | ||
if(config && typeof config.handleClickOutside === "function") { | ||
clickOutsideHandler = config.handleClickOutside(instance); | ||
if(typeof clickOutsideHandler !== "function") { | ||
throw new Error("Component lacks a function for processing outside click events specified by the handleClickOutside config option."); | ||
} | ||
} else { | ||
if(typeof instance.handleClickOutside !== "function") { | ||
throw new Error("Component lacks a handleClickOutside(event) function for processing outside click events."); | ||
} | ||
clickOutsideHandler = instance.handleClickOutside; | ||
} | ||
@@ -115,2 +126,3 @@ | ||
instance, | ||
clickOutsideHandler, | ||
this.props.outsideClickIgnoreClass || IGNORE_CLASS, | ||
@@ -192,6 +204,9 @@ this.props.preventDefault || false, | ||
var passedProps = this.props; | ||
var props = { ref: 'instance' }; | ||
var props = {}; | ||
Object.keys(this.props).forEach(function(key) { | ||
props[key] = passedProps[key]; | ||
}); | ||
props.ref = 'instance'; | ||
props.disableOnClickOutside = this.disableOnClickOutside; | ||
props.enableOnClickOutside = this.enableOnClickOutside; | ||
return React.createElement(Component, props); | ||
@@ -198,0 +213,0 @@ } |
{ | ||
"name": "react-onclickoutside", | ||
"version": "5.3.3", | ||
"version": "5.4.0", | ||
"description": "An onClickOutside mixin for React components", | ||
@@ -5,0 +5,0 @@ "main": "index.js", |
@@ -31,5 +31,26 @@ # An onClickOutside wrapper for React components | ||
``` | ||
Note that if you try to wrap a React component class without a `handleClickOutside(evt)` handler like this, the HOC will throw an error. In order to use a custom event handler, you can specify the function to be used by the HOC as second parameter | ||
(this can be useful in environments like TypeScript, where the fact that the wrapped component does not implement the handler can be fallged at compile-time): | ||
Note that if you try to wrap a React component class without `handleClickOutside(evt)` handler, the HOC will throw an error. If you want onClickOutside functionality, you *must* have this function defined. | ||
```javascript | ||
// load the HOC: | ||
var onClickOutside = require('react-onclickoutside'); | ||
// create a new component, wrapped by this onclickoutside HOC: | ||
var MyComponent = onClickOutside(React.createClass({ | ||
..., | ||
myClickOutsideHandler: function(evt) { | ||
// ...handling code goes here... | ||
}, | ||
... | ||
}), { | ||
handleClickOutside: function(instance) { | ||
return instance.myClickOutsideHandler; | ||
} | ||
}); | ||
``` | ||
Note that if you try to wrap a React component with a custom handler that the component does not implement, the HOC will throw an error at run-time. | ||
## Regulate which events to listen for | ||
@@ -36,0 +57,0 @@ |
@@ -11,6 +11,16 @@ var React = require('react'); | ||
return { | ||
clickOutsideHandled: false | ||
clickOutsideHandled: false, | ||
timesHandlerCalled: 0 | ||
}; | ||
}, | ||
toggleEnableClickOutside: function(on) { | ||
if(on) { | ||
this.props.enableOnClickOutside(); | ||
} | ||
else { | ||
this.props.disableOnClickOutside(); | ||
} | ||
}, | ||
handleClickOutside: function(event) { | ||
@@ -22,3 +32,4 @@ if (event === undefined) { | ||
this.setState({ | ||
clickOutsideHandled: true | ||
clickOutsideHandled: true, | ||
timesHandlerCalled: this.state.timesHandlerCalled + 1 | ||
}); | ||
@@ -61,2 +72,84 @@ }, | ||
}); | ||
it('should call the specified handler when clicking the document', function() { | ||
var Component = React.createClass({ | ||
getInitialState: function() { | ||
return { | ||
clickOutsideHandled: false | ||
}; | ||
}, | ||
myOnClickHandler: function(event) { | ||
if (event === undefined) { | ||
throw new Error("event cannot be undefined"); | ||
} | ||
this.setState({ | ||
clickOutsideHandled: true | ||
}); | ||
}, | ||
render: function() { | ||
return React.createElement('div'); | ||
} | ||
}); | ||
var WrappedWithCustomHandler = wrapComponent(Component, { | ||
handleClickOutside: function (instance) { | ||
return instance.myOnClickHandler; | ||
} | ||
}); | ||
var element = React.createElement(WrappedWithCustomHandler); | ||
assert(element, "element can be created"); | ||
var component = TestUtils.renderIntoDocument(element); | ||
assert(component, "component renders correctly"); | ||
document.dispatchEvent(new Event('mousedown')); | ||
var instance = component.getInstance(); | ||
assert(instance.state.clickOutsideHandled, "clickOutsideHandled got flipped"); | ||
}); | ||
it('should throw an error when a custom handler is specified, but the component does not implement it', function() { | ||
var BadComponent = React.createClass({ | ||
render: function() { | ||
return React.createElement('div'); | ||
} | ||
}); | ||
try { | ||
var bad = wrapComponent(BadComponent, { | ||
handleClickOutside: function (instance) { | ||
return instance.nonExistentMethod; | ||
} | ||
}); | ||
assert(false, "component was wrapped, despite not implementing the custom handler"); | ||
} catch (e) { | ||
assert(e, "component was not wrapped"); | ||
} | ||
}); | ||
it('should not call handleClickOutside if this.props.disableOnClickOutside() is called, until this.props.enableOnClickOutside() is called.', function() { | ||
var element = React.createElement(WrappedComponent); | ||
var component = TestUtils.renderIntoDocument(element); | ||
document.dispatchEvent(new Event('mousedown')); | ||
var instance = component.getInstance(); | ||
assert(instance.state.timesHandlerCalled === 1, "handleClickOutside called"); | ||
try { | ||
instance.toggleEnableClickOutside(false); | ||
} | ||
catch(error) { | ||
assert(false, 'this.props.disableOnClickOutside() should not be undefined.'); | ||
} | ||
document.dispatchEvent(new Event('mousedown')); | ||
assert(instance.state.timesHandlerCalled === 1, "handleClickOutside not called after disableOnClickOutside()"); | ||
instance.toggleEnableClickOutside(true); | ||
document.dispatchEvent(new Event('mousedown')); | ||
assert(instance.state.timesHandlerCalled === 2, "handleClickOutside called after enableOnClickOutside()"); | ||
}); | ||
}); |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
25936
411
165