瀏覽代碼

Introduced Emitter#delegate( '*' ) syntax to delegate all events. Code refactoring.

Aleksander Nowodzinski 9 年之前
父節點
當前提交
276b6072cd
共有 2 個文件被更改,包括 84 次插入16 次删除
  1. 10 14
      packages/ckeditor5-utils/src/emittermixin.js
  2. 74 2
      packages/ckeditor5-utils/tests/emittermixin.js

+ 10 - 14
packages/ckeditor5-utils/src/emittermixin.js

@@ -275,14 +275,14 @@ const EmitterMixin = {
 		// Delegate event to other emitters if needed.
 		if ( this._delegations ) {
 			const destinations = this._delegations.get( event );
-			const passThruDestinations = this._delegations.get( '*' );
+			const passAllDestinations = this._delegations.get( '*' );
 
 			if ( destinations ) {
 				fireDelegatedEvents( destinations, eventInfo, args );
 			}
 
-			if ( passThruDestinations ) {
-				fireDelegatedEvents( passThruDestinations, eventInfo, args );
+			if ( passAllDestinations ) {
+				fireDelegatedEvents( passAllDestinations, eventInfo, args );
 			}
 		}
 	},
@@ -319,18 +319,14 @@ const EmitterMixin = {
 					this._delegations = new Map();
 				}
 
-				if ( events.length ) {
-					for ( let eventName of events ) {
-						let destinations = this._delegations.get( eventName );
+				for ( let eventName of events ) {
+					let destinations = this._delegations.get( eventName );
 
-						if ( !destinations ) {
-							this._delegations.set( eventName, new Map( [ [ emitter, nameOrFunction ] ] ) );
-						} else {
-							destinations.set( emitter, nameOrFunction );
-						}
+					if ( !destinations ) {
+						this._delegations.set( eventName, new Map( [ [ emitter, nameOrFunction ] ] ) );
+					} else {
+						destinations.set( emitter, nameOrFunction );
 					}
-				} else {
-					this._delegations.set( '*', new Map( [ [ emitter, nameOrFunction ] ] ) );
 				}
 			}
 		};
@@ -503,7 +499,7 @@ function getCallbacksForEvent( source, eventName ) {
 // Fires delegated events for given map of destinations.
 //
 // @private
-// * @param {Map.<utils.Emitter>} destinations A map containing {@link utils.Emitter}–event name pair destinations.
+// * @param {Map.<utils.Emitter>} destinations A map containing `[ {@link utils.Emitter}, "event name" ]` pair destinations.
 // * @param {utils.EventInfo} eventInfo The original event info object.
 // * @param {Array.<*>} fireArgs Arguments the original event was fired with.
 function fireDelegatedEvents( destinations, eventInfo, fireArgs ) {

+ 74 - 2
packages/ckeditor5-utils/tests/emittermixin.js

@@ -832,7 +832,7 @@ describe( 'delegate', () => {
 			const spyABar = sinon.spy();
 			const spyABaz = sinon.spy();
 
-			emitterB.delegate().to( emitterA );
+			emitterB.delegate( '*' ).to( emitterA );
 
 			emitterA.on( 'foo', spyAFoo );
 			emitterA.on( 'bar', spyABar );
@@ -855,7 +855,7 @@ describe( 'delegate', () => {
 			const spyABarDel = sinon.spy();
 			const spyABazDel = sinon.spy();
 
-			emitterB.delegate().to( emitterA, name => name + '-delegated' );
+			emitterB.delegate( '*' ).to( emitterA, name => name + '-delegated' );
 
 			emitterA.on( 'foo', spyAFoo );
 			emitterA.on( 'bar', spyABar );
@@ -986,6 +986,78 @@ describe( 'stopDelegating', () => {
 		sinon.assert.callOrder( spyFooB, spyFooC, spyFooB );
 	} );
 
+	it( 'stops delegating all ("*")', () => {
+		const emitterA = getEmitterInstance();
+		const emitterB = getEmitterInstance();
+		const emitterC = getEmitterInstance();
+		const spyAFoo = sinon.spy();
+		const spyABar = sinon.spy();
+		const spyCFoo = sinon.spy();
+		const spyCBar = sinon.spy();
+
+		emitterB.delegate( '*' ).to( emitterA );
+		emitterB.delegate( '*' ).to( emitterC );
+
+		emitterA.on( 'foo', spyAFoo );
+		emitterA.on( 'bar', spyABar );
+		emitterC.on( 'foo', spyCFoo );
+		emitterC.on( 'bar', spyCBar );
+
+		emitterB.fire( 'foo' );
+		emitterB.fire( 'bar' );
+
+		sinon.assert.calledOnce( spyAFoo );
+		sinon.assert.calledOnce( spyABar );
+		sinon.assert.calledOnce( spyCFoo );
+		sinon.assert.calledOnce( spyCBar );
+
+		emitterB.stopDelegating( '*' );
+
+		emitterB.fire( 'foo' );
+		emitterB.fire( 'bar' );
+
+		sinon.assert.calledOnce( spyAFoo );
+		sinon.assert.calledOnce( spyABar );
+		sinon.assert.calledOnce( spyCFoo );
+		sinon.assert.calledOnce( spyCBar );
+	} );
+
+	it( 'stops delegating all ("*") to a specific emitter', () => {
+		const emitterA = getEmitterInstance();
+		const emitterB = getEmitterInstance();
+		const emitterC = getEmitterInstance();
+		const spyAFoo = sinon.spy();
+		const spyABar = sinon.spy();
+		const spyCFoo = sinon.spy();
+		const spyCBar = sinon.spy();
+
+		emitterB.delegate( '*' ).to( emitterA );
+		emitterB.delegate( 'foo' ).to( emitterC );
+
+		emitterA.on( 'foo', spyAFoo );
+		emitterA.on( 'bar', spyABar );
+		emitterC.on( 'foo', spyCFoo );
+		emitterC.on( 'bar', spyCBar );
+
+		emitterB.fire( 'foo' );
+		emitterB.fire( 'bar' );
+
+		sinon.assert.calledOnce( spyAFoo );
+		sinon.assert.calledOnce( spyABar );
+		sinon.assert.calledOnce( spyCFoo );
+		sinon.assert.notCalled( spyCBar );
+
+		emitterB.stopDelegating( '*', emitterA );
+
+		emitterB.fire( 'foo' );
+		emitterB.fire( 'bar' );
+
+		sinon.assert.calledOnce( spyAFoo );
+		sinon.assert.calledOnce( spyABar );
+		sinon.assert.calledTwice( spyCFoo );
+		sinon.assert.notCalled( spyCBar );
+	} );
+
 	it( 'passes when stopping delegation of a specific event which has never been delegated', () => {
 		const emitterA = getEmitterInstance();
 		const emitterB = getEmitterInstance();