瀏覽代碼

Using writer to set class on view element.

Szymon Kupś 7 年之前
父節點
當前提交
77df582893

+ 2 - 9
packages/ckeditor5-engine/src/conversion/downcast-converters.js

@@ -386,13 +386,7 @@ function _createViewElementFromDefinition( viewElementDefinition, ViewElementCla
 	}
 
 	if ( viewElementDefinition.class ) {
-		const classes = viewElementDefinition.class;
-
-		if ( typeof classes == 'string' ) {
-			element.addClass( classes );
-		} else {
-			element.addClass( ...classes );
-		}
+		element._addClass( viewElementDefinition.class );
 	}
 
 	return element;
@@ -1011,8 +1005,7 @@ export function createViewElementFromHighlightDescriptor( descriptor ) {
 	const viewElement = new HighlightAttributeElement( 'span', descriptor.attributes );
 
 	if ( descriptor.class ) {
-		const cssClasses = Array.isArray( descriptor.class ) ? descriptor.class : [ descriptor.class ];
-		viewElement.addClass( ...cssClasses );
+		viewElement._addClass( descriptor.class );
 	}
 
 	if ( descriptor.priority ) {

+ 17 - 14
packages/ckeditor5-engine/src/view/element.js

@@ -420,20 +420,6 @@ export default class Element extends Node {
 	}
 
 	/**
-	 * Adds specified class.
-	 *
-	 *		element.addClass( 'foo' ); // Adds 'foo' class.
-	 *		element.addClass( 'foo', 'bar' ); // Adds 'foo' and 'bar' classes.
-	 *
-	 * @param {...String} className
-	 * @fires module:engine/view/node~Node#change
-	 */
-	addClass( ...className ) {
-		this._fireChange( 'attributes', this );
-		className.forEach( name => this._classes.add( name ) );
-	}
-
-	/**
 	 * Removes specified class.
 	 *
  	 *		element.removeClass( 'foo' );  // Removes 'foo' class.
@@ -714,6 +700,23 @@ export default class Element extends Node {
 	}
 
 	/**
+	 * Adds specified class.
+	 *
+	 *		element._addClass( 'foo' ); // Adds 'foo' class.
+	 *		element._addClass( [ 'foo', 'bar' ] ); // Adds 'foo' and 'bar' classes.
+	 *
+	 * @protected
+	 * @param {Array.<String>|String} className
+	 * @fires module:engine/view/node~Node#change
+	 */
+	_addClass( className ) {
+		this._fireChange( 'attributes', this );
+
+		className = Array.isArray( className ) ? className : [ className ];
+		className.forEach( name => this._classes.add( name ) );
+	}
+
+	/**
 	 * Returns block {@link module:engine/view/filler filler} offset or `null` if block filler is not needed.
 	 *
 	 * @abstract

+ 2 - 2
packages/ckeditor5-engine/src/view/placeholder.js

@@ -108,14 +108,14 @@ function updateSinglePlaceholder( element, checkFunction ) {
 
 	// If element is empty and editor is blurred.
 	if ( !document.isFocused && isEmptyish ) {
-		element.addClass( 'ck-placeholder' );
+		element._addClass( 'ck-placeholder' );
 
 		return;
 	}
 
 	// It there are no child elements and selection is not placed inside element.
 	if ( isEmptyish && anchor && anchor.parent !== element ) {
-		element.addClass( 'ck-placeholder' );
+		element._addClass( 'ck-placeholder' );
 	} else {
 		element.removeClass( 'ck-placeholder' );
 	}

+ 5 - 1
packages/ckeditor5-engine/src/view/writer.js

@@ -190,6 +190,10 @@ export default class Writer {
 		element._removeAttribute( key );
 	}
 
+	addClass( className, element ) {
+		element._addClass( className );
+	}
+
 	/**
 	 * Breaks attribute nodes at provided position or at boundaries of provided range. It breaks attribute elements inside
 	 * up to a container element.
@@ -1045,7 +1049,7 @@ export default class Writer {
 
 		for ( const key of wrapper.getClassNames() ) {
 			if ( !toWrap.hasClass( key ) ) {
-				toWrap.addClass( key );
+				this.addClass( key, toWrap );
 			}
 		}
 

+ 3 - 1
packages/ckeditor5-engine/tests/conversion/downcast-converters.js

@@ -1303,7 +1303,9 @@ describe( 'downcast-converters', () => {
 					const viewContainer = new ViewContainerElement( 'div' );
 
 					viewContainer.setCustomProperty( 'addHighlight', ( element, descriptor ) => {
-						element.addClass( descriptor.class );
+						controller.view.change( writer => {
+							writer.addClass( descriptor.class, element );
+						} );
 					} );
 
 					viewContainer.setCustomProperty( 'removeHighlight', element => {

+ 1 - 1
packages/ckeditor5-engine/tests/conversion/downcast-selection-converters.js

@@ -523,7 +523,7 @@ describe( 'downcast-selection-converters', () => {
 						consumable.consume( selection, 'selection' );
 
 						const viewNode = conversionApi.mapper.toViewElement( node );
-						viewNode.addClass( 'selected' );
+						conversionApi.writer.addClass( 'selected', viewNode );
 					}
 				}
 			} );

+ 1 - 1
packages/ckeditor5-engine/tests/conversion/viewconsumable.js

@@ -487,7 +487,7 @@ describe( 'ViewConsumable', () => {
 		} );
 
 		it( 'should add all classes', () => {
-			el.addClass( 'foo', 'bar', 'baz' );
+			el._addClass( [ 'foo', 'bar', 'baz' ] );
 
 			const consumables = ViewConsumable.consumablesFromElement( el );
 			expect( consumables.class.length ).to.equal( 3 );

+ 22 - 22
packages/ckeditor5-engine/tests/view/element.js

@@ -174,7 +174,7 @@ describe( 'Element', () => {
 
 		it( 'should clone class attribute', () => {
 			const el = new Element( 'p', { foo: 'bar' } );
-			el.addClass( 'baz', 'qux' );
+			el._addClass( [ 'baz', 'qux' ] );
 			const clone = el.clone( false );
 
 			expect( clone ).to.not.equal( el );
@@ -261,10 +261,10 @@ describe( 'Element', () => {
 			const el3 = new Element( 'p' );
 			const el4 = new Element( 'p' );
 
-			el1.addClass( 'foo', 'bar' );
-			el2.addClass( 'bar', 'foo' );
-			el3.addClass( 'baz' );
-			el4.addClass( 'baz', 'bar' );
+			el1._addClass( [ 'foo', 'bar' ] );
+			el2._addClass( [ 'bar', 'foo' ] );
+			el3._addClass( 'baz' );
+			el4._addClass( [ 'baz', 'bar' ] );
 
 			expect( el1.isSimilar( el2 ) ).to.be.true;
 			expect( el1.isSimilar( el3 ) ).to.be.false;
@@ -492,7 +492,7 @@ describe( 'Element', () => {
 			} );
 
 			it( 'should return class attribute', () => {
-				el.addClass( 'foo', 'bar' );
+				el._addClass( [ 'foo', 'bar' ] );
 
 				expect( el.getAttribute( 'class' ) ).to.equal( 'foo bar' );
 			} );
@@ -524,7 +524,7 @@ describe( 'Element', () => {
 			it( 'should return class and style attribute', () => {
 				el._setAttribute( 'class', 'abc' );
 				el._setAttribute( 'style', 'width:20px;' );
-				el.addClass( 'xyz' );
+				el._addClass( 'xyz' );
 				el.setStyle( 'font-weight', 'bold' );
 
 				expect( Array.from( el.getAttributes() ) ).to.deep.equal( [
@@ -543,7 +543,7 @@ describe( 'Element', () => {
 
 			it( 'should return true if element has class attribute', () => {
 				expect( el.hasAttribute( 'class' ) ).to.be.false;
-				el.addClass( 'foo' );
+				el._addClass( 'foo' );
 				expect( el.hasAttribute( 'class' ) ).to.be.true;
 			} );
 
@@ -571,7 +571,7 @@ describe( 'Element', () => {
 			} );
 
 			it( 'should return class key', () => {
-				el.addClass( 'foo' );
+				el._addClass( 'foo' );
 				el._setAttribute( 'bar', true );
 				const expected = [ 'class', 'bar' ];
 				let i = 0;
@@ -619,7 +619,7 @@ describe( 'Element', () => {
 			} );
 
 			it( 'should remove class attribute', () => {
-				el.addClass( 'foo', 'bar' );
+				el._addClass( [ 'foo', 'bar' ] );
 				const el2 = new Element( 'p' );
 				const removed1 = el._removeAttribute( 'class' );
 				const removed2 = el2._removeAttribute( 'class' );
@@ -654,9 +654,9 @@ describe( 'Element', () => {
 			el = new Element( 'p' );
 		} );
 
-		describe( 'addClass', () => {
+		describe( '_addClass()', () => {
 			it( 'should add single class', () => {
-				el.addClass( 'one' );
+				el._addClass( 'one' );
 
 				expect( el._classes.has( 'one' ) ).to.be.true;
 			} );
@@ -667,11 +667,11 @@ describe( 'Element', () => {
 					done();
 				} );
 
-				el.addClass( 'one' );
+				el._addClass( 'one' );
 			} );
 
 			it( 'should add multiple classes', () => {
-				el.addClass( 'one', 'two', 'three' );
+				el._addClass( [ 'one', 'two', 'three' ] );
 
 				expect( el._classes.has( 'one' ) ).to.be.true;
 				expect( el._classes.has( 'two' ) ).to.be.true;
@@ -681,7 +681,7 @@ describe( 'Element', () => {
 
 		describe( 'removeClass', () => {
 			it( 'should remove single class', () => {
-				el.addClass( 'one', 'two', 'three' );
+				el._addClass( [ 'one', 'two', 'three' ] );
 
 				el.removeClass( 'one' );
 
@@ -691,7 +691,7 @@ describe( 'Element', () => {
 			} );
 
 			it( 'should fire change event with attributes type', done => {
-				el.addClass( 'one' );
+				el._addClass( 'one' );
 				el.once( 'change:attributes', eventInfo => {
 					expect( eventInfo.source ).to.equal( el );
 					done();
@@ -701,7 +701,7 @@ describe( 'Element', () => {
 			} );
 
 			it( 'should remove multiple classes', () => {
-				el.addClass( 'one', 'two', 'three', 'four' );
+				el._addClass( [ 'one', 'two', 'three', 'four' ] );
 				el.removeClass( 'one', 'two', 'three' );
 
 				expect( el._classes.has( 'one' ) ).to.be.false;
@@ -713,7 +713,7 @@ describe( 'Element', () => {
 
 		describe( 'hasClass', () => {
 			it( 'should check if element has a class', () => {
-				el.addClass( 'one', 'two', 'three' );
+				el._addClass( [ 'one', 'two', 'three' ] );
 
 				expect( el.hasClass( 'one' ) ).to.be.true;
 				expect( el.hasClass( 'two' ) ).to.be.true;
@@ -722,7 +722,7 @@ describe( 'Element', () => {
 			} );
 
 			it( 'should check if element has multiple classes', () => {
-				el.addClass( 'one', 'two', 'three' );
+				el._addClass( [ 'one', 'two', 'three' ] );
 
 				expect( el.hasClass( 'one', 'two' ) ).to.be.true;
 				expect( el.hasClass( 'three', 'two' ) ).to.be.true;
@@ -734,7 +734,7 @@ describe( 'Element', () => {
 		describe( 'getClassNames', () => {
 			it( 'should return iterator with all class names', () => {
 				const names = [ 'one', 'two', 'three' ];
-				el.addClass( ...names );
+				el._addClass( names );
 				const iterator = el.getClassNames();
 				let i = 0;
 
@@ -1019,7 +1019,7 @@ describe( 'Element', () => {
 
 		it( 'should return classes in sorted order', () => {
 			const el = new Element( 'fruit' );
-			el.addClass( 'banana', 'lemon', 'apple' );
+			el._addClass( [ 'banana', 'lemon', 'apple' ] );
 
 			expect( el.getIdentity() ).to.equal( 'fruit class="apple,banana,lemon"' );
 		} );
@@ -1049,7 +1049,7 @@ describe( 'Element', () => {
 				style: 'text-align:center;border-radius:10px'
 			} );
 
-			el.addClass( 'three', 'two', 'one' );
+			el._addClass( [ 'three', 'two', 'one' ] );
 
 			expect( el.getIdentity() ).to.equal(
 				'baz class="one,three,two" style="border-radius:10px;text-align:center" bar="two" foo="one"'

+ 4 - 4
packages/ckeditor5-engine/tests/view/matcher.js

@@ -306,7 +306,7 @@ describe( 'Matcher', () => {
 			};
 			const matcher = new Matcher( pattern );
 			const el = new Element( 'a' );
-			el.addClass( 'foo', 'bar', 'baz' );
+			el._addClass( [ 'foo', 'bar', 'baz' ] );
 
 			const result = matcher.match( el );
 			expect( result ).to.be.an( 'object' );
@@ -376,9 +376,9 @@ describe( 'Matcher', () => {
 			const el2 = new Element( 'p' );
 			const el3 = new Element( 'p' );
 
-			el1.addClass( 'red-foreground' );
-			el2.addClass( 'red-background' );
-			el3.addClass( 'blue-text' );
+			el1._addClass( 'red-foreground' );
+			el2._addClass( 'red-background' );
+			el3._addClass( 'blue-text' );
 
 			const result = matcher.matchAll( el1, el2, el3 );
 			expect( result ).to.be.an( 'array' );