Skip to content

Commit 76ef6b1

Browse files
committed
Enhance custom event focus and fix repeat bind caused by bind(this)
1 parent 5b6cab9 commit 76ef6b1

File tree

3 files changed

+52
-29
lines changed

3 files changed

+52
-29
lines changed

src/decorators/customEvent.js

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -33,10 +33,12 @@ const setUntargetItems = function (currentTarget, targetArray) {
3333
}
3434
}
3535

36+
let customListener
37+
3638
export default function (target) {
3739
target.prototype.isCustomEvent = function (ele) {
3840
const {event} = this.state
39-
return event || ele.getAttribute('data-event')
41+
return event || !!ele.getAttribute('data-event')
4042
}
4143

4244
/* Bind listener for custom event */
@@ -46,13 +48,14 @@ export default function (target) {
4648
const dataEventOff = ele.getAttribute('data-event-off') || eventOff
4749

4850
dataEvent.split(' ').forEach(event => {
49-
ele.removeEventListener(event, checkStatus)
50-
ele.addEventListener(event, checkStatus.bind(this, dataEventOff), false)
51+
ele.removeEventListener(event, customListener)
52+
customListener = checkStatus.bind(this, dataEventOff)
53+
ele.addEventListener(event, customListener, false)
5154
})
5255
if (dataEventOff) {
5356
dataEventOff.split(' ').forEach(event => {
5457
ele.removeEventListener(event, this.hideTooltip)
55-
ele.addEventListener(event, ::this.hideTooltip, false)
58+
ele.addEventListener(event, this.hideTooltip, false)
5659
})
5760
}
5861
}
@@ -63,7 +66,7 @@ export default function (target) {
6366
const dataEvent = event || ele.getAttribute('data-event')
6467
const dataEventOff = eventOff || ele.getAttribute('data-event-off')
6568

66-
ele.removeEventListener(dataEvent, checkStatus)
69+
ele.removeEventListener(dataEvent, customListener)
6770
if (dataEventOff) ele.removeEventListener(dataEventOff, this.hideTooltip)
6871
}
6972
}

src/decorators/windowListener.js

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,21 +7,20 @@ export default function (target) {
77
target.prototype.bindWindowEvents = function () {
88
// ReactTooltip.hide
99
window.removeEventListener(CONSTANT.GLOBAL.HIDE, this.hideTooltip)
10-
window.addEventListener(CONSTANT.GLOBAL.HIDE, ::this.hideTooltip, false)
10+
window.addEventListener(CONSTANT.GLOBAL.HIDE, this.hideTooltip, false)
1111

1212
// ReactTooltip.rebuild
1313
window.removeEventListener(CONSTANT.GLOBAL.REBUILD, this.globalRebuild)
14-
window.addEventListener(CONSTANT.GLOBAL.REBUILD, ::this.globalRebuild, false)
14+
window.addEventListener(CONSTANT.GLOBAL.REBUILD, this.globalRebuild, false)
1515

1616
// Resize
1717
window.removeEventListener('resize', this.onWindowResize)
18-
window.addEventListener('resize', ::this.onWindowResize, false)
18+
window.addEventListener('resize', this.onWindowResize, false)
1919
}
2020

2121
target.prototype.unbindWindowEvents = function () {
2222
window.removeEventListener(CONSTANT.GLOBAL.HIDE, this.hideTooltip)
2323
window.removeEventListener(CONSTANT.GLOBAL.REBUILD, this.globalRebuild)
24-
window.removeEventListener(CONSTANT.GLOBAL.REBUILD, this.globalShow)
2524
window.removeEventListener('resize', this.onWindowResize)
2625
}
2726

src/index.js

Lines changed: 41 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -61,12 +61,29 @@ class ReactTooltip extends Component {
6161
currentTarget: null // Current target of mouse event
6262
}
6363

64+
this.bind([
65+
'showTooltip',
66+
'updateTooltip',
67+
'hideTooltip',
68+
'globalRebuild',
69+
'onWindowResize'
70+
])
71+
6472
this.mount = true
6573
this.delayShowLoop = null
6674
this.delayHideLoop = null
6775
this.intervalUpdateContent = null
6876
}
6977

