Explorar el Código

Updated placeholder to use view writer to manipulate view nodes.

Szymon Kupś hace 8 años
padre
commit
e13d4cb5b3

+ 31 - 17
packages/ckeditor5-engine/src/view/placeholder.js

@@ -30,61 +30,67 @@ export function attachPlaceholder( view, element, placeholderText, checkFunction
 	const document = view.document;
 	const document = view.document;
 
 
 	// Detach placeholder if was used before.
 	// Detach placeholder if was used before.
-	detachPlaceholder( element );
+	detachPlaceholder( view, element );
 
 
 	// Single listener per document.
 	// Single listener per document.
 	if ( !documentPlaceholders.has( document ) ) {
 	if ( !documentPlaceholders.has( document ) ) {
 		documentPlaceholders.set( document, new Map() );
 		documentPlaceholders.set( document, new Map() );
 
 
 		// Attach listener just before rendering and update placeholders.
 		// Attach listener just before rendering and update placeholders.
-		listener.listenTo( view.renderer, 'render', () => updateAllPlaceholders( document ), { priority: 'highest' } );
+		listener.listenTo( view.renderer, 'render', () => updateAllPlaceholders( view ), { priority: 'highest' } );
 	}
 	}
 
 
 	// Store text in element's data attribute.
 	// Store text in element's data attribute.
 	// This data attribute is used in CSS class to show the placeholder.
 	// This data attribute is used in CSS class to show the placeholder.
-	element._setAttribute( 'data-placeholder', placeholderText );
+	view.change( writer => {
+		writer.setAttribute( 'data-placeholder', placeholderText, element );
+	} );
 
 
 	// Store information about placeholder.
 	// Store information about placeholder.
 	documentPlaceholders.get( document ).set( element, checkFunction );
 	documentPlaceholders.get( document ).set( element, checkFunction );
 
 
 	// Update right away too.
 	// Update right away too.
-	updateSinglePlaceholder( element, checkFunction );
+	updateSinglePlaceholder( view, element, checkFunction );
 }
 }
 
 
 /**
 /**
  * Removes placeholder functionality from given element.
  * Removes placeholder functionality from given element.
  *
  *
+ * @param {module:engine/view/view~View} view
  * @param {module:engine/view/element~Element} element
  * @param {module:engine/view/element~Element} element
  */
  */
-export function detachPlaceholder( element ) {
+export function detachPlaceholder( view, element ) {
 	const document = element.document;
 	const document = element.document;
 
 
-	element._removeClass( 'ck-placeholder' );
-	element._removeAttribute( 'data-placeholder' );
-
 	if ( documentPlaceholders.has( document ) ) {
 	if ( documentPlaceholders.has( document ) ) {
 		documentPlaceholders.get( document ).delete( element );
 		documentPlaceholders.get( document ).delete( element );
 	}
 	}
+
+	view.change( writer => {
+		writer.removeClass( 'ck-placeholder', element );
+		writer.removeAttribute( 'data-placeholder', element );
+	} );
 }
 }
 
 
 // Updates all placeholders of given document.
 // Updates all placeholders of given document.
 //
 //
 // @private
 // @private
-// @param {module:engine/view/document~Document} document
-function updateAllPlaceholders( document ) {
-	const placeholders = documentPlaceholders.get( document );
+// @param {module:engine/view/view~View} view
+function updateAllPlaceholders( view ) {
+	const placeholders = documentPlaceholders.get( view.document );
 
 
 	for ( const [ element, checkFunction ] of placeholders ) {
 	for ( const [ element, checkFunction ] of placeholders ) {
-		updateSinglePlaceholder( element, checkFunction );
+		updateSinglePlaceholder( view, element, checkFunction );
 	}
 	}
 }
 }
 
 
 // Updates placeholder class of given element.
 // Updates placeholder class of given element.
 //
 //
 // @private
 // @private
+// @param {module:engine/view/view~View} view
 // @param {module:engine/view/element~Element} element
 // @param {module:engine/view/element~Element} element
 // @param {Function} checkFunction
 // @param {Function} checkFunction
