name version author flamewave000
 *  license see https see https if ( ! ( < any > globalThis ) . HooksExt ) { /**
     * A simple event framework used throughout Foundry Virtual Tabletop.
     * When key actions or events occur, a "hook" is defined where user-defined callback functions can execute.
     * This class manages the registration and execution of hooked callback functions.
     */ class _HooksExt { /** Registry of RegExp based hooks */ static readonly _regex = new Map < string , { regex : RegExp ; fns : number [ ] ; } > ( ) ; /** Repository of all hooks ever invoked. This is only ever used when `CONFIG.debug.hooks` is `true` */ static readonly _hookRepo = new Set < string > ( ) ; param { string | RegExp } hook param { Function } fn return { number } static on ( hook , fn ) { console . debug ( `${ vtt } | Registered callback for ${ hook } hook` ) ; const id = Hooks . _id ++ ; if ( hook instanceof RegExp ) { const pattern = hook . toString ( ) ; let regex = this . _regex . get ( pattern ) ; if ( ! regex ) { regex = { regex : hook , fns : [ ] } ; this . _regex . set ( pattern , regex ) ; } regex . fns . push ( id ) ; Hooks . _hooks [ pattern ] = Hooks . _hooks [ pattern ] || [ ] ; Hooks . _hooks [ pattern ] . push ( fn ) ; } else { Hooks . _hooks [ hook ] = Hooks . _hooks [ hook ] || [ ] ; Hooks . _hooks [ hook ] . push ( fn ) ; } Hooks . _ids [ id ] = fn ; return id ; } param { string | RegExp } hook param { Function | number } fn static off ( hook , fn ) { if ( typeof fn === "number" ) { const id = fn ; fn = Hooks . _ids [ fn ] ; delete Hooks . _ids [ id ] ; } else { const entry = Object . entries ( Hooks . _ids ) . find ( x => x [ 1 ] === fn ) ; if ( entry ) delete Hooks . _ids [ parseInt ( entry [ 0 ] ) ] ; } if ( hook instanceof RegExp ) hook = hook . toString ( ) ; this . _regex . delete ( hook ) ; if ( ! Hooks . _hooks . hasOwnProperty ( hook ) ) return ; const fns = Hooks . _hooks [ hook ] ; const idx = fns . indexOf ( fn ) ; if ( idx !== - 1 ) fns . splice ( idx , 1 ) ; console . debug ( `${ vtt } | Unregistered callback for ${ hook } hook` ) ; } param { string } hook param { ... * } args returns { boolean } static callAll ( hook , ... args ) { if ( CONFIG . debug . hooks ) { console . log ( `DEBUG | Calling ${ hook } hook with args:` ) ; console . log ( args ) ; this . _hookRepo . add ( hook ) ; } for ( const regex of this . _regex ) { if ( ! regex [ 1 ] . regex . test ( hook ) ) continue ; for ( const fnId of regex [ 1 ] . fns ) Hooks . _call ( hook , Hooks . _ids [ fnId ] , args ) ; } if ( ! Hooks . _hooks . hasOwnProperty ( hook ) ) return true ; const fns = new Array ( ... Hooks . _hooks [ hook ] ) ; for ( const fn of fns ) { Hooks . _call ( hook , fn , args ) ; } return true ; } param { string } hook param { ... * } args returns { boolean } static call ( hook , ... args ) { if ( CONFIG . debug . hooks ) { console . log ( `DEBUG | Calling ${ hook } hook with args:` ) ; console . log ( args ) ; this . _hookRepo . add ( hook ) ; } let fns = [ ] ; for ( const regex of this . _regex ) { if ( regex [ 1 ] . regex . test ( hook ) ) fns = fns . concat ( regex [ 1 ] . fns . map ( x => Hooks . _ids [ x ] ) ) ; } const hooksExist = Hooks . _hooks . hasOwnProperty ( hook ) ; if ( ! hooksExist && fns . length == 0 ) return true ; if ( hooksExist ) fns = fns . concat ( ... Hooks . _hooks [ hook ] ) ; for ( const fn of fns ) { const callAdditional = Hooks . _call ( hook , fn , args ) ; if ( callAdditional === false ) return false ; } return true ; } returns static allUniqueHooks ( ) { return [ ... this . _hookRepo . values ( ) ] ; } } ( < any > globalThis ) . HooksExt = _HooksExt ; Hooks . on = < any > _HooksExt . on . bind ( _HooksExt ) ; Hooks . off = < any > _HooksExt . off . bind ( _HooksExt ) ; Hooks . callAll = < any > _HooksExt . callAll . bind ( _HooksExt ) ; Hooks . call = < any > _HooksExt . call . bind ( _HooksExt ) ; }