@@ -24,21 +24,8 @@ const EmitterMixin = {
2424 /**
2525 * Registers a callback function to be executed when an event is fired.
2626 *
27- * Events can be grouped in namespaces using `:`.
28- * When namespaced event is fired, it additionally fires all callbacks for that namespace.
29- *
30- * myEmitter.on( 'myGroup', genericCallback );
31- * myEmitter.on( 'myGroup:myEvent', specificCallback );
32- *
33- * // genericCallback is fired.
34- * myEmitter.fire( 'myGroup' );
35- * // both genericCallback and specificCallback are fired.
36- * myEmitter.fire( 'myGroup:myEvent' );
37- * // genericCallback is fired even though there are no callbacks for "foo".
38- * myEmitter.fire( 'myGroup:foo' );
39- *
40- * An event callback can {@link module:utils/eventinfo~EventInfo#stop stop the event} and
41- * set the {@link module:utils/eventinfo~EventInfo#return return value} of the {@link #fire} method.
27+ * Shorthand for {@link #listenTo `this.listenTo( this, event, callback, options )`} (it makes the emitter
28+ * listen on itself).
4229 *
4330 * @method #on
4431 * @param {String } event The name of the event.
@@ -49,34 +36,7 @@ const EmitterMixin = {
4936 * order they were added.
5037 */
5138 on ( event , callback , options = { } ) {
52- createEventNamespace ( this , event ) ;
53- const lists = getCallbacksListsForNamespace ( this , event ) ;
54- const priority = priorities . get ( options . priority ) ;
55-
56- callback = {
57- callback,
58- priority
59- } ;
60-
61- // Add the callback to all callbacks list.
62- for ( const callbacks of lists ) {
63- // Add the callback to the list in the right priority position.
64- let added = false ;
65-
66- for ( let i = 0 ; i < callbacks . length ; i ++ ) {
67- if ( callbacks [ i ] . priority < priority ) {
68- callbacks . splice ( i , 0 , callback ) ;
69- added = true ;
70-
71- break ;
72- }
73- }
74-
75- // Add at the end, if right place was not found.
76- if ( ! added ) {
77- callbacks . push ( callback ) ;
78- }
79- }
39+ this . listenTo ( this , event , callback , options ) ;
8040 } ,
8141
8242 /**
@@ -101,33 +61,41 @@ const EmitterMixin = {
10161 } ;
10262
10363 // Make a similar on() call, simply replacing the callback.
104- this . on ( event , onceCallback , options ) ;
64+ this . listenTo ( this , event , onceCallback , options ) ;
10565 } ,
10666
10767 /**
10868 * Stops executing the callback on the given event.
69+ * Shorthand for {@link #stopListening `this.stopListening( this, event, callback )`}.
10970 *
11071 * @method #off
11172 * @param {String } event The name of the event.
11273 * @param {Function } callback The function to stop being called.
11374 */
11475 off ( event , callback ) {
115- const lists = getCallbacksListsForNamespace ( this , event ) ;
116-
117- for ( const callbacks of lists ) {
118- for ( let i = 0 ; i < callbacks . length ; i ++ ) {
119- if ( callbacks [ i ] . callback == callback ) {
120- // Remove the callback from the list (fixing the next index).
121- callbacks . splice ( i , 1 ) ;
122- i -- ;
123- }
124- }
125- }
76+ this . stopListening ( this , event , callback ) ;
12677 } ,
12778
12879 /**
12980 * Registers a callback function to be executed when an event is fired in a specific (emitter) object.
13081 *
82+ * Events can be grouped in namespaces using `:`.
83+ * When namespaced event is fired, it additionally fires all callbacks for that namespace.
84+ *
85+ * // myEmitter.on( ... ) is a shorthand for myEmitter.listenTo( myEmitter, ... ).
86+ * myEmitter.on( 'myGroup', genericCallback );
87+ * myEmitter.on( 'myGroup:myEvent', specificCallback );
88+ *
89+ * // genericCallback is fired.
90+ * myEmitter.fire( 'myGroup' );
91+ * // both genericCallback and specificCallback are fired.
92+ * myEmitter.fire( 'myGroup:myEvent' );
93+ * // genericCallback is fired even though there are no callbacks for "foo".
94+ * myEmitter.fire( 'myGroup:foo' );
95+ *
96+ * An event callback can {@link module:utils/eventinfo~EventInfo#stop stop the event} and
97+ * set the {@link module:utils/eventinfo~EventInfo#return return value} of the {@link #fire} method.
98+ *
13199 * @method #listenTo
132100 * @param {module:utils/emittermixin~Emitter } emitter The object that fires the event.
133101 * @param {String } event The name of the event.
@@ -137,7 +105,7 @@ const EmitterMixin = {
137105 * the priority value the sooner the callback will be fired. Events having the same priority are called in the
138106 * order they were added.
139107 */
140- listenTo ( emitter , event , callback , options ) {
108+ listenTo ( emitter , event , callback , options = { } ) {
141109 let emitterInfo , eventCallbacks ;
142110
143111 // _listeningTo contains a list of emitters that this object is listening to.
@@ -180,7 +148,34 @@ const EmitterMixin = {
180148 eventCallbacks . push ( callback ) ;
181149
182150 // Finally register the callback to the event.
183- emitter . on ( event , callback , options ) ;
151+ createEventNamespace ( emitter , event ) ;
152+ const lists = getCallbacksListsForNamespace ( emitter , event ) ;
153+ const priority = priorities . get ( options . priority ) ;
154+
155+ const callbackDefinition = {
156+ callback,
157+ priority
158+ } ;
159+
160+ // Add the callback to all callbacks list.
161+ for ( const callbacks of lists ) {
162+ // Add the callback to the list in the right priority position.
163+ let added = false ;
164+
165+ for ( let i = 0 ; i < callbacks . length ; i ++ ) {
166+ if ( callbacks [ i ] . priority < priority ) {
167+ callbacks . splice ( i , 0 , callbackDefinition ) ;
168+ added = true ;
169+
170+ break ;
171+ }
172+ }
173+
174+ // Add at the end, if right place was not found.
175+ if ( ! added ) {
176+ callbacks . push ( callbackDefinition ) ;
177+ }
178+ }
184179 } ,
185180
186181 /**
@@ -189,7 +184,7 @@ const EmitterMixin = {
189184 * * To stop listening to a specific callback.
190185 * * To stop listening to a specific event.
191186 * * To stop listening to all events fired by a specific object.
192- * * To stop listening to all events fired by all object .
187+ * * To stop listening to all events fired by all objects .
193188 *
194189 * @method #stopListening
195190 * @param {module:utils/emittermixin~Emitter } [emitter] The object to stop listening to. If omitted, stops it for all objects.
@@ -211,13 +206,14 @@ const EmitterMixin = {
211206
212207 // All params provided. off() that single callback.
213208 if ( callback ) {
214- emitter . off ( event , callback ) ;
209+ removeCallback ( emitter , event , callback ) ;
215210 }
216211 // Only `emitter` and `event` provided. off() all callbacks for that event.
217212 else if ( eventCallbacks ) {
218213 while ( ( callback = eventCallbacks . pop ( ) ) ) {
219- emitter . off ( event , callback ) ;
214+ removeCallback ( emitter , event , callback ) ;
220215 }
216+
221217 delete emitterInfo . callbacks [ event ] ;
222218 }
223219 // Only `emitter` provided. off() all events for that emitter.
@@ -246,7 +242,7 @@ const EmitterMixin = {
246242 * @param {String|module:utils/eventinfo~EventInfo } eventOrInfo The name of the event or `EventInfo` object if event is delegated.
247243 * @param {...* } [args] Additional arguments to be passed to the callbacks.
248244 * @returns {* } By default the method returns `undefined`. However, the return value can be changed by listeners
249- * through modification of the {@link module:utils/eventinfo~EventInfo#return}'s value (the event info
245+ * through modification of the {@link module:utils/eventinfo~EventInfo#return `evt.return` }'s property (the event info
250246 * is the first param of every callback).
251247 */
252248 fire ( eventOrInfo , ...args ) {
@@ -277,7 +273,7 @@ const EmitterMixin = {
277273 // Remove the called mark for the next calls.
278274 delete eventInfo . off . called ;
279275
280- this . off ( event , callbacks [ i ] . callback ) ;
276+ removeCallback ( this , event , callbacks [ i ] . callback ) ;
281277 }
282278
283279 // Do not execute next callbacks if stop() was called.
@@ -508,7 +504,6 @@ function createEventNamespace( source, eventName ) {
508504// Gets an array containing callbacks list for a given event and it's more specific events.
509505// I.e. if given event is foo:bar and there is also foo:bar:abc event registered, this will
510506// return callback list of foo:bar and foo:bar:abc (but not foo).
511- // Returns empty array if given event has not been yet registered.
512507function getCallbacksListsForNamespace ( source , eventName ) {
513508 const eventNode = getEvents ( source ) [ eventName ] ;
514509
@@ -570,6 +565,25 @@ function fireDelegatedEvents( destinations, eventInfo, fireArgs ) {
570565 }
571566}
572567
568+ // Removes callback from emitter for given event.
569+ //
570+ // @param {module:utils/emittermixin~Emitter } emitter
571+ // @param {String } event
572+ // @param {Function } callback
573+ function removeCallback ( emitter , event , callback ) {
574+ const lists = getCallbacksListsForNamespace ( emitter , event ) ;
575+
576+ for ( const callbacks of lists ) {
577+ for ( let i = 0 ; i < callbacks . length ; i ++ ) {
578+ if ( callbacks [ i ] . callback == callback ) {
579+ // Remove the callback from the list (fixing the next index).
580+ callbacks . splice ( i , 1 ) ;
581+ i -- ;
582+ }
583+ }
584+ }
585+ }
586+
573587/**
574588 * Interface representing classes which mix in {@link module:utils/emittermixin~EmitterMixin}.
575589 *
0 commit comments