Skip to content

Commit 853e371

Browse files
committed
Progress
1 parent 732b1bc commit 853e371

File tree

3 files changed

+83
-116
lines changed

3 files changed

+83
-116
lines changed

src/decorators/windowListener.js

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,20 +6,20 @@ import CONSTANT from '../constant'
66
export default function (target) {
77
target.prototype.bindWindowEvents = function () {
88
// ReactTooltip.hide
9-
window.removeEventListener(CONSTANT.GLOBAL.HIDE, this.globalHide)
10-
window.addEventListener(CONSTANT.GLOBAL.HIDE, this.globalHide, false)
9+
window.removeEventListener(CONSTANT.GLOBAL.HIDE, this.hideTooltip)
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 () {
22-
window.removeEventListener(CONSTANT.GLOBAL.HIDE, this.globalHide)
22+
window.removeEventListener(CONSTANT.GLOBAL.HIDE, this.hideTooltip)
2323
window.removeEventListener(CONSTANT.GLOBAL.REBUILD, this.globalRebuild)
2424
window.removeEventListener('resize', this.onWindowResize)
2525
}

src/index.js

Lines changed: 75 additions & 109 deletions
Original file line numberDiff line numberDiff line change
@@ -13,51 +13,28 @@ import cssStyle from './style'
1313

1414
@staticMethods @windowListener
1515
class ReactTooltip extends Component {
16-
/**
17-
* Class method
18-
* @see ReactTooltip.hide() && ReactTooltup.rebuild()
19-
*/
20-
// static hide () {
21-
// /**
22-
// * Check for ie
23-
// * @see http://stackoverflow.com/questions/26596123/internet-explorer-9-10-11-event-constructor-doesnt-work
24-
// */
25-
// if (typeof window.Event === 'function') {
26-
// window.dispatchEvent(new window.Event('__react_tooltip_hide_event'))
27-
// } else {
28-
// let event = document.createEvent('Event')
29-
// event.initEvent('__react_tooltip_hide_event', false, true)
30-
// window.dispatchEvent(event)
31-
// }
32-
// }
33-
34-
// static rebuild () {
35-
// if (typeof window.Event === 'function') {
36-
// window.dispatchEvent(new window.Event('__react_tooltip_rebuild_event'))
37-
// } else {
38-
// let event = document.createEvent('Event')
39-
// event.initEvent('__react_tooltip_rebuild_event', false, true)
40-
// window.dispatchEvent(event)
41-
// }
42-
// }
43-
44-
globalHide () {
45-
if (this.mount) {
46-
this.hideTooltip()
47-
}
48-
}
4916

50-
globalRebuild () {
51-
if (this.mount) {
52-
this.unbindListener()
53-
this.bindListener()
54-
}
17+
static propTypes = {
18+
children: PropTypes.any,
19+
place: PropTypes.string,
20+
type: PropTypes.string,
21+
effect: PropTypes.string,
22+
offset: PropTypes.object,
23+
multiline: PropTypes.bool,
24+
border: PropTypes.bool,
25+
class: PropTypes.string,
26+
id: PropTypes.string,
27+
html: PropTypes.bool,
28+
delayHide: PropTypes.number,
29+
delayShow: PropTypes.number,
30+
event: PropTypes.any,
31+
eventOff: PropTypes.any,
32+
watchWindow: PropTypes.bool,
33+
isCapture: PropTypes.bool
5534
}
5635

5736
constructor (props) {
5837
super(props)
59-
this._bind('showTooltip', 'updateTooltip', 'hideTooltip', 'checkStatus', 'onWindowResize', 'bindClickListener', 'globalHide', 'globalRebuild')
60-
this.mount = true
6138
this.state = {
6239
show: false,
6340
border: false,
@@ -78,28 +55,16 @@ class ReactTooltip extends Component {
7855
eventOff: props.eventOff || null,
7956
isCapture: props.isCapture || false
8057
}
58+
59+
this.mount = true
8160
this.delayShowLoop = null
8261
this.delayHideLoop = null
8362
}
8463

85-
/* Bind this with method */
86-
_bind (...handlers) {
87-
handlers.forEach(handler => this[handler] = this[handler].bind(this))
88-
}
89-
9064
componentDidMount () {
9165
this.bindListener()
9266
this.setStyleHeader()
9367
this.bindWindowEvents()
94-
// /* Add window event listener for hide and rebuild */
95-
// window.removeEventListener('__react_tooltip_hide_event', this.globalHide)
96-
// window.addEventListener('__react_tooltip_hide_event', this.globalHide, false)
97-
98-
// window.removeEventListener('__react_tooltip_rebuild_event', this.globalRebuild)
99-
// window.addEventListener('__react_tooltip_rebuild_event', this.globalRebuild, false)
100-
// /* Add listener on window resize */
101-
// window.removeEventListener('resize', this.onWindowResize)
102-
// window.addEventListener('resize', this.onWindowResize, false)
10368
}
10469

10570
componentWillUpdate () {
@@ -118,61 +83,78 @@ class ReactTooltip extends Component {
11883
this.removeScrollListener()
11984
this.mount = false
12085
this.unbindWindowEvents()
121-
// window.removeEventListener('__react_tooltip_hide_event', this.globalHide)
122-
// window.removeEventListener('__react_tooltip_rebuild_event', this.globalRebuild)
123-
// window.removeEventListener('resize', this.onWindowResize)
12486
}
12587

126-
/* TODO: optimize, bind has been trigger too many times */
88+
/*
89+
* Rebind the tooltip
90+
* Invoked by ReactTooltip.rebuild()
91+
*/
92+
globalRebuild () {
93+
if (this.mount) {
94+
this.unbindListener()
95+
this.bindListener()
96+
}
97+
}
98+
99+
/**
100+
* Bind listener to the target elements
101+
* These listeners used to trigger showing or hiding the tooltip
102+
*/
127103
bindListener () {
128104
let targetArray = this.getTargetArray()
129105

130106
let dataEvent
131107
let dataEventOff
132-
for (let i = 0; i < targetArray.length; i++) {
133-
if (targetArray[i].getAttribute('currentItem') === null) {
134-
targetArray[i].setAttribute('currentItem', 'false')
108+
targetArray.forEach(target => {
109+
if (target.getAttribute('currentItem') === null) {
110+
target.setAttribute('currentItem', 'false')
135111
}
136-
dataEvent = this.state.event || targetArray[i].getAttribute('data-event')
137-
if (dataEvent) {
138-
// if off event is specified, we will show tip on data-event and hide it on data-event-off
139-
dataEventOff = this.state.eventOff || targetArray[i].getAttribute('data-event-off')
140112

141-
targetArray[i].removeEventListener(dataEvent, this.checkStatus)
142-
targetArray[i].addEventListener(dataEvent, this.checkStatus, false)
113+
dataEvent = this.state.event || target.getAttribute('data-event')
114+
dataEventOff = this.state.eventOff || target.getAttribute('data-event-off')
115+
116+
if (dataEvent) {
117+
target.removeEventListener(dataEvent, this.checkStatus)
118+
target.addEventListener(dataEvent, ::this.checkStatus, false)
143119
if (dataEventOff) {
144-
targetArray[i].removeEventListener(dataEventOff, this.hideTooltip)
145-
targetArray[i].addEventListener(dataEventOff, this.hideTooltip, false)
120+
target.removeEventListener(dataEventOff, this.hideTooltip)
121+
target.addEventListener(dataEventOff, ::this.hideTooltip, false)
146122
}
147-
} else {
148-
targetArray[i].removeEventListener('mouseenter', this.showTooltip)
149-
targetArray[i].addEventListener('mouseenter', this.showTooltip, false)
123+
return
124+
}
150125

151-
if (this.state.effect === 'float') {
152-
targetArray[i].removeEventListener('mousemove', this.updateTooltip)
153-
targetArray[i].addEventListener('mousemove', this.updateTooltip, false)
154-
}
126+
target.removeEventListener('mouseenter', this.showTooltip)
127+
target.addEventListener('mouseenter', ::this.showTooltip, false)
155128

156-
targetArray[i].removeEventListener('mouseleave', this.hideTooltip)
157-
targetArray[i].addEventListener('mouseleave', this.hideTooltip, false)
129+
if (this.state.effect === 'float') {
130+
target.removeEventListener('mousemove', this.updateTooltip)
131+
target.addEventListener('mousemove', ::this.updateTooltip, false)
158132
}
159-
}
133+
134+
target.removeEventListener('mouseleave', this.hideTooltip)
135+
target.addEventListener('mouseleave', ::this.hideTooltip, false)
136+
})
160137
}
161138

139+
/**
140+
* Unbind listeners on target elements
141+
*/
162142
unbindListener () {
163143
let targetArray = document.querySelectorAll('[data-tip]')
164144
let dataEvent
165145

166-
for (let i = 0; i < targetArray.length; i++) {
167-
dataEvent = this.state.event || targetArray[i].getAttribute('data-event')
146+
targetArray.forEach(target => {
147+
dataEvent = this.state.event || target.getAttribute('data-event')
168148
if (dataEvent) {
169-
targetArray[i].removeEventListener(dataEvent, this.checkStatus)
170-
} else {
171-
targetArray[i].removeEventListener('mouseenter', this.showTooltip)
172-
targetArray[i].removeEventListener('mousemove', this.updateTooltip)
173-
targetArray[i].removeEventListener('mouseleave', this.hideTooltip)
149+
target.removeEventListener(dataEvent, this.checkStatus)
150+
if (dataEventOff) target.removeEventListener(dataEventOff, this.hideTooltip)
151+
return
174152
}
175-
}
153+
154+
target.removeEventListener('mouseenter', this.showTooltip)
155+
target.removeEventListener('mousemove', this.updateTooltip)
156+
target.removeEventListener('mouseleave', this.hideTooltip)
157+
})
176158
}
177159

178160
/**
@@ -232,7 +214,7 @@ class ReactTooltip extends Component {
232214
e.currentTarget.setAttribute('currentItem', 'true')
233215
/* when click other place, the tooltip should be removed */
234216
window.removeEventListener('click', this.bindClickListener)
235-
window.addEventListener('click', this.bindClickListener, isCapture)
217+
window.addEventListener('click', ::this.bindClickListener, isCapture)
236218

237219
this.showTooltip(e)
238220
this.setUntargetItems(e.currentTarget)
@@ -251,7 +233,7 @@ class ReactTooltip extends Component {
251233
}
252234

253235
bindClickListener () {
254-
this.globalHide()
236+
this.hideTooltip()
255237
window.removeEventListener('click', this.bindClickListener)
256238
}
257239

@@ -331,6 +313,9 @@ class ReactTooltip extends Component {
331313
*/
332314
hideTooltip () {
333315
const {delayHide} = this.state
316+
317+
if (!this.mount) return
318+
334319
clearTimeout(this.delayShowLoop)
335320
clearTimeout(this.delayHideLoop)
336321
this.delayHideLoop = setTimeout(() => {
@@ -346,7 +331,7 @@ class ReactTooltip extends Component {
346331
* or tooltip will always existed
347332
*/
348333
addScrollListener () {
349-
window.addEventListener('scroll', this.hideTooltip)
334+
window.addEventListener('scroll', ::this.hideTooltip)
350335
}
351336

352337
removeScrollListener () {
@@ -668,24 +653,5 @@ class ReactTooltip extends Component {
668653

669654
}
670655

671-
ReactTooltip.propTypes = {
672-
children: PropTypes.any,
673-
place: PropTypes.string,
674-
type: PropTypes.string,
675-
effect: PropTypes.string,
676-
offset: PropTypes.object,
677-
multiline: PropTypes.bool,
678-
border: PropTypes.bool,
679-
class: PropTypes.string,
680-
id: PropTypes.string,
681-
html: PropTypes.bool,
682-
delayHide: PropTypes.number,
683-
delayShow: PropTypes.number,
684-
event: PropTypes.any,
685-
eventOff: PropTypes.any,
686-
watchWindow: PropTypes.bool,
687-
isCapture: PropTypes.bool
688-
}
689-
690656
/* export default not fit for standalone, it will exports {default:...} */
691657
module.exports = ReactTooltip

test/globalMethods.test.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,15 @@ describe('Global methods', () => {
1515
it('should be hided by invoking ReactTooltip.hide', () => {
1616
const wrapper = mount(<ReactTooltip />)
1717
wrapper.setState({ show: true })
18-
expect(wrapper).to.have.state('show', true)
18+
sinon.spy(ReactTooltip.prototype, 'hideTooltip')
1919
ReactTooltip.hide()
2020
setImmediate(() => {
21+
expect(ReactTooltip.prototype.hideTooltip.calledOnce).to.equal(true)
2122
expect(wrapper).to.have.state('show', false)
2223
})
2324
})
2425

25-
it('should be rebuild by invoking ReactTooltip.rebuild', () => {
26+
it('should invoke globalRebuild when using ReactTooltip.rebuild', () => {
2627
sinon.spy(ReactTooltip.prototype, 'globalRebuild')
2728
ReactTooltip.rebuild()
2829
setImmediate(() => {

0 commit comments

Comments
 (0)