78+
/**
79+
* For unify the bind and unbind listener
80+
*/
81+
bind (methodArray) {
82+
methodArray.forEach(method => {
83+
this[method] = this[method].bind(this)
84+
})
85+
}
86+
7087
componentDidMount () {
7188
this.setStyleHeader() // Set the style to the <link>
7289
this.bindListener() // Bind listener for tooltip
@@ -115,27 +132,24 @@ class ReactTooltip extends Component {
115132
if (target.getAttribute('currentItem') === null) {
116133
target.setAttribute('currentItem', 'false')
117134
}
135+
this.unbindBasicListener(target)
118136

119137
if (this.isCustomEvent(target)) {
120138
this.customBindListener(target)
121139
return
122140
}
123141

124-
target.removeEventListener('mouseenter', this.showTooltip)
125-
target.addEventListener('mouseenter', ::this.showTooltip, isCaptureMode)
142+
target.addEventListener('mouseenter', this.showTooltip, isCaptureMode)
126143
if (this.state.effect === 'float') {
127-
target.removeEventListener('mousemove', this.updateTooltip)
128-
target.addEventListener('mousemove', ::this.updateTooltip, isCaptureMode)
144+
target.addEventListener('mousemove', this.updateTooltip, isCaptureMode)
129145
}
130-
131-
target.removeEventListener('mouseleave', this.hideTooltip)
132-
target.addEventListener('mouseleave', ::this.hideTooltip, isCaptureMode)
146+
target.addEventListener('mouseleave', this.hideTooltip, isCaptureMode)
133147
})
134148

135149
// Global event to hide tooltip
136150
if (globalEventOff) {
137151
window.removeEventListener(globalEventOff, this.hideTooltip)
138-
window.addEventListener(globalEventOff, ::this.hideTooltip, false)
152+
window.addEventListener(globalEventOff, this.hideTooltip, false)
139153
}
140154
}
141155

@@ -145,21 +159,25 @@ class ReactTooltip extends Component {
145159
unbindListener () {
146160
const {id, globalEventOff} = this.props
147161
const targetArray = this.getTargetArray(id)
148-
149162
targetArray.forEach(target => {
150-
if (this.isCustomEvent(target)) {
151-
this.customUnbindListener(target)
152-
return
153-
}
154-
155-
target.removeEventListener('mouseenter', this.showTooltip)
156-
target.removeEventListener('mousemove', this.updateTooltip)
157-
target.removeEventListener('mouseleave', this.hideTooltip)
163+
this.unbindBasicListener(target)
164+
if (this.isCustomEvent(target)) this.customUnbindListener(target)
158165
})
159166

160167
if (globalEventOff) window.removeEventListener(globalEventOff, this.hideTooltip)
161168
}
162169

170+
/**
171+
* Invoke this before bind listener and ummount the compont
172+
* it is necessary to invloke this even when binding custom event
173+
* so that the tooltip can switch between custom and default listener
174+
*/
175+
unbindBasicListener (target) {
176+
target.removeEventListener('mouseenter', this.showTooltip)
177+
target.removeEventListener('mousemove', this.updateTooltip)
178+
target.removeEventListener('mouseleave', this.hideTooltip)
179+
}
180+
163181
/**
164182
* When mouse enter, show the tooltip
165183
*/
@@ -170,6 +188,7 @@ class ReactTooltip extends Component {
170188
const originTooltip = e.currentTarget.getAttribute('data-tip')
171189
const isMultiline = e.currentTarget.getAttribute('data-multiline') || multiline || false
172190

191+
// Generate tootlip content
173192
let content = children
174193
if (getContent) {
175194
if (Array.isArray(getContent)) {
@@ -178,14 +197,16 @@ class ReactTooltip extends Component {
178197
content = getContent()
179198
}
180199
}
181-
182200
const placeholder = getTipContent(originTooltip, content, isMultiline)
183201

202+
// If e is instance of FocusEvent, switch to `solid` effect
203+
const isFocus = e instanceof FocusEvent
204+
184205
this.setState({
185206
placeholder,
186207
place: e.currentTarget.getAttribute('data-place') || this.props.place || 'top',
187208
type: e.currentTarget.getAttribute('data-type') || this.props.type || 'dark',
188-
effect: e.currentTarget.getAttribute('data-effect') || this.props.effect || 'float',
209+
effect: isFocus && 'solid' || e.currentTarget.getAttribute('data-effect') || this.props.effect || 'float',
189210
offset: e.currentTarget.getAttribute('data-offset') || this.props.offset || {},
190211
html: e.currentTarget.getAttribute('data-html') === 'true' || this.props.html || false,
191212
delayShow: e.currentTarget.getAttribute('data-delay-show') || this.props.delayShow || 0,
@@ -255,7 +276,7 @@ class ReactTooltip extends Component {
255276
*/
256277
addScrollListener (e) {
257278
const isCaptureMode = this.isCapture(e.currentTarget)
258-
window.addEventListener('scroll', ::this.hideTooltip, isCaptureMode)
279+
window.addEventListener('scroll', this.hideTooltip, isCaptureMode)
259280
}
260281

261282
removeScrollListener () {

0 commit comments

Comments
 (0)