-function updateSinglePlaceholder( element, checkFunction ) {
+function updateSinglePlaceholder( view, element, checkFunction ) {
 	const document = element.document;
 	const document = element.document;
 
 
 	// Element was removed from document.
 	// Element was removed from document.
@@ -97,7 +103,9 @@ function updateSinglePlaceholder( element, checkFunction ) {
 
 
 	// If checkFunction is provided and returns false - remove placeholder.
 	// If checkFunction is provided and returns false - remove placeholder.
 	if ( checkFunction && !checkFunction() ) {
 	if ( checkFunction && !checkFunction() ) {
-		element._removeClass( 'ck-placeholder' );
+		view.change( writer => {
+			writer.removeClass( 'ck-placeholder', element );
+		} );
 
 
 		return;
 		return;
 	}
 	}
@@ -108,15 +116,21 @@ function updateSinglePlaceholder( element, checkFunction ) {
 
 
 	// If element is empty and editor is blurred.
 	// If element is empty and editor is blurred.
 	if ( !document.isFocused && isEmptyish ) {
 	if ( !document.isFocused && isEmptyish ) {
-		element._addClass( 'ck-placeholder' );
+		view.change( writer => {
+			writer.addClass( 'ck-placeholder', element );
+		} );
 
 
 		return;
 		return;
 	}
 	}
 
 
 	// It there are no child elements and selection is not placed inside element.
 	// It there are no child elements and selection is not placed inside element.
 	if ( isEmptyish && anchor && anchor.parent !== element ) {
 	if ( isEmptyish && anchor && anchor.parent !== element ) {
-		element._addClass( 'ck-placeholder' );
+		view.change( writer => {
+			writer.addClass( 'ck-placeholder', element );
+		} );
 	} else {
 	} else {
-		element._removeClass( 'ck-placeholder' );
+		view.change( writer => {
+			writer.removeClass( 'ck-placeholder', element );
+		} );
 	}
 	}
 }
 }

+ 5 - 3
packages/ckeditor5-engine/src/view/view.js

@@ -22,6 +22,7 @@ import ObservableMixin from '@ckeditor/ckeditor5-utils/src/observablemixin';
 import log from '@ckeditor/ckeditor5-utils/src/log';
 import log from '@ckeditor/ckeditor5-utils/src/log';
 import mix from '@ckeditor/ckeditor5-utils/src/mix';
 import mix from '@ckeditor/ckeditor5-utils/src/mix';
 import { scrollViewportToShowTarget } from '@ckeditor/ckeditor5-utils/src/dom/scroll';
 import { scrollViewportToShowTarget } from '@ckeditor/ckeditor5-utils/src/dom/scroll';
+import priorities from '@ckeditor/ckeditor5-utils/src/priorities';
 import { injectUiElementHandling } from './uielement';
 import { injectUiElementHandling } from './uielement';
 import { injectQuirksHandling } from './filler';
 import { injectQuirksHandling } from './filler';
 
 
@@ -352,13 +353,14 @@ export default class View {
 	 * @private
 	 * @private
 	 */
 	 */
 	_render() {
 	_render() {
-		this._renderingInProgress = true;
+		// Lock just before rendering and unlock just after.
+		// This way other parts of the code can listen to the `render` event and modify the view tree just before rendering.
+		this.renderer.once( 'render', () => ( this._renderingInProgress = true ), { priority: priorities.get( 'normal' ) + 1 } );
+		this.renderer.once( 'render', () => ( this._renderingInProgress = false ), { priority: priorities.get( 'normal' ) - 1 } );
 
 
 		this.disableObservers();
 		this.disableObservers();
 		this.renderer.render();
 		this.renderer.render();
 		this.enableObservers();
 		this.enableObservers();
-
-		this._renderingInProgress = false;
 	}
 	}
 
 
 	/**
 	/**

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

@@ -78,7 +78,7 @@ describe( 'placeholder', () => {
 
 
 			attachPlaceholder( view, element, 'foo bar baz', spy );
 			attachPlaceholder( view, element, 'foo bar baz', spy );
 
 
-			sinon.assert.calledOnce( spy );
+			sinon.assert.called( spy );
 			expect( element.getAttribute( 'data-placeholder' ) ).to.equal( 'foo bar baz' );
 			expect( element.getAttribute( 'data-placeholder' ) ).to.equal( 'foo bar baz' );
 			expect( element.hasClass( 'ck-placeholder' ) ).to.be.false;
 			expect( element.hasClass( 'ck-placeholder' ) ).to.be.false;
 		} );
 		} );
@@ -185,7 +185,7 @@ describe( 'placeholder', () => {
 			expect( element.getAttribute( 'data-placeholder' ) ).to.equal( 'foo bar baz' );
 			expect( element.getAttribute( 'data-placeholder' ) ).to.equal( 'foo bar baz' );
 			expect( element.hasClass( 'ck-placeholder' ) ).to.be.true;
 			expect( element.hasClass( 'ck-placeholder' ) ).to.be.true;
 
 
-			detachPlaceholder( element );
+			detachPlaceholder( view, element );
 
 
 			expect( element.hasAttribute( 'data-placeholder' ) ).to.be.false;
 			expect( element.hasAttribute( 'data-placeholder' ) ).to.be.false;
 			expect( element.hasClass( 'ck-placeholder' ) ).to.be.false;
 			expect( element.hasClass( 'ck-placeholder' ) ).to.be.false;