|
1 | 1 | /*eslint-disable react/prop-types */ |
2 | 2 | import React, { cloneElement } from 'react'; |
3 | | - |
| 3 | +import contains from 'dom-helpers/query/contains'; |
4 | 4 | import createChainedFunction from './utils/createChainedFunction'; |
5 | 5 | import createContextWrapper from './utils/createContextWrapper'; |
6 | 6 | import Overlay from './Overlay'; |
@@ -126,6 +126,11 @@ const OverlayTrigger = React.createClass({ |
126 | 126 | } |
127 | 127 | }, |
128 | 128 |
|
| 129 | + componentWillMount() { |
| 130 | + this.handleMouseOver = this.handleMouseOverOut.bind(null, this.handleDelayedShow); |
| 131 | + this.handleMouseOut = this.handleMouseOverOut.bind(null, this.handleDelayedHide); |
| 132 | + }, |
| 133 | + |
129 | 134 | componentDidMount(){ |
130 | 135 | this._mountNode = document.createElement('div'); |
131 | 136 | React.render(this._overlay, this._mountNode); |
@@ -195,8 +200,8 @@ const OverlayTrigger = React.createClass({ |
195 | 200 | '[react-bootstrap] Specifying only the `"hover"` trigger limits the visibilty of the overlay to just mouse users. ' + |
196 | 201 | 'Consider also including the `"focus"` trigger so that touch and keyboard only users can see the overlay as well.'); |
197 | 202 |
|
198 | | - props.onMouseOver = createChainedFunction(this.handleDelayedShow, this.props.onMouseOver, triggerProps.onMouseOver); |
199 | | - props.onMouseOut = createChainedFunction(this.handleDelayedHide, this.props.onMouseOut, triggerProps.onMouseOut); |
| 203 | + props.onMouseOver = createChainedFunction(this.handleMouseOver, this.props.onMouseOver, triggerProps.onMouseOver); |
| 204 | + props.onMouseOut = createChainedFunction(this.handleMouseOut, this.props.onMouseOut, triggerProps.onMouseOut); |
200 | 205 | } |
201 | 206 |
|
202 | 207 | if (isOneOf('focus', this.props.trigger)) { |
@@ -250,6 +255,19 @@ const OverlayTrigger = React.createClass({ |
250 | 255 | this._hoverDelay = null; |
251 | 256 | this.hide(); |
252 | 257 | }, delay); |
| 258 | + }, |
| 259 | + |
| 260 | + // Simple implementation of mouseEnter and mouseLeave. |
| 261 | + // React's built version is broken: https://github.com/facebook/react/issues/4251 |
| 262 | + // for cases when the trigger is disabled and mouseOut/Over can cause flicker moving |
| 263 | + // from one child element to another. |
| 264 | + handleMouseOverOut(handler, e){ |
| 265 | + let target = e.currentTarget; |
| 266 | + let related = e.relatedTarget || e.nativeEvent.toElement; |
| 267 | + |
| 268 | + if (!related || related !== target && !contains(target, related)){ |
| 269 | + handler(e); |
| 270 | + } |
253 | 271 | } |
254 | 272 |
|
255 | 273 | }); |
|
0 commit comments