2019-07-17 01:35:11 +08:00
class ClickOutsideDelegate {
constructor ( ) {
2019-07-17 14:40:28 +08:00
console . debug ( '[ClickOutsideDelegate]: Ctor called' )
2019-07-17 01:35:11 +08:00
this . handlers = new Map ( )
this . handlerCount = 0
this . handleClickOutside = this . handleClickOutside . bind ( this )
}
handleClickOutside ( 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 ) {
2019-07-17 14:40:28 +08:00
console . debug ( '[ClickOutsideDelegate]: unregisterHandler' )
2019-07-17 01:35:11 +08:00
const h = this . handlers . get ( handler )
if ( h ) {
2019-07-22 15:15:55 +08:00
console . debug ( '[ClickOutsideDelegate.unregisterHandler]: handler found' )
2019-07-18 00:32:01 +08:00
this . handlers . delete ( handler )
2019-07-17 01:35:11 +08:00
-- this . handlerCount
2019-07-22 15:15:55 +08:00
console . debug ( '[ClickOutsideDelegate.unregisterHandler]: handler unregistered' )
} else {
console . debug ( '[ClickOutsideDelegate.unregisterHandler]: handler not found' )
2019-07-17 01:35:11 +08:00
}
if ( ! this . handlerCount ) {
2019-07-17 14:40:28 +08:00
console . debug ( '[ClickOutsideDelegate]: remove handler from window' )
2019-07-22 17:41:56 +08:00
window . removeEventListener ( 'click' , this . handleClickOutside )
2019-07-17 01:35:11 +08:00
this . handlers = new Map ( )
}
}
registerHandler ( els , handler , once = true ) {
if ( ! Array . isArray ( els ) ) {
els = [ els ]
}
for ( const el of els ) {
2019-07-17 14:40:28 +08:00
if ( ! el ) throw new Error ( '[ClickOutsideDelegate.registerHandler]: make sure `el` is an HTMLElement' )
2019-07-17 01:35:11 +08:00
}
if ( this . handlers . get ( handler ) ) {
2019-07-22 17:41:56 +08:00
throw new Error ( '[ClickOutsideDelegate.registerHandler]: don\'t register duplicate event handler, if you want to do it, unregister this handler and reregister it.' )
2019-07-17 01:35:11 +08:00
}
if ( ! this . handlerCount ) {
2019-07-17 14:40:28 +08:00
console . debug ( '[ClickOutsideDelegate]: add handler to window' )
2019-07-22 17:41:56 +08:00
window . addEventListener ( 'click' , this . handleClickOutside )
2019-07-17 01:35:11 +08:00
}
++ this . handlerCount
this . handlers . set ( handler , { els , once } )
window . x = this . handlers
}
}
export default new ClickOutsideDelegate ( )