mirror of
https://github.com/tusen-ai/naive-ui.git
synced 2024-12-27 05:00:48 +08:00
ffad17ff1f
mouseleave event sometimes can't fire. So I detect mouseout outside the popover and activator to make it disappear. Implementation has many tricks. Sigh, life is so hard.
69 lines
2.0 KiB
JavaScript
69 lines
2.0 KiB
JavaScript
class MoveOutsideDelegate {
|
|
constructor () {
|
|
console.debug('[MoveOutsideDelegate]: Ctor called')
|
|
this.handlers = new Map()
|
|
this.handlerCount = 0
|
|
this.handleMoveOutside = this.handleMoveOutside.bind(this)
|
|
}
|
|
handleMoveOutside (e) {
|
|
const target = e.target
|
|
for (const [handler, { els, once }] of this.handlers) {
|
|
let existElContainTarget = false
|
|
for (const el of els) {
|
|
if (el) {
|
|
if (typeof el === 'function') {
|
|
const unwrappedEl = el()
|
|
if (unwrappedEl && unwrappedEl.contains(target)) {
|
|
existElContainTarget = true
|
|
break
|
|
}
|
|
} else if (el.contains(target)) {
|
|
existElContainTarget = true
|
|
break
|
|
}
|
|
}
|
|
}
|
|
if (existElContainTarget) continue
|
|
else {
|
|
handler(e)
|
|
if (once) {
|
|
this.unregisterHandler(handler)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
unregisterHandler (handler) {
|
|
console.debug('[MoveOutsideDelegate]: unregisterHandler')
|
|
const h = this.handlers.get(handler)
|
|
if (h) {
|
|
this.handlers.delete(handler)
|
|
--this.handlerCount
|
|
}
|
|
if (!this.handlerCount) {
|
|
console.debug('[MoveOutsideDelegate]: remove handler from window')
|
|
window.removeEventListener('mousemove', this.handleMoveOutside, true)
|
|
this.handlers = new Map()
|
|
}
|
|
}
|
|
registerHandler (els, handler, once = true) {
|
|
if (!Array.isArray(els)) {
|
|
els = [els]
|
|
}
|
|
for (const el of els) {
|
|
if (!el) throw new Error('[MoveOutsideDelegate.registerHandler]: make sure `el` is an HTMLElement')
|
|
}
|
|
if (this.handlers.get(handler)) {
|
|
this.handlers.set(handler, { els, once })
|
|
return
|
|
}
|
|
if (!this.handlerCount) {
|
|
console.debug('[MoveOutsideDelegate]: add handler to window')
|
|
window.addEventListener('mousemove', this.handleMoveOutside, true)
|
|
}
|
|
++this.handlerCount
|
|
this.handlers.set(handler, { els, once })
|
|
}
|
|
}
|
|
|
|
export default new MoveOutsideDelegate()
|