import { VNode , VNodeData } from "../vnode" ; import { Module } from "./module" ; type Listener < T > = ( this : VNode , ev : T , vnode : VNode ) => void ; export type On = { [ N in keyof HTMLElementEventMap ] ? : Listener < HTMLElementEventMap [ N ] > | Array < Listener < HTMLElementEventMap [ N ] > > ; } & { [ event ] : Listener < any > | Array < Listener < any > > ; } ; type SomeListener < N extends keyof HTMLElementEventMap > = Listener < HTMLElementEventMap [ N ] > | Listener < any > ; function invokeHandler < N extends keyof HTMLElementEventMap > ( handler , vnode , event ? ) { if ( typeof handler === "function" ) { handler . call ( vnode , event , vnode ) ; } else if ( typeof handler === "object" ) { for ( let i = 0 ; i < handler . length ; i ++ ) { invokeHandler ( handler [ i ] , vnode , event ) ; } } } function handleEvent ( event , vnode ) { const name = event . type ; const on = ( vnode . data as VNodeData ) . on ; if ( on && on [ name ] ) { invokeHandler ( on [ name ] , vnode , event ) ; } } function createListener ( ) { return function handler ( event ) { handleEvent ( event , ( handler as any ) . vnode ) ; } ; } function updateEventListeners ( oldVnode , vnode ? ) { const oldOn = ( oldVnode . data as VNodeData ) . on ; const oldListener = ( oldVnode as any ) . listener ; const oldElm = oldVnode . elm as Element ; const on = vnode && ( vnode . data as VNodeData ) . on ; const elm = ( vnode && vnode . elm ) as Element ; let name ; if ( oldOn === on ) { return ; } if ( oldOn && oldListener ) { if ( ! on ) { for ( name in oldOn ) { oldElm . removeEventListener ( name , oldListener , false ) ; } } else { for ( name in oldOn ) { if ( ! on [ name ] ) { oldElm . removeEventListener ( name , oldListener , false ) ; } } } } if ( on ) { const listener = ( ( vnode as any ) . listener = ( oldVnode as any ) . listener || createListener ( ) ) ; listener . vnode = vnode ; if ( ! oldOn ) { for ( name in on ) { elm . addEventListener ( name , listener , false ) ; } } else { for ( name in on ) { if ( ! oldOn [ name ] ) { elm . addEventListener ( name , listener , false ) ; } } } } } export const eventListenersModule = { create : updateEventListeners , update : updateEventListeners , destroy : updateEventListeners , } ;