Explorar o código

Split Collection.bindTo#using into #using() and #as().

Aleksander Nowodzinski %!s(int64=8) %!d(string=hai) anos
pai
achega
c6688494f4

+ 50 - 34
packages/ckeditor5-utils/src/collection.js

@@ -293,7 +293,7 @@ export default class Collection {
 	 *		const source = new Collection( { idProperty: 'label' } );
 	 *		const source = new Collection( { idProperty: 'label' } );
 	 *		const target = new Collection();
 	 *		const target = new Collection();
 	 *
 	 *
-	 *		target.bindTo( source ).using( FactoryClass );
+	 *		target.bindTo( source ).as( FactoryClass );
 	 *
 	 *
 	 *		source.add( { label: 'foo' } );
 	 *		source.add( { label: 'foo' } );
 	 *		source.add( { label: 'bar' } );
 	 *		source.add( { label: 'bar' } );
@@ -355,37 +355,68 @@ export default class Collection {
 	 * @returns {module:ui/viewcollection~ViewCollection#bindTo#using}
 	 * @returns {module:ui/viewcollection~ViewCollection#bindTo#using}
 	 */
 	 */
 	bindTo( collection ) {
 	bindTo( collection ) {
+		// Sets the actual binding using provided factory.
+		//
+		// @private
+		// @param {Function} factory A collection item factory returning collection items.
+		const bind = ( factory ) => {
+			// Load the initial content of the collection.
+			for ( let item of collection ) {
+				this.add( factory( item ) );
+			}
+
+			// Synchronize the with collection as new items are added.
+			this.listenTo( collection, 'add', ( evt, item, index ) => {
+				this.add( factory( item ), index );
+			} );
+
+			// Synchronize the with collection as new items are removed.
+			this.listenTo( collection, 'remove', ( evt, item ) => {
+				this.remove( this._boundItemsMap.get( item ) );
+
+				this._boundItemsMap.delete( item );
+			} );
+		};
+
 		return {
 		return {
 			/**
 			/**
-			 * Determines the output of the binding.
+			 * Creates the class factory binding.
 			 *
 			 *
 			 * @static
 			 * @static
-			 * @param {Function|String} CallbackPropertyOrClass When specified as a callback, the callback
-			 * produces the items. When the class constructor is passed, the factory of that class is initialized.
-			 * When the string is provided, the property value is used to create the binding.
+			 * @param {Function} Class Specifies which class factory is to be initialized.
 			 */
 			 */
-			using: ( CallbackPropertyOrClass ) => {
-				let createItem;
+			as: ( Class ) => {
+				bind( ( item ) => {
+					const instance = new Class( item );
 
 
-				if ( CallbackPropertyOrClass.toString().match( /^class/ ) ) {
-					createItem = ( item ) => {
-						const instance = new CallbackPropertyOrClass( item );
+					this._boundItemsMap.set( item, instance );
 
 
-						this._boundItemsMap.set( item, instance );
+					return instance;
+				} );
+			},
 
 
-						return instance;
-					};
-				} else if ( typeof CallbackPropertyOrClass == 'function' ) {
-					createItem = ( item ) => {
-						const instance = CallbackPropertyOrClass( item );
+			/**
+			 * Creates callback or property binding.
+			 *
+			 * @static
+			 * @param {Function|String} callbackOrProperty When the function is passed, it is used to
+			 * produce the items. When the string is provided, the property value is used to create
+			 * the bound collection items.
+			 */
+			using: ( callbackOrProperty ) => {
+				let factory;
+
+				if ( typeof callbackOrProperty == 'function' ) {
+					factory = ( item ) => {
+						const instance = callbackOrProperty( item );
 
 
 						this._boundItemsMap.set( item, instance );
 						this._boundItemsMap.set( item, instance );
 
 
 						return instance;
 						return instance;
 					};
 					};
 				} else {
 				} else {
-					createItem = ( item ) => {
-						const instance = item[ CallbackPropertyOrClass ];
+					factory = ( item ) => {
+						const instance = item[ callbackOrProperty ];
 
 
 						this._boundItemsMap.set( item, instance );
 						this._boundItemsMap.set( item, instance );
 
 
@@ -393,22 +424,7 @@ export default class Collection {
 					};
 					};
 				}
 				}
 
 
-				// Load the initial content of the collection.
-				for ( let item of collection ) {
-					this.add( createItem( item ) );
-				}
-
-				// Synchronize the with collection as new items are added.
-				this.listenTo( collection, 'add', ( evt, item, index ) => {
-					this.add( createItem( item ), index );
-				} );
-
-				// Synchronize the with collection as new items are removed.
-				this.listenTo( collection, 'remove', ( evt, item ) => {
-					this.remove( this._boundItemsMap.get( item ) );
-
-					this._boundItemsMap.delete( item );
-				} );
+				bind( factory );
 			}
 			}
 		};
 		};
 	}
 	}

+ 60 - 53
packages/ckeditor5-utils/tests/collection.js

@@ -519,11 +519,69 @@ describe( 'Collection', () => {
 			}
 			}
 		}
 		}
 
 
-		it( 'provides "using()" interface', () => {
+		it( 'provides "using()" and "as()" interfaces', () => {
 			const returned = collection.bindTo( {} );
 			const returned = collection.bindTo( {} );
 
 
-			expect( returned ).to.have.keys( 'using' );
+			expect( returned ).to.have.keys( 'using', 'as' );
 			expect( returned.using ).to.be.a( 'function' );
 			expect( returned.using ).to.be.a( 'function' );
+			expect( returned.as ).to.be.a( 'function' );
+		} );
+
+		describe( 'as()', () => {
+			let items;
+
+			beforeEach( () => {
+				items = new Collection();
+			} );
+
+			it( 'creates a binding (initial content)', () => {
+				items.add( { id: '1' } );
+				items.add( { id: '2' } );
+
+				collection = new Collection();
+				collection.bindTo( items ).as( FactoryClass );
+
+				expect( collection ).to.have.length( 2 );
+				expect( collection.get( 0 ) ).to.be.instanceOf( FactoryClass );
+				expect( collection.get( 1 ) ).to.be.instanceOf( FactoryClass );
+				expect( collection.get( 1 ).data ).to.equal( items.get( 1 ) );
+			} );
+
+			it( 'creates a binding (new content)', () => {
+				collection = new Collection();
+				collection.bindTo( items ).as( FactoryClass );
+
+				expect( collection ).to.have.length( 0 );
+
+				items.add( { id: '1' } );
+				items.add( { id: '2' } );
+
+				expect( collection ).to.have.length( 2 );
+				expect( collection.get( 0 ) ).to.be.instanceOf( FactoryClass );
+				expect( collection.get( 1 ) ).to.be.instanceOf( FactoryClass );
+				expect( collection.get( 1 ).data ).to.equal( items.get( 1 ) );
+			} );
+
+			it( 'creates a binding (item removal)', () => {
+				collection = new Collection();
+				collection.bindTo( items ).as( FactoryClass );
+
+				expect( collection ).to.have.length( 0 );
+
+				items.add( { id: '1' } );
+				items.add( { id: '2' } );
+
+				expect( collection ).to.have.length( 2 );
+				expect( collection.get( 0 ) ).to.be.instanceOf( FactoryClass );
+				expect( collection.get( 1 ) ).to.be.instanceOf( FactoryClass );
+				expect( collection.get( 1 ).data ).to.equal( items.get( 1 ) );
+
+				items.remove( 1 );
+				expect( collection.get( 0 ).data ).to.equal( items.get( 0 ) );
+
+				items.remove( 0 );
+				expect( collection ).to.have.length( 0 );
+			} );
 		} );
 		} );
 
 
 		describe( 'using()', () => {
 		describe( 'using()', () => {
@@ -593,57 +651,6 @@ describe( 'Collection', () => {
 				} );
 				} );
 			} );
 			} );
 
 
-			describe( 'class constructor', () => {
-				it( 'creates a binding (initial content)', () => {
-					items.add( { id: '1' } );
-					items.add( { id: '2' } );
-
-					collection = new Collection();
-					collection.bindTo( items ).using( FactoryClass );
-
-					expect( collection ).to.have.length( 2 );
-					expect( collection.get( 0 ) ).to.be.instanceOf( FactoryClass );
-					expect( collection.get( 1 ) ).to.be.instanceOf( FactoryClass );
-					expect( collection.get( 1 ).data ).to.equal( items.get( 1 ) );
-				} );
-
-				it( 'creates a binding (new content)', () => {
-					collection = new Collection();
-					collection.bindTo( items ).using( FactoryClass );
-
-					expect( collection ).to.have.length( 0 );
-
-					items.add( { id: '1' } );
-					items.add( { id: '2' } );
-
-					expect( collection ).to.have.length( 2 );
-					expect( collection.get( 0 ) ).to.be.instanceOf( FactoryClass );
-					expect( collection.get( 1 ) ).to.be.instanceOf( FactoryClass );
-					expect( collection.get( 1 ).data ).to.equal( items.get( 1 ) );
-				} );
-
-				it( 'creates a binding (item removal)', () => {
-					collection = new Collection();
-					collection.bindTo( items ).using( FactoryClass );
-
-					expect( collection ).to.have.length( 0 );
-
-					items.add( { id: '1' } );
-					items.add( { id: '2' } );
-
-					expect( collection ).to.have.length( 2 );
-					expect( collection.get( 0 ) ).to.be.instanceOf( FactoryClass );
-					expect( collection.get( 1 ) ).to.be.instanceOf( FactoryClass );
-					expect( collection.get( 1 ).data ).to.equal( items.get( 1 ) );
-
-					items.remove( 1 );
-					expect( collection.get( 0 ).data ).to.equal( items.get( 0 ) );
-
-					items.remove( 0 );
-					expect( collection ).to.have.length( 0 );
-				} );
-			} );
-
 			describe( 'property name', () => {
 			describe( 'property name', () => {
 				it( 'creates a binding', () => {
 				it( 'creates a binding', () => {
 					collection = new Collection();
 					collection = new Collection();