import { Component } from "@angular/core" ; type EventTarget = Window | Document | HTMLElement ; interface EventConfig { name : string ; isStop : boolean ; isPrevent : boolean ; isCapture : boolean ; isSelf : boolean ; isOnce : boolean ; isPassive : boolean ; } export class VueEventModifiersPlugin { private supportsPassive : boolean ; constructor ( ) { this . supportsPassive = this . detectPassiveSupport ( ) ; } public addEventListener ( element , higherOrderEventName , handler ) { var eventConfig = this . parseHigherOrderEventName ( higherOrderEventName ) ; return ( this . setupEventBinding ( element , eventConfig , handler ) ) ; } public addGlobalEventListener ( higherOrderElement , higherOrderEventName , handler ) { var target = this . parseHigherOrderElement ( higherOrderElement ) ; var eventConfig = this . parseHigherOrderEventName ( higherOrderEventName ) ; return ( this . setupEventBinding ( target , eventConfig , handler ) ) ; } public supports ( eventName ) { var eventPattern = /^[a-z]+(?:\.(?:stop|prevent|capture|self|once|passive))+$/ ; return ( eventPattern . test ( eventName ) ) ; } private detectPassiveSupport ( ) { var support = false ; try { var handler = function ( ) { } ; var options = { get passive ( ) { return ( support = true ) ; } } ; window . addEventListener ( "test" , handler , options ) ; window . removeEventListener ( "test" , handler , options ) ; } catch ( error ) { } return ( support ) ; } private parseHigherOrderElement ( selector ) { switch ( selector ) { case "window" : return ( window ) ; break ; case "document" : return ( document ) ; break ; case "body" : return ( document . body ) ; break ; default : throw ( new Error ( `Element selector [${ selector }] not supported.` ) ) ; break ; } } private parseHigherOrderEventName ( eventName ) { var parts = eventName . split ( "." ) ; var config = { name : < string > parts . shift ( ) , isStop : false , isPrevent : false , isCapture : false , isSelf : false , isOnce : false , isPassive : false } ; while ( parts . length ) { switch ( parts . shift ( ) ) { case "stop" : config . isStop = true ; break ; case "prevent" : config . isPrevent = true ; break ; case "capture" : config . isCapture = true ; break ; case "self" : config . isSelf = true ; break ; case "once" : config . isOnce = true ; break ; case "passive" : config . isPassive = true ; break ; default : throw ( new Error ( `Event config [${ eventName }] not supported.` ) ) ; break ; } } return ( config ) ; } private setupEventBinding ( target , eventConfig , handler ) { var options = eventConfig . isCapture ; if ( this . supportsPassive && eventConfig . isPassive ) { options = { passive : true , capture : eventConfig . isCapture } ; } addProxyFunction ( ) ; return ( removeProxyFunction ) ; function addProxyFunction ( ) { target . addEventListener ( eventConfig . name , proxyFunction , options ) ; } function removeProxyFunction ( ) { target . removeEventListener ( eventConfig . name , proxyFunction , options ) ; } function proxyFunction ( event ) { if ( eventConfig . isSelf && ( event . target !== target ) ) { return ; } if ( eventConfig . isOnce ) { removeProxyFunction ( ) ; } if ( eventConfig . isStop ) { event . stopPropagation ( ) ; } if ( eventConfig . isPrevent ) { event . preventDefault ( ) ; } handler ( event ) ; } } }