From da4e96585cae1aa1ad2a0030a709576ff5dfad38 Mon Sep 17 00:00:00 2001 From: wwayne Date: Thu, 4 Aug 2016 18:21:01 +0800 Subject: [PATCH] Support ReactTooltip.show() #47 --- README.md | 21 ++++++++++++++++----- src/decorators/staticMethods.js | 25 +++++++++++++++++++++---- src/decorators/windowListener.js | 5 +++++ src/index.js | 15 +++++++++++---- 4 files changed, 53 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index 2f114a4c9..1e4d9937d 100644 --- a/README.md +++ b/README.md @@ -75,21 +75,32 @@ Check the example [React-tooltip Test](http://wwayne.com/react-tooltip) 3. When using react component as tooltip, you can have many `` in a page but they should have different **id** ## Static Methods -`ReactTooltip.hide()`: Hide the tooltip manually +**ReactTooltip.hide()**: Hide the tooltip manually -`ReactTooltip.rebuild()`: Rebinding tooltip to the corresponding elements +**ReactTooltip.rebuild()**: Rebinding tooltip to the corresponding elements -I suggest always put `` in the Highest level or smart component of Redux, so you might need these static -method to control tooltip's behaviour in some situations +**ReactTooltip.show(target)**: Show specific tooltip manually, for example: + +``` +import {findDOMNode} from 'react-dom' +import ReactTooltip from 'react-tooltip' + +

+ + +``` ## Trouble Shooting -#### Using tooltip within the modal (e.g. [react-modal](https://github.com/reactjs/react-modal)) +### Using tooltip within the modal (e.g. [react-modal](https://github.com/reactjs/react-modal)) The component was designed to set a `` one place then use tooltip everywhere, but a lot of people stuck in using this component with modal, you can check the discussion [here](https://github.com/wwayne/react-tooltip/issues/130), the summarization of solving the problem is as following: 1. Put `` out of the `` 2. Use `React.rebuild()` when opening the modal 3. If your modal's z-index happens to higher than the tooltip, use the attribute `class` to custom your tooltip's z-index +>I suggest always put `` in the Highest level or smart component of Redux, so you might need these static +method to control tooltip's behaviour in some situations + ## Article [How I insert sass into react component](https://medium.com/@wwayne_me/how-i-insert-sass-into-my-npm-react-component-b46b9811c226#.gi4hxu44a) diff --git a/src/decorators/staticMethods.js b/src/decorators/staticMethods.js index ebc60a59b..c837726fc 100644 --- a/src/decorators/staticMethods.js +++ b/src/decorators/staticMethods.js @@ -3,16 +3,16 @@ */ import CONSTANT from '../constant' -const dispatchGlobalEvent = (eventName) => { +const dispatchGlobalEvent = (eventName, opts) => { // Compatibale with IE // @see http://stackoverflow.com/questions/26596123/internet-explorer-9-10-11-event-constructor-doesnt-work let event - if (typeof window.Event === 'function') { - event = new window.Event(eventName) + if (typeof window.CustomEvent === 'function') { + event = new window.CustomEvent(eventName, { detail: opts }) } else { event = document.createEvent('Event') - event.initEvent(eventName, false, true) + event.initEvent(eventName, false, true, opts) } window.dispatchEvent(event) @@ -35,10 +35,27 @@ export default function (target) { dispatchGlobalEvent(CONSTANT.GLOBAL.REBUILD) } + /** + * Show specific tooltip + * @trigger ReactTooltip.show() + */ + target.show = (target) => { + dispatchGlobalEvent(CONSTANT.GLOBAL.SHOW, {target}) + } + target.prototype.globalRebuild = function () { if (this.mount) { this.unbindListener() this.bindListener() } } + + target.prototype.globalShow = function (event) { + if (this.mount) { + // Create a fake event, specific show will limit the type to `solid` + // only `float` type cares e.clientX e.clientY + const e = { currentTarget: event.detail.target } + this.showTooltip(e, true) + } + } } diff --git a/src/decorators/windowListener.js b/src/decorators/windowListener.js index 3420ddfcf..2489091cf 100644 --- a/src/decorators/windowListener.js +++ b/src/decorators/windowListener.js @@ -13,6 +13,10 @@ export default function (target) { window.removeEventListener(CONSTANT.GLOBAL.REBUILD, this.globalRebuild) window.addEventListener(CONSTANT.GLOBAL.REBUILD, this.globalRebuild, false) + // ReactTooltip.show + window.removeEventListener(CONSTANT.GLOBAL.SHOW, this.globalShow) + window.addEventListener(CONSTANT.GLOBAL.SHOW, this.globalShow, false) + // Resize window.removeEventListener('resize', this.onWindowResize) window.addEventListener('resize', this.onWindowResize, false) @@ -21,6 +25,7 @@ export default function (target) { target.prototype.unbindWindowEvents = function () { window.removeEventListener(CONSTANT.GLOBAL.HIDE, this.hideTooltip) window.removeEventListener(CONSTANT.GLOBAL.REBUILD, this.globalRebuild) + window.removeEventListener(CONSTANT.GLOBAL.SHOW, this.globalShow) window.removeEventListener('resize', this.onWindowResize) } diff --git a/src/index.js b/src/index.js index bb87addae..7b7d968ba 100644 --- a/src/index.js +++ b/src/index.js @@ -71,6 +71,7 @@ class ReactTooltip extends Component { 'updateTooltip', 'hideTooltip', 'globalRebuild', + 'globalShow', 'onWindowResize' ]) @@ -198,7 +199,13 @@ class ReactTooltip extends Component { /** * When mouse enter, show the tooltip */ - showTooltip (e) { + showTooltip (e, isGlobalCall) { + if (isGlobalCall) { + // Don't trigger other elements belongs to other ReactTooltip + const targetArray = this.getTargetArray(this.props.id) + const isMyElement = targetArray.some(ele => ele === e.currentTarget) + if (!isMyElement || this.state.show) return + } // Get the tooltip content // calculate in this phrase so that tip width height can be detected const {children, multiline, getContent} = this.props @@ -216,13 +223,13 @@ class ReactTooltip extends Component { } const placeholder = getTipContent(originTooltip, content, isMultiline) - // If it is focus event, switch to `solid` effect - const isFocus = e instanceof window.FocusEvent + // If it is focus event or called by ReactTooltip.show, switch to `solid` effect + const switchToSolid = e instanceof window.FocusEvent || isGlobalCall this.setState({ placeholder, place: e.currentTarget.getAttribute('data-place') || this.props.place || 'top', type: e.currentTarget.getAttribute('data-type') || this.props.type || 'dark', - effect: isFocus && 'solid' || e.currentTarget.getAttribute('data-effect') || this.props.effect || 'float', + effect: switchToSolid && 'solid' || e.currentTarget.getAttribute('data-effect') || this.props.effect || 'float', offset: e.currentTarget.getAttribute('data-offset') || this.props.offset || {}, html: e.currentTarget.getAttribute('data-html') ? e.currentTarget.getAttribute('data-html') === 'true'