basant307/AI_Governance_Project
048
1import * as util from './util/index.mjs';2import * as is from './is.mjs';3import Event from './event.mjs';4 5const eventRegex = /^([^.]+)(\.(?:[^.]+))?$/; // regex for matching event strings (e.g. "click.namespace")6const universalNamespace = '.*'; // matches as if no namespace specified and prevents users from unbinding accidentally7 8const defaults = {9 qualifierCompare: function( q1, q2 ){10 return q1 === q2;11 },12 eventMatches: function( /*context, listener, eventObj*/ ){13 return true;14 },15 addEventFields: function( /*context, evt*/ ){16 },17 callbackContext: function( context/*, listener, eventObj*/ ){18 return context;19 },20 beforeEmit: function(/* context, listener, eventObj */){21 },22 afterEmit: function(/* context, listener, eventObj */){23 },24 bubble: function( /*context*/ ){25 return false;26 },27 parent: function( /*context*/ ){28 return null;29 },30 context: null31};32 33let defaultsKeys = Object.keys( defaults );34let emptyOpts = {};35 36function Emitter( opts = emptyOpts, context ){37 // micro-optimisation vs Object.assign() -- reduces Element instantiation time38 for( let i = 0; i < defaultsKeys.length; i++ ){39 let key = defaultsKeys[i];40 41 this[key] = opts[key] || defaults[key];42 }43 44 this.context = context || this.context;45 this.listeners = [];46 this.emitting = 0;47}48 49let p = Emitter.prototype;50 51let forEachEvent = function( self, handler, events, qualifier, callback, conf, confOverrides ){52 if( is.fn( qualifier ) ){53 callback = qualifier;54 qualifier = null;55 }56 57 if( confOverrides ){58 if( conf == null ){59 conf = confOverrides;60 } else {61 conf = util.assign( {}, conf, confOverrides );62 }63 }64 65 let eventList = is.array(events) ? events : events.split(/\s+/);66 67 for( let i = 0; i < eventList.length; i++ ){68 let evt = eventList[i];69 70 if( is.emptyString( evt ) ){ continue; }71 72 let match = evt.match( eventRegex ); // type[.namespace]73 74 if( match ){75 let type = match[1];76 let namespace = match[2] ? match[2] : null;77 let ret = handler( self, evt, type, namespace, qualifier, callback, conf );78 79 if( ret === false ){ break; } // allow exiting early80 }81 }82};83 84let makeEventObj = function( self, obj ){85 self.addEventFields( self.context, obj );86 87 return new Event( obj.type, obj );88};89 90let forEachEventObj = function( self, handler, events ){91 if( is.event( events ) ){92 handler( self, events );93 94 return;95 } else if( is.plainObject( events ) ){96 handler( self, makeEventObj( self, events ) );97 98 return;99 }100 101 let eventList = is.array(events) ? events : events.split(/\s+/);102 103 for( let i = 0; i < eventList.length; i++ ){104 let evt = eventList[i];105 106 if( is.emptyString( evt ) ){ continue; }107 108 let match = evt.match( eventRegex ); // type[.namespace]109 110 if( match ){111 let type = match[1];112 let namespace = match[2] ? match[2] : null;113 let eventObj = makeEventObj( self, {114 type: type,115 namespace: namespace,116 target: self.context117 } );118 119 handler( self, eventObj );120 }121 }122};123 124p.on = p.addListener = function( events, qualifier, callback, conf, confOverrides ){125 forEachEvent( this, function( self, event, type, namespace, qualifier, callback, conf ){126 if( is.fn( callback ) ){127 self.listeners.push( {128 event: event, // full event string129 callback: callback, // callback to run130 type: type, // the event type (e.g. 'click')131 namespace: namespace, // the event namespace (e.g. ".foo")132 qualifier: qualifier, // a restriction on whether to match this emitter133 conf: conf // additional configuration134 } );135 }136 }, events, qualifier, callback, conf, confOverrides );137 138 return this;139};140 141p.one = function( events, qualifier, callback, conf ){142 return this.on( events, qualifier, callback, conf, { one: true } );143};144 145p.removeListener = p.off = function( events, qualifier, callback, conf ){146 if( this.emitting !== 0 ){147 this.listeners = util.copyArray( this.listeners );148 }149 150 let listeners = this.listeners;151 152 for( let i = listeners.length - 1; i >= 0; i-- ){153 let listener = listeners[i];154 155 forEachEvent( this, function( self, event, type, namespace, qualifier, callback/*, conf*/ ){156 if(157 ( listener.type === type || events === '*' ) &&158 ( (!namespace && listener.namespace !== '.*') || listener.namespace === namespace ) &&159 ( !qualifier || self.qualifierCompare( listener.qualifier, qualifier ) ) &&160 ( !callback || listener.callback === callback )161 ){162 listeners.splice( i, 1 );163 164 return false;165 }166 }, events, qualifier, callback, conf );167 }168 169 return this;170};171 172p.removeAllListeners = function(){173 return this.removeListener('*');174};175 176p.emit = p.trigger = function( events, extraParams, manualCallback ){177 let listeners = this.listeners;178 let numListenersBeforeEmit = listeners.length;179 180 this.emitting++;181 182 if( !is.array( extraParams ) ){183 extraParams = [ extraParams ];184 }185 186 forEachEventObj( this, function( self, eventObj ){187 if( manualCallback != null ){188 listeners = [{189 event: eventObj.event,190 type: eventObj.type,191 namespace: eventObj.namespace,192 callback: manualCallback193 }];194 195 numListenersBeforeEmit = listeners.length;196 }197 198 for( let i = 0; i < numListenersBeforeEmit; i++ ){199 let listener = listeners[i];200 201 if(202 ( listener.type === eventObj.type ) &&203 ( !listener.namespace || listener.namespace === eventObj.namespace || listener.namespace === universalNamespace ) &&204 ( self.eventMatches( self.context, listener, eventObj ) )205 ){206 let args = [ eventObj ];207 208 if( extraParams != null ){209 util.push( args, extraParams );210 }211 212 self.beforeEmit( self.context, listener, eventObj );213 214 if( listener.conf && listener.conf.one ){215 self.listeners = self.listeners.filter( l => l !== listener );216 }217 218 let context = self.callbackContext( self.context, listener, eventObj );219 let ret = listener.callback.apply( context, args );220 221 self.afterEmit( self.context, listener, eventObj );222 223 if( ret === false ){224 eventObj.stopPropagation();225 eventObj.preventDefault();226 }227 } // if listener matches228 } // for listener229 230 if( self.bubble( self.context ) && !eventObj.isPropagationStopped() ){231 self.parent( self.context ).emit( eventObj, extraParams );232 }233 }, events );234 235 this.emitting--;236 237 return this;238};239 240export default Emitter;241 