From 9e93b82207c6db9b5b949e3007fdacc504cb678b Mon Sep 17 00:00:00 2001 From: Illia Sheremetov Date: Wed, 19 Jul 2023 16:44:12 +0200 Subject: [PATCH 01/14] Feature (engine): move placeholder property to editing root --- .../src/classiceditorui.ts | 3 ++- .../ckeditor5-engine/src/view/placeholder.ts | 17 +++++++++-------- .../src/view/rooteditableelement.ts | 8 ++++++++ 3 files changed, 19 insertions(+), 9 deletions(-) diff --git a/packages/ckeditor5-editor-classic/src/classiceditorui.ts b/packages/ckeditor5-editor-classic/src/classiceditorui.ts index aad897a4166..4a19c438492 100644 --- a/packages/ckeditor5-editor-classic/src/classiceditorui.ts +++ b/packages/ckeditor5-editor-classic/src/classiceditorui.ts @@ -165,10 +165,11 @@ export default class ClassicEditorUI extends EditorUI { enablePlaceholder( { view: editingView, element: editingRoot, - text: placeholderText, isDirectHost: false, keepOnFocus: true } ); + + editingRoot.set( 'placeholder', placeholderText ); } } diff --git a/packages/ckeditor5-engine/src/view/placeholder.ts b/packages/ckeditor5-engine/src/view/placeholder.ts index b892d9f5e7c..9688486b0d1 100644 --- a/packages/ckeditor5-engine/src/view/placeholder.ts +++ b/packages/ckeditor5-engine/src/view/placeholder.ts @@ -37,10 +37,9 @@ const documentPlaceholders = new WeakMap { + // Store information about the element placeholder under its document. + documentPlaceholders.get( doc )!.set( element, { + text, + isDirectHost, + keepOnFocus, + hostElement: isDirectHost ? element : null + } ); } ); // Update the placeholders right away. diff --git a/packages/ckeditor5-engine/src/view/rooteditableelement.ts b/packages/ckeditor5-engine/src/view/rooteditableelement.ts index 98acbe5f85c..1edc05e085f 100644 --- a/packages/ckeditor5-engine/src/view/rooteditableelement.ts +++ b/packages/ckeditor5-engine/src/view/rooteditableelement.ts @@ -19,6 +19,13 @@ const rootNameSymbol = Symbol( 'rootName' ); * editable elements} making them "nested editables". */ export default class RootEditableElement extends EditableElement { + /** + * Placeholder of current editiing root. + * + * @observable + */ + declare public placeholder?: string; + /** * Creates root editable element. * @@ -31,6 +38,7 @@ export default class RootEditableElement extends EditableElement { ) { super( document, name ); + this.set( 'placeholder', undefined ); this.rootName = 'main'; } From 724e8e01d6913a8c487979c5fd0b868e1f707aaf Mon Sep 17 00:00:00 2001 From: Illia Sheremetov Date: Thu, 20 Jul 2023 21:35:23 +0200 Subject: [PATCH 02/14] Feature (engine): improve updating placeholder feature --- .../src/ballooneditorui.ts | 25 +++++++--------- .../src/classiceditorui.ts | 17 +++++------ .../src/decouplededitorui.ts | 25 +++++++--------- .../src/inlineeditorui.ts | 25 ++++++++-------- .../src/multirooteditorui.ts | 4 --- .../ckeditor5-engine/src/view/placeholder.ts | 27 +++++++++++++---- .../tests/view/placeholder.js | 29 +++++++++++++++++++ 7 files changed, 91 insertions(+), 61 deletions(-) diff --git a/packages/ckeditor5-editor-balloon/src/ballooneditorui.ts b/packages/ckeditor5-editor-balloon/src/ballooneditorui.ts index 8ae764b8257..76765226bd4 100644 --- a/packages/ckeditor5-editor-balloon/src/ballooneditorui.ts +++ b/packages/ckeditor5-editor-balloon/src/ballooneditorui.ts @@ -8,8 +8,7 @@ */ import { - type Editor, - type ElementApi + type Editor } from 'ckeditor5/src/core'; import { @@ -110,22 +109,20 @@ export default class BalloonEditorUI extends EditorUI { const editor = this.editor; const editingView = editor.editing.view; const editingRoot = editingView.document.getRoot()!; - const sourceElement = ( editor as Editor & ElementApi ).sourceElement; const placeholder = editor.config.get( 'placeholder' ); + let placeholderText; if ( placeholder ) { - const placeholderText = typeof placeholder === 'string' ? placeholder : placeholder[ editingRoot.rootName ]; - - if ( placeholderText ) { - enablePlaceholder( { - view: editingView, - element: editingRoot, - text: placeholderText, - isDirectHost: false, - keepOnFocus: true - } ); - } + placeholderText = typeof placeholder === 'string' ? placeholder : placeholder[ editingRoot.rootName ]; } + + enablePlaceholder( { + view: editingView, + element: editingRoot, + text: placeholderText, + isDirectHost: false, + keepOnFocus: true + } ); } } diff --git a/packages/ckeditor5-editor-classic/src/classiceditorui.ts b/packages/ckeditor5-editor-classic/src/classiceditorui.ts index 4a19c438492..340aa337a64 100644 --- a/packages/ckeditor5-editor-classic/src/classiceditorui.ts +++ b/packages/ckeditor5-editor-classic/src/classiceditorui.ts @@ -161,16 +161,13 @@ export default class ClassicEditorUI extends EditorUI { placeholderText = sourceElement.getAttribute( 'placeholder' ); } - if ( placeholderText ) { - enablePlaceholder( { - view: editingView, - element: editingRoot, - isDirectHost: false, - keepOnFocus: true - } ); - - editingRoot.set( 'placeholder', placeholderText ); - } + enablePlaceholder( { + view: editingView, + element: editingRoot, + text: placeholderText !== null ? placeholderText : undefined, + isDirectHost: false, + keepOnFocus: true + } ); } /** diff --git a/packages/ckeditor5-editor-decoupled/src/decouplededitorui.ts b/packages/ckeditor5-editor-decoupled/src/decouplededitorui.ts index 0cd2e55327b..bff9f361875 100644 --- a/packages/ckeditor5-editor-decoupled/src/decouplededitorui.ts +++ b/packages/ckeditor5-editor-decoupled/src/decouplededitorui.ts @@ -8,8 +8,7 @@ */ import { - type Editor, - type ElementApi + type Editor } from 'ckeditor5/src/core'; import { @@ -118,22 +117,20 @@ export default class DecoupledEditorUI extends EditorUI { const editor = this.editor; const editingView = editor.editing.view; const editingRoot = editingView.document.getRoot()!; - const sourceElement = ( editor as Editor & ElementApi ).sourceElement; const placeholder = editor.config.get( 'placeholder' ); + let placeholderText; if ( placeholder ) { - const placeholderText = typeof placeholder === 'string' ? placeholder : placeholder[ editingRoot.rootName ]; - - if ( placeholderText ) { - enablePlaceholder( { - view: editingView, - element: editingRoot, - text: placeholderText, - isDirectHost: false, - keepOnFocus: true - } ); - } + placeholderText = typeof placeholder === 'string' ? placeholder : placeholder[ editingRoot.rootName ]; } + + enablePlaceholder( { + view: editingView, + element: editingRoot, + text: placeholderText, + isDirectHost: false, + keepOnFocus: true + } ); } } diff --git a/packages/ckeditor5-editor-inline/src/inlineeditorui.ts b/packages/ckeditor5-editor-inline/src/inlineeditorui.ts index c812882ac56..e515d3ef0d9 100644 --- a/packages/ckeditor5-editor-inline/src/inlineeditorui.ts +++ b/packages/ckeditor5-editor-inline/src/inlineeditorui.ts @@ -8,7 +8,6 @@ */ import { - type ElementApi, type Editor } from 'ckeditor5/src/core'; @@ -153,22 +152,22 @@ export default class InlineEditorUI extends EditorUI { const editor = this.editor; const editingView = editor.editing.view; const editingRoot = editingView.document.getRoot()!; - const sourceElement = ( editor as Editor & ElementApi ).sourceElement; const placeholder = editor.config.get( 'placeholder' ); + let placeholderText; if ( placeholder ) { - const placeholderText = typeof placeholder === 'string' ? placeholder : placeholder[ editingRoot.rootName ]; - - if ( placeholderText ) { - enablePlaceholder( { - view: editingView, - element: editingRoot, - text: placeholderText, - isDirectHost: false, - keepOnFocus: true - } ); - } + placeholderText = typeof placeholder === 'string' ? placeholder : placeholder[ editingRoot.rootName ]; + } + + if ( placeholderText ) { + enablePlaceholder( { + view: editingView, + element: editingRoot, + text: placeholderText, + isDirectHost: false, + keepOnFocus: true + } ); } } } diff --git a/packages/ckeditor5-editor-multi-root/src/multirooteditorui.ts b/packages/ckeditor5-editor-multi-root/src/multirooteditorui.ts index b9279832088..4ccff490a19 100644 --- a/packages/ckeditor5-editor-multi-root/src/multirooteditorui.ts +++ b/packages/ckeditor5-editor-multi-root/src/multirooteditorui.ts @@ -204,10 +204,6 @@ export default class MultiRootEditorUI extends EditorUI { } } - if ( !placeholder ) { - return; - } - const editingView = this.editor.editing.view; const editingRoot = editingView.document.getRoot( editable.name! )!; diff --git a/packages/ckeditor5-engine/src/view/placeholder.ts b/packages/ckeditor5-engine/src/view/placeholder.ts index 9688486b0d1..da8ce67ea23 100644 --- a/packages/ckeditor5-engine/src/view/placeholder.ts +++ b/packages/ckeditor5-engine/src/view/placeholder.ts @@ -37,9 +37,10 @@ const documentPlaceholders = new WeakMap { - // Store information about the element placeholder under its document. + if ( element.is( 'rootElement' ) ) { + element.on( 'change:placeholder', ( evtInfo, evt, text ) => { + // Store information about the element placeholder under its document. + documentPlaceholders.get( doc )!.set( element, { + text, + isDirectHost, + keepOnFocus, + hostElement: isDirectHost ? element : null + } ); + + // Update the placeholders right away. + view.change( writer => updateDocumentPlaceholders( doc, writer ) ); + } ); + } + + if ( text ) { documentPlaceholders.get( doc )!.set( element, { text, isDirectHost, keepOnFocus, hostElement: isDirectHost ? element : null } ); - } ); - // Update the placeholders right away. - view.change( writer => updateDocumentPlaceholders( doc, writer ) ); + // Update the placeholders right away. + view.change( writer => updateDocumentPlaceholders( doc, writer ) ); + } } /** diff --git a/packages/ckeditor5-engine/tests/view/placeholder.js b/packages/ckeditor5-engine/tests/view/placeholder.js index 77c3b7e0f94..3f841ec9c51 100644 --- a/packages/ckeditor5-engine/tests/view/placeholder.js +++ b/packages/ckeditor5-engine/tests/view/placeholder.js @@ -612,5 +612,34 @@ describe( 'placeholder', () => { expect( needsPlaceholder( element, true ) ).to.be.false; } ); + + it( 'should update placeholder when property in editing root is changed', () => { + setData( view, '
{another div}
' ); + + enablePlaceholder( { + view, + element: viewRoot, + text: 'foo bar baz' + } ); + + viewRoot.placeholder = 'new placeholder'; + + expect( viewRoot.getAttribute( 'data-placeholder' ) ).to.equal( 'new placeholder' ); + } ); + + it( 'should update placeholder when property in editing root is changed (isDirectHost=false)', () => { + setData( view, '
{another div}
' ); + + enablePlaceholder( { + view, + element: viewRoot, + text: 'foo bar baz', + isDirectHost: false + } ); + + viewRoot.placeholder = 'new placeholder'; + + expect( viewRoot.getChild( 0 ).getAttribute( 'data-placeholder' ) ).to.equal( 'new placeholder' ); + } ); } ); } ); From 05c052df1dffe2ee173bc2a823907b258d74190a Mon Sep 17 00:00:00 2001 From: Illia Sheremetov Date: Fri, 21 Jul 2023 14:32:49 +0200 Subject: [PATCH 03/14] Docs (engine): updating placeholder docs --- .../features/update-placeholder.html | 4 +++ docs/_snippets/features/update-placeholder.js | 36 +++++++++++++++++++ docs/features/editor-placeholder.md | 10 ++++++ 3 files changed, 50 insertions(+) create mode 100644 docs/_snippets/features/update-placeholder.html create mode 100644 docs/_snippets/features/update-placeholder.js diff --git a/docs/_snippets/features/update-placeholder.html b/docs/_snippets/features/update-placeholder.html new file mode 100644 index 00000000000..e6e19a63460 --- /dev/null +++ b/docs/_snippets/features/update-placeholder.html @@ -0,0 +1,4 @@ +
+

+
+ diff --git a/docs/_snippets/features/update-placeholder.js b/docs/_snippets/features/update-placeholder.js new file mode 100644 index 00000000000..9dac835d1f9 --- /dev/null +++ b/docs/_snippets/features/update-placeholder.js @@ -0,0 +1,36 @@ +/** + * @license Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved. + * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license + */ + +/* globals console, window, document, ClassicEditor */ + +import { CS_CONFIG } from '@ckeditor/ckeditor5-cloud-services/tests/_utils/cloud-services-config'; + +ClassicEditor + .create( document.querySelector( '#snippet-update-placeholder' ), { + cloudServices: CS_CONFIG, + toolbar: [ + 'undo', 'redo', '|', 'heading', + '|', 'bold', 'italic', + '|', 'link', 'uploadImage', 'insertTable', 'mediaEmbed', + '|', 'bulletedList', 'numberedList', 'outdent', 'indent' + ], + ui: { + viewportOffset: { + top: window.getViewportTopOffsetConfig() + } + }, + placeholder: 'Type some content here!' + } ) + .then( editor => { + const button = document.getElementById( 'update-placeholder-button' ); + window.editor = editor; + + button.addEventListener( 'click', () => { + editor.editing.view.document.getRoot( 'main' ).placeholder = 'New placeholder'; + } ); + } ) + .catch( err => { + console.error( err.stack ); + } ); diff --git a/docs/features/editor-placeholder.md b/docs/features/editor-placeholder.md index e5fd981e2d8..a006cb87411 100644 --- a/docs/features/editor-placeholder.md +++ b/docs/features/editor-placeholder.md @@ -108,6 +108,16 @@ The editor placeholder text is displayed using a CSS pseudo–element (`::before **Note**: The `.ck-placeholder` class is also used to display placeholders in other places, for instance, {@link features/images-captions image captions}. Make sure your custom styles apply to the right subset of placeholders. +## Updating the placeholder + +The editor placeholder could be updated in runtime changing `placeholder` property in editing root. You can use it also in {@link installation/getting-started/predefined-builds#multi-root-editor `Multi-root editor`} and {@link installation/getting-started/predefined-builds#inline-editor `Inline editor`}. + +```js +editor.editing.view.document.getRoot( 'main' ).placeholder = 'new placeholder' +``` + +{@snippet features/update-placeholder} + ## Contribute The source code of the feature is available on GitHub at [https://github.com/ckeditor/ckeditor5/tree/master/packages/ckeditor5-core](https://github.com/ckeditor/ckeditor5/tree/master/packages/ckeditor5-core). From b4fc19d54aa34c8d00aeba3272b2f1b20838ff8d Mon Sep 17 00:00:00 2001 From: Illia Sheremetov Date: Mon, 24 Jul 2023 16:19:19 +0200 Subject: [PATCH 04/14] Fix (engine): remove text paramater in enablePlaceholder() --- .../src/ballooneditorui.ts | 3 +- .../src/classiceditorui.ts | 5 +- .../src/decouplededitorui.ts | 3 +- .../src/inlineeditorui.ts | 3 +- .../src/multirooteditorui.ts | 3 +- .../src/view/editableelement.ts | 8 ++ .../ckeditor5-engine/src/view/placeholder.ts | 13 +-- .../src/view/rooteditableelement.ts | 8 -- .../tests/view/placeholder.js | 86 +++++++++---------- packages/ckeditor5-heading/src/title.ts | 7 +- .../src/imagecaption/imagecaptionediting.ts | 2 +- 11 files changed, 75 insertions(+), 66 deletions(-) diff --git a/packages/ckeditor5-editor-balloon/src/ballooneditorui.ts b/packages/ckeditor5-editor-balloon/src/ballooneditorui.ts index 76765226bd4..03b74c57e9e 100644 --- a/packages/ckeditor5-editor-balloon/src/ballooneditorui.ts +++ b/packages/ckeditor5-editor-balloon/src/ballooneditorui.ts @@ -117,10 +117,11 @@ export default class BalloonEditorUI extends EditorUI { placeholderText = typeof placeholder === 'string' ? placeholder : placeholder[ editingRoot.rootName ]; } + editingRoot.placeholder = placeholderText; + enablePlaceholder( { view: editingView, element: editingRoot, - text: placeholderText, isDirectHost: false, keepOnFocus: true } ); diff --git a/packages/ckeditor5-editor-classic/src/classiceditorui.ts b/packages/ckeditor5-editor-classic/src/classiceditorui.ts index 340aa337a64..b5655b5adef 100644 --- a/packages/ckeditor5-editor-classic/src/classiceditorui.ts +++ b/packages/ckeditor5-editor-classic/src/classiceditorui.ts @@ -161,10 +161,13 @@ export default class ClassicEditorUI extends EditorUI { placeholderText = sourceElement.getAttribute( 'placeholder' ); } + if ( placeholderText ) { + editingRoot.placeholder = placeholderText; + } + enablePlaceholder( { view: editingView, element: editingRoot, - text: placeholderText !== null ? placeholderText : undefined, isDirectHost: false, keepOnFocus: true } ); diff --git a/packages/ckeditor5-editor-decoupled/src/decouplededitorui.ts b/packages/ckeditor5-editor-decoupled/src/decouplededitorui.ts index bff9f361875..2fef9903de5 100644 --- a/packages/ckeditor5-editor-decoupled/src/decouplededitorui.ts +++ b/packages/ckeditor5-editor-decoupled/src/decouplededitorui.ts @@ -125,10 +125,11 @@ export default class DecoupledEditorUI extends EditorUI { placeholderText = typeof placeholder === 'string' ? placeholder : placeholder[ editingRoot.rootName ]; } + editingRoot.placeholder = placeholderText; + enablePlaceholder( { view: editingView, element: editingRoot, - text: placeholderText, isDirectHost: false, keepOnFocus: true } ); diff --git a/packages/ckeditor5-editor-inline/src/inlineeditorui.ts b/packages/ckeditor5-editor-inline/src/inlineeditorui.ts index e515d3ef0d9..b9cf3eb5510 100644 --- a/packages/ckeditor5-editor-inline/src/inlineeditorui.ts +++ b/packages/ckeditor5-editor-inline/src/inlineeditorui.ts @@ -160,11 +160,12 @@ export default class InlineEditorUI extends EditorUI { placeholderText = typeof placeholder === 'string' ? placeholder : placeholder[ editingRoot.rootName ]; } + editingRoot.placeholder = placeholderText; + if ( placeholderText ) { enablePlaceholder( { view: editingView, element: editingRoot, - text: placeholderText, isDirectHost: false, keepOnFocus: true } ); diff --git a/packages/ckeditor5-editor-multi-root/src/multirooteditorui.ts b/packages/ckeditor5-editor-multi-root/src/multirooteditorui.ts index 4ccff490a19..c41af0254b5 100644 --- a/packages/ckeditor5-editor-multi-root/src/multirooteditorui.ts +++ b/packages/ckeditor5-editor-multi-root/src/multirooteditorui.ts @@ -207,10 +207,11 @@ export default class MultiRootEditorUI extends EditorUI { const editingView = this.editor.editing.view; const editingRoot = editingView.document.getRoot( editable.name! )!; + editingRoot.placeholder = placeholder; + enablePlaceholder( { view: editingView, element: editingRoot, - text: placeholder, isDirectHost: false, keepOnFocus: true } ); diff --git a/packages/ckeditor5-engine/src/view/editableelement.ts b/packages/ckeditor5-engine/src/view/editableelement.ts index 19459835a33..7499f35dc5c 100644 --- a/packages/ckeditor5-engine/src/view/editableelement.ts +++ b/packages/ckeditor5-engine/src/view/editableelement.ts @@ -42,6 +42,13 @@ export default class EditableElement extends ObservableMixin( ContainerElement ) */ declare public isFocused: boolean; + /** + * Placeholder of current editable element. + * + * @observable + */ + declare public placeholder?: string; + /** * Creates an editable element. * @@ -62,6 +69,7 @@ export default class EditableElement extends ObservableMixin( ContainerElement ) this.set( 'isReadOnly', false ); this.set( 'isFocused', false ); + this.set( 'placeholder', undefined ); this.bind( 'isReadOnly' ).to( document ); diff --git a/packages/ckeditor5-engine/src/view/placeholder.ts b/packages/ckeditor5-engine/src/view/placeholder.ts index da8ce67ea23..0388c6fb814 100644 --- a/packages/ckeditor5-engine/src/view/placeholder.ts +++ b/packages/ckeditor5-engine/src/view/placeholder.ts @@ -37,10 +37,11 @@ const documentPlaceholders = new WeakMap { // Store information about the element placeholder under its document. documentPlaceholders.get( doc )!.set( element, { @@ -75,9 +76,9 @@ export function enablePlaceholder( { view, element, text, isDirectHost = true, k } ); } - if ( text ) { + if ( element.placeholder ) { documentPlaceholders.get( doc )!.set( element, { - text, + text: element.placeholder, isDirectHost, keepOnFocus, hostElement: isDirectHost ? element : null diff --git a/packages/ckeditor5-engine/src/view/rooteditableelement.ts b/packages/ckeditor5-engine/src/view/rooteditableelement.ts index 1edc05e085f..98acbe5f85c 100644 --- a/packages/ckeditor5-engine/src/view/rooteditableelement.ts +++ b/packages/ckeditor5-engine/src/view/rooteditableelement.ts @@ -19,13 +19,6 @@ const rootNameSymbol = Symbol( 'rootName' ); * editable elements} making them "nested editables". */ export default class RootEditableElement extends EditableElement { - /** - * Placeholder of current editiing root. - * - * @observable - */ - declare public placeholder?: string; - /** * Creates root editable element. * @@ -38,7 +31,6 @@ export default class RootEditableElement extends EditableElement { ) { super( document, name ); - this.set( 'placeholder', undefined ); this.rootName = 'main'; } diff --git a/packages/ckeditor5-engine/tests/view/placeholder.js b/packages/ckeditor5-engine/tests/view/placeholder.js index 3f841ec9c51..05e699c5849 100644 --- a/packages/ckeditor5-engine/tests/view/placeholder.js +++ b/packages/ckeditor5-engine/tests/view/placeholder.js @@ -31,10 +31,10 @@ describe( 'placeholder', () => { setData( view, '
{another div}
' ); const element = viewRoot.getChild( 0 ); + element.placeholder = 'foo bar baz'; enablePlaceholder( { view, - element, - text: 'foo bar baz' + element } ); expect( element.getAttribute( 'data-placeholder' ) ).to.equal( 'foo bar baz' ); @@ -45,10 +45,10 @@ describe( 'placeholder', () => { setData( view, '

' ); viewDocument.isFocused = false; + viewRoot.placeholder = 'foo bar baz'; enablePlaceholder( { view, element: viewRoot, - text: 'foo bar baz', isDirectHost: false } ); @@ -60,10 +60,10 @@ describe( 'placeholder', () => { setData( view, '
first div
{another div}
' ); const element = viewRoot.getChild( 0 ); + element.placeholder = 'foo bar baz'; enablePlaceholder( { view, - element, - text: 'foo bar baz' + element } ); expect( element.getAttribute( 'data-placeholder' ) ).to.equal( 'foo bar baz' ); @@ -74,10 +74,10 @@ describe( 'placeholder', () => { setData( view, '
{another div}
' ); const element = viewRoot.getChild( 0 ); + element.placeholder = 'foo bar baz'; enablePlaceholder( { view, - element, - text: 'foo bar baz' + element } ); expect( element.getAttribute( 'data-placeholder' ) ).to.equal( 'foo bar baz' ); @@ -88,10 +88,10 @@ describe( 'placeholder', () => { setData( view, '
[]
another div
' ); const element = viewRoot.getChild( 0 ); + element.placeholder = 'foo bar baz'; enablePlaceholder( { view, - element, - text: 'foo bar baz' + element } ); expect( element.getAttribute( 'data-placeholder' ) ).to.equal( 'foo bar baz' ); @@ -103,10 +103,10 @@ describe( 'placeholder', () => { const element = viewRoot.getChild( 0 ); viewDocument.isFocused = false; + element.placeholder = 'foo bar baz'; enablePlaceholder( { view, - element, - text: 'foo bar baz' + element } ); view.forceRender(); @@ -119,10 +119,10 @@ describe( 'placeholder', () => { setData( view, '
{another div}
' ); const element = viewRoot.getChild( 0 ); + element.placeholder = 'foo bar baz'; enablePlaceholder( { view, - element, - text: 'foo bar baz' + element } ); expect( element.getAttribute( 'data-placeholder' ) ).to.equal( 'foo bar baz' ); @@ -139,16 +139,16 @@ describe( 'placeholder', () => { setData( view, '
{another div}
' ); const element = viewRoot.getChild( 0 ); + element.placeholder = 'foo bar baz'; enablePlaceholder( { view, - element, - text: 'foo bar baz' + element } ); + element.placeholder = 'new text'; enablePlaceholder( { view, - element, - text: 'new text' + element } ); expect( element.getAttribute( 'data-placeholder' ) ).to.equal( 'new text' ); @@ -159,10 +159,10 @@ describe( 'placeholder', () => { setData( view, '
{another div}
' ); const element = viewRoot.getChild( 0 ); + element.placeholder = 'foo bar baz'; enablePlaceholder( { view, - element, - text: 'foo bar baz' + element } ); setData( view, '

paragraph

' ); @@ -180,16 +180,16 @@ describe( 'placeholder', () => { setData( secondView, '
{another div}
' ); const secondElement = secondRoot.getChild( 0 ); + element.placeholder = 'first placeholder'; enablePlaceholder( { view, - element, - text: 'first placeholder' + element } ); + secondElement.placeholder = 'second placeholder'; enablePlaceholder( { view: secondView, - element: secondElement, - text: 'second placeholder' + element: secondElement } ); expect( element.getAttribute( 'data-placeholder' ) ).to.equal( 'first placeholder' ); @@ -218,10 +218,10 @@ describe( 'placeholder', () => { setData( view, '
{another div}
' ); const element = viewRoot.getChild( 0 ); + element.placeholder = 'foo bar baz'; enablePlaceholder( { view, - element, - text: 'foo bar baz' + element } ); view.change( writer => { @@ -240,10 +240,10 @@ describe( 'placeholder', () => { setData( view, '

' ); viewDocument.isFocused = false; + viewRoot.placeholder = 'foo bar baz'; enablePlaceholder( { view, element: viewRoot, - text: 'foo bar baz', isDirectHost: false } ); @@ -256,10 +256,10 @@ describe( 'placeholder', () => { setData( view, '

foobar

' ); viewDocument.isFocused = false; + viewRoot.placeholder = 'foo bar baz'; enablePlaceholder( { view, element: viewRoot, - text: 'foo bar baz', isDirectHost: false } ); @@ -272,17 +272,17 @@ describe( 'placeholder', () => { setData( view, '

' ); viewDocument.isFocused = false; + viewRoot.placeholder = 'foo'; enablePlaceholder( { view, element: viewRoot, - text: 'foo', isDirectHost: false } ); + viewRoot.getChild( 0 ).placeholder = 'bar'; enablePlaceholder( { view, element: viewRoot.getChild( 0 ), - text: 'bar', isDirectHost: true } ); @@ -295,10 +295,10 @@ describe( 'placeholder', () => { setData( view, '

' ); viewDocument.isFocused = false; + viewRoot.placeholder = 'foo bar baz'; enablePlaceholder( { view, element: viewRoot, - text: 'foo bar baz', isDirectHost: false } ); @@ -312,10 +312,10 @@ describe( 'placeholder', () => { setData( view, '

foobar

' ); viewDocument.isFocused = false; + viewRoot.getChild( 0 ).placeholder = 'foo bar baz'; enablePlaceholder( { view, element: viewRoot.getChild( 0 ), - text: 'foo bar baz', isDirectHost: false } ); @@ -328,10 +328,10 @@ describe( 'placeholder', () => { setData( view, '' ); viewDocument.isFocused = false; + viewRoot.placeholder = 'foo bar baz'; enablePlaceholder( { view, element: viewRoot, - text: 'foo bar baz', isDirectHost: false } ); @@ -343,10 +343,10 @@ describe( 'placeholder', () => { setData( view, 'foo' ); viewDocument.isFocused = false; + viewRoot.placeholder = 'foo bar baz'; enablePlaceholder( { view, element: viewRoot, - text: 'foo bar baz', isDirectHost: false } ); @@ -358,10 +358,10 @@ describe( 'placeholder', () => { setData( view, '
{another div}
' ); const element = viewRoot.getChild( 0 ); + element.placeholder = 'foo bar baz'; enablePlaceholder( { view, element, - text: 'foo bar baz', keepOnFocus: true } ); @@ -384,10 +384,10 @@ describe( 'placeholder', () => { setData( view, '
{another div}
' ); const element = viewRoot.getChild( 0 ); + element.placeholder = 'foo bar baz'; enablePlaceholder( { view, - element, - text: 'foo bar baz' + element // Defaults: keepOnFocus = false } ); @@ -410,10 +410,10 @@ describe( 'placeholder', () => { setData( view, '
[]
' ); const element = viewRoot.getChild( 0 ); + element.placeholder = 'foo bar baz'; enablePlaceholder( { view, element, - text: 'foo bar baz', keepOnFocus: true } ); @@ -440,10 +440,10 @@ describe( 'placeholder', () => { setData( view, '
{another div}
' ); const element = viewRoot.getChild( 0 ); + element.placeholder = 'foo bar baz'; enablePlaceholder( { view, - element, - text: 'foo bar baz' + element } ); expect( element.getAttribute( 'data-placeholder' ) ).to.equal( 'foo bar baz' ); @@ -469,10 +469,10 @@ describe( 'placeholder', () => { setData( view, '

' ); viewDocument.isFocused = false; + viewRoot.placeholder = 'foo bar baz'; enablePlaceholder( { view, element: viewRoot, - text: 'foo bar baz', isDirectHost: false } ); @@ -616,20 +616,20 @@ describe( 'placeholder', () => { it( 'should update placeholder when property in editing root is changed', () => { setData( view, '
{another div}
' ); + viewRoot.placeholder = 'new placeholder'; enablePlaceholder( { view, element: viewRoot, text: 'foo bar baz' } ); - viewRoot.placeholder = 'new placeholder'; - expect( viewRoot.getAttribute( 'data-placeholder' ) ).to.equal( 'new placeholder' ); } ); it( 'should update placeholder when property in editing root is changed (isDirectHost=false)', () => { setData( view, '
{another div}
' ); + viewRoot.placeholder = 'new placeholder'; enablePlaceholder( { view, element: viewRoot, @@ -637,8 +637,6 @@ describe( 'placeholder', () => { isDirectHost: false } ); - viewRoot.placeholder = 'new placeholder'; - expect( viewRoot.getChild( 0 ).getAttribute( 'data-placeholder' ) ).to.equal( 'new placeholder' ); } ); } ); diff --git a/packages/ckeditor5-heading/src/title.ts b/packages/ckeditor5-heading/src/title.ts index d2cc1f563db..7253464845c 100644 --- a/packages/ckeditor5-heading/src/title.ts +++ b/packages/ckeditor5-heading/src/title.ts @@ -354,10 +354,13 @@ export default class Title extends Plugin { // Attach placeholder to the view title element. editor.editing.downcastDispatcher.on>( 'insert:title-content', ( evt, data, conversionApi ) => { + const element: ViewElement & { placeholder?: string } = conversionApi.mapper.toViewElement( data.item )!; + + element.placeholder = titlePlaceholder; + enablePlaceholder( { view, - element: conversionApi.mapper.toViewElement( data.item )!, - text: titlePlaceholder, + element, keepOnFocus: true } ); } ); diff --git a/packages/ckeditor5-image/src/imagecaption/imagecaptionediting.ts b/packages/ckeditor5-image/src/imagecaption/imagecaptionediting.ts index 24c4f77be5c..88fd0aa8fc6 100644 --- a/packages/ckeditor5-image/src/imagecaption/imagecaptionediting.ts +++ b/packages/ckeditor5-image/src/imagecaption/imagecaptionediting.ts @@ -122,10 +122,10 @@ export default class ImageCaptionEditing extends Plugin { const figcaptionElement = writer.createEditableElement( 'figcaption' ); writer.setCustomProperty( 'imageCaption', true, figcaptionElement ); + figcaptionElement.placeholder = t( 'Enter image caption' ); enablePlaceholder( { view, element: figcaptionElement, - text: t( 'Enter image caption' ), keepOnFocus: true } ); From 2db58951b8380690061713a97a4f5f58655a1bf4 Mon Sep 17 00:00:00 2001 From: Illia Sheremetov Date: Tue, 25 Jul 2023 09:49:19 +0200 Subject: [PATCH 05/14] Fix (table): fix table enabling placeholder --- .../ckeditor5-table/src/tablecaption/tablecaptionediting.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/ckeditor5-table/src/tablecaption/tablecaptionediting.ts b/packages/ckeditor5-table/src/tablecaption/tablecaptionediting.ts index aebd514e034..b417d548aac 100644 --- a/packages/ckeditor5-table/src/tablecaption/tablecaptionediting.ts +++ b/packages/ckeditor5-table/src/tablecaption/tablecaptionediting.ts @@ -95,10 +95,11 @@ export default class TableCaptionEditing extends Plugin { const figcaptionElement = writer.createEditableElement( 'figcaption' ); writer.setCustomProperty( 'tableCaption', true, figcaptionElement ); + figcaptionElement.placeholder = t( 'Enter table caption' ); + enablePlaceholder( { view, element: figcaptionElement, - text: t( 'Enter table caption' ), keepOnFocus: true } ); From 450d1dc658e6c79da23723a7688ecaf8b3d05a14 Mon Sep 17 00:00:00 2001 From: Illia Sheremetov Date: Tue, 25 Jul 2023 12:03:32 +0200 Subject: [PATCH 06/14] Fix (engine): bring back CC to 100% --- packages/ckeditor5-engine/src/view/placeholder.ts | 12 +++++++++--- packages/ckeditor5-engine/tests/view/placeholder.js | 4 ++-- packages/ckeditor5-heading/src/title.ts | 5 +++-- .../src/imagecaption/imagecaptionediting.ts | 2 +- 4 files changed, 15 insertions(+), 8 deletions(-) diff --git a/packages/ckeditor5-engine/src/view/placeholder.ts b/packages/ckeditor5-engine/src/view/placeholder.ts index 0388c6fb814..ec41487b6df 100644 --- a/packages/ckeditor5-engine/src/view/placeholder.ts +++ b/packages/ckeditor5-engine/src/view/placeholder.ts @@ -11,6 +11,7 @@ import '../../theme/placeholder.css'; import type Document from './document'; import type DowncastWriter from './downcastwriter'; +import type EditableElement from './editableelement'; import type Element from './element'; import type View from './view'; @@ -39,9 +40,7 @@ const documentPlaceholders = new WeakMap { it( 'should update placeholder when property in editing root is changed', () => { setData( view, '
{another div}
' ); - viewRoot.placeholder = 'new placeholder'; enablePlaceholder( { view, element: viewRoot, text: 'foo bar baz' } ); + viewRoot.placeholder = 'new placeholder'; expect( viewRoot.getAttribute( 'data-placeholder' ) ).to.equal( 'new placeholder' ); } ); @@ -629,13 +629,13 @@ describe( 'placeholder', () => { it( 'should update placeholder when property in editing root is changed (isDirectHost=false)', () => { setData( view, '
{another div}
' ); - viewRoot.placeholder = 'new placeholder'; enablePlaceholder( { view, element: viewRoot, text: 'foo bar baz', isDirectHost: false } ); + viewRoot.placeholder = 'new placeholder'; expect( viewRoot.getChild( 0 ).getAttribute( 'data-placeholder' ) ).to.equal( 'new placeholder' ); } ); diff --git a/packages/ckeditor5-heading/src/title.ts b/packages/ckeditor5-heading/src/title.ts index 7253464845c..aa509f2d187 100644 --- a/packages/ckeditor5-heading/src/title.ts +++ b/packages/ckeditor5-heading/src/title.ts @@ -25,7 +25,8 @@ import { type UpcastElementEvent, type View, type ViewElement, - type Writer + type Writer, + type PlaceholderableElement } from 'ckeditor5/src/engine'; // A list of element names that should be treated by the Title plugin as title-like. @@ -354,7 +355,7 @@ export default class Title extends Plugin { // Attach placeholder to the view title element. editor.editing.downcastDispatcher.on>( 'insert:title-content', ( evt, data, conversionApi ) => { - const element: ViewElement & { placeholder?: string } = conversionApi.mapper.toViewElement( data.item )!; + const element: PlaceholderableElement = conversionApi.mapper.toViewElement( data.item )!; element.placeholder = titlePlaceholder; diff --git a/packages/ckeditor5-image/src/imagecaption/imagecaptionediting.ts b/packages/ckeditor5-image/src/imagecaption/imagecaptionediting.ts index 88fd0aa8fc6..022b4be371d 100644 --- a/packages/ckeditor5-image/src/imagecaption/imagecaptionediting.ts +++ b/packages/ckeditor5-image/src/imagecaption/imagecaptionediting.ts @@ -8,7 +8,7 @@ */ import { type Editor, Plugin, type CommandExecuteEvent } from 'ckeditor5/src/core'; -import { Element, enablePlaceholder, type DocumentChangeEvent, type DiffItemAttribute } from 'ckeditor5/src/engine'; +import { Element, enablePlaceholder, type DocumentChangeEvent, type DiffItemAttribute, PlaceholderableElement } from 'ckeditor5/src/engine'; import { toWidgetEditable } from 'ckeditor5/src/widget'; import type { GetCallback } from 'ckeditor5/src/utils'; From a753adc7f0b24ba3570a6fc51af7678190b35dd3 Mon Sep 17 00:00:00 2001 From: Illia Sheremetov Date: Tue, 25 Jul 2023 12:36:48 +0200 Subject: [PATCH 07/14] Fix (media-embed): fix the test with placeholder --- packages/ckeditor5-media-embed/tests/integration.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/ckeditor5-media-embed/tests/integration.js b/packages/ckeditor5-media-embed/tests/integration.js index d6b9d4c1fb6..46ab59518ce 100644 --- a/packages/ckeditor5-media-embed/tests/integration.js +++ b/packages/ckeditor5-media-embed/tests/integration.js @@ -32,11 +32,12 @@ describe( 'MediaEmbed integration', () => { const editor = await ClassicTestEditor.create( element, { plugins: [ MediaEmbed, Paragraph ] } ); + const editingRoot = editor.editing.view.document.getRoot(); + editingRoot.placeholder = 'foo'; enablePlaceholder( { view: editor.editing.view, - element: editor.editing.view.document.getRoot(), - text: 'foo', + element: editingRoot, isDirectHost: false } ); From 32d4d8fcdcf2b59ee84b709c1c4ec75ed2ff9694 Mon Sep 17 00:00:00 2001 From: Illia Sheremetov Date: Tue, 25 Jul 2023 13:53:53 +0200 Subject: [PATCH 08/14] fix (engine): code review fixes --- .../src/ballooneditorui.ts | 4 +++- .../src/decouplededitorui.ts | 4 +++- .../src/inlineeditorui.ts | 4 +++- .../src/multirooteditorui.ts | 4 +++- .../src/view/editableelement.ts | 4 +++- .../ckeditor5-engine/src/view/placeholder.ts | 19 +++++++------------ 6 files changed, 22 insertions(+), 17 deletions(-) diff --git a/packages/ckeditor5-editor-balloon/src/ballooneditorui.ts b/packages/ckeditor5-editor-balloon/src/ballooneditorui.ts index 03b74c57e9e..f34f456b430 100644 --- a/packages/ckeditor5-editor-balloon/src/ballooneditorui.ts +++ b/packages/ckeditor5-editor-balloon/src/ballooneditorui.ts @@ -117,7 +117,9 @@ export default class BalloonEditorUI extends EditorUI { placeholderText = typeof placeholder === 'string' ? placeholder : placeholder[ editingRoot.rootName ]; } - editingRoot.placeholder = placeholderText; + if ( placeholderText ) { + editingRoot.placeholder = placeholderText; + } enablePlaceholder( { view: editingView, diff --git a/packages/ckeditor5-editor-decoupled/src/decouplededitorui.ts b/packages/ckeditor5-editor-decoupled/src/decouplededitorui.ts index 2fef9903de5..f2ce48219c1 100644 --- a/packages/ckeditor5-editor-decoupled/src/decouplededitorui.ts +++ b/packages/ckeditor5-editor-decoupled/src/decouplededitorui.ts @@ -125,7 +125,9 @@ export default class DecoupledEditorUI extends EditorUI { placeholderText = typeof placeholder === 'string' ? placeholder : placeholder[ editingRoot.rootName ]; } - editingRoot.placeholder = placeholderText; + if ( placeholderText ) { + editingRoot.placeholder = placeholderText; + } enablePlaceholder( { view: editingView, diff --git a/packages/ckeditor5-editor-inline/src/inlineeditorui.ts b/packages/ckeditor5-editor-inline/src/inlineeditorui.ts index b9cf3eb5510..774c8d3c4be 100644 --- a/packages/ckeditor5-editor-inline/src/inlineeditorui.ts +++ b/packages/ckeditor5-editor-inline/src/inlineeditorui.ts @@ -160,7 +160,9 @@ export default class InlineEditorUI extends EditorUI { placeholderText = typeof placeholder === 'string' ? placeholder : placeholder[ editingRoot.rootName ]; } - editingRoot.placeholder = placeholderText; + if ( placeholderText ) { + editingRoot.placeholder = placeholderText; + } if ( placeholderText ) { enablePlaceholder( { diff --git a/packages/ckeditor5-editor-multi-root/src/multirooteditorui.ts b/packages/ckeditor5-editor-multi-root/src/multirooteditorui.ts index c41af0254b5..1cd0e30241d 100644 --- a/packages/ckeditor5-editor-multi-root/src/multirooteditorui.ts +++ b/packages/ckeditor5-editor-multi-root/src/multirooteditorui.ts @@ -207,7 +207,9 @@ export default class MultiRootEditorUI extends EditorUI { const editingView = this.editor.editing.view; const editingRoot = editingView.document.getRoot( editable.name! )!; - editingRoot.placeholder = placeholder; + if ( placeholder ) { + editingRoot.placeholder = placeholder; + } enablePlaceholder( { view: editingView, diff --git a/packages/ckeditor5-engine/src/view/editableelement.ts b/packages/ckeditor5-engine/src/view/editableelement.ts index 7499f35dc5c..282a9be7f10 100644 --- a/packages/ckeditor5-engine/src/view/editableelement.ts +++ b/packages/ckeditor5-engine/src/view/editableelement.ts @@ -43,7 +43,9 @@ export default class EditableElement extends ObservableMixin( ContainerElement ) declare public isFocused: boolean; /** - * Placeholder of current editable element. + * Placeholder of editable element. Could be updated. + * + * editor.editing.view.document.getRoot( 'main' ).placeholder = 'New placeholder'; * * @observable */ diff --git a/packages/ckeditor5-engine/src/view/placeholder.ts b/packages/ckeditor5-engine/src/view/placeholder.ts index ec41487b6df..6f1c657d7e3 100644 --- a/packages/ckeditor5-engine/src/view/placeholder.ts +++ b/packages/ckeditor5-engine/src/view/placeholder.ts @@ -31,7 +31,6 @@ const documentPlaceholders = new WeakMap { - // Store information about the element placeholder under its document. - documentPlaceholders.get( doc )!.set( element, { - text, - isDirectHost, - keepOnFocus, - hostElement: isDirectHost ? element : null - } ); - - // Update the placeholders right away. - view.change( writer => updateDocumentPlaceholders( doc, writer ) ); + setPlaceholder( text ); } ); } if ( element.placeholder ) { + setPlaceholder( element.placeholder ); + } + + function setPlaceholder( text: string ) { + // Store information about the element placeholder under its document. documentPlaceholders.get( doc )!.set( element, { - text: element.placeholder, + text, isDirectHost, keepOnFocus, hostElement: isDirectHost ? element : null From ce44c03034b486bd57e65d3f3c6de173b70d8abf Mon Sep 17 00:00:00 2001 From: Marek Lewandowski Date: Wed, 26 Jul 2023 08:54:45 +0200 Subject: [PATCH 09/14] Internal: Enclose placeholder handling within a single if block. --- .../ckeditor5-editor-balloon/src/ballooneditorui.ts | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/packages/ckeditor5-editor-balloon/src/ballooneditorui.ts b/packages/ckeditor5-editor-balloon/src/ballooneditorui.ts index f34f456b430..07d1c9887df 100644 --- a/packages/ckeditor5-editor-balloon/src/ballooneditorui.ts +++ b/packages/ckeditor5-editor-balloon/src/ballooneditorui.ts @@ -109,16 +109,14 @@ export default class BalloonEditorUI extends EditorUI { const editor = this.editor; const editingView = editor.editing.view; const editingRoot = editingView.document.getRoot()!; - const placeholder = editor.config.get( 'placeholder' ); - let placeholderText; if ( placeholder ) { - placeholderText = typeof placeholder === 'string' ? placeholder : placeholder[ editingRoot.rootName ]; - } + const placeholderText = typeof placeholder === 'string' ? placeholder : placeholder[ editingRoot.rootName ]; - if ( placeholderText ) { - editingRoot.placeholder = placeholderText; + if ( placeholderText ) { + editingRoot.placeholder = placeholderText; + } } enablePlaceholder( { From 8be265ba296876dc7a623093ae59085a64b0a17d Mon Sep 17 00:00:00 2001 From: Marek Lewandowski Date: Wed, 26 Jul 2023 09:07:31 +0200 Subject: [PATCH 10/14] Updated the comment - placeholder is also added if no initial placeholder text is passed. --- .../ckeditor5-editor-balloon/src/ballooneditorui.ts | 2 +- .../ckeditor5-editor-classic/src/classiceditorui.ts | 2 +- .../src/decouplededitorui.ts | 12 +++++------- 3 files changed, 7 insertions(+), 9 deletions(-) diff --git a/packages/ckeditor5-editor-balloon/src/ballooneditorui.ts b/packages/ckeditor5-editor-balloon/src/ballooneditorui.ts index 07d1c9887df..b83609aa51a 100644 --- a/packages/ckeditor5-editor-balloon/src/ballooneditorui.ts +++ b/packages/ckeditor5-editor-balloon/src/ballooneditorui.ts @@ -103,7 +103,7 @@ export default class BalloonEditorUI extends EditorUI { } /** - * Enable the placeholder text on the editing root, if any was configured. + * Enable the placeholder text on the editing root. */ private _initPlaceholder(): void { const editor = this.editor; diff --git a/packages/ckeditor5-editor-classic/src/classiceditorui.ts b/packages/ckeditor5-editor-classic/src/classiceditorui.ts index b5655b5adef..a7066a6bd2b 100644 --- a/packages/ckeditor5-editor-classic/src/classiceditorui.ts +++ b/packages/ckeditor5-editor-classic/src/classiceditorui.ts @@ -142,7 +142,7 @@ export default class ClassicEditorUI extends EditorUI { } /** - * Enable the placeholder text on the editing root, if any was configured. + * Enable the placeholder text on the editing root. */ private _initPlaceholder(): void { const editor = this.editor; diff --git a/packages/ckeditor5-editor-decoupled/src/decouplededitorui.ts b/packages/ckeditor5-editor-decoupled/src/decouplededitorui.ts index f2ce48219c1..20fe5ae520c 100644 --- a/packages/ckeditor5-editor-decoupled/src/decouplededitorui.ts +++ b/packages/ckeditor5-editor-decoupled/src/decouplededitorui.ts @@ -111,22 +111,20 @@ export default class DecoupledEditorUI extends EditorUI { } /** - * Enable the placeholder text on the editing root, if any was configured. + * Enable the placeholder text on the editing root. */ private _initPlaceholder(): void { const editor = this.editor; const editingView = editor.editing.view; const editingRoot = editingView.document.getRoot()!; - const placeholder = editor.config.get( 'placeholder' ); - let placeholderText; if ( placeholder ) { - placeholderText = typeof placeholder === 'string' ? placeholder : placeholder[ editingRoot.rootName ]; - } + const placeholderText = typeof placeholder === 'string' ? placeholder : placeholder[ editingRoot.rootName ]; - if ( placeholderText ) { - editingRoot.placeholder = placeholderText; + if ( placeholderText ) { + editingRoot.placeholder = placeholderText; + } } enablePlaceholder( { From 54a683fbd8af8dbf8482bcfc69c082bcc52060b3 Mon Sep 17 00:00:00 2001 From: Marek Lewandowski Date: Wed, 26 Jul 2023 09:08:21 +0200 Subject: [PATCH 11/14] Fixed handling for placeholders in inline editor. --- .../src/inlineeditorui.ts | 26 ++++++++----------- 1 file changed, 11 insertions(+), 15 deletions(-) diff --git a/packages/ckeditor5-editor-inline/src/inlineeditorui.ts b/packages/ckeditor5-editor-inline/src/inlineeditorui.ts index 774c8d3c4be..0ae5c1e2a1c 100644 --- a/packages/ckeditor5-editor-inline/src/inlineeditorui.ts +++ b/packages/ckeditor5-editor-inline/src/inlineeditorui.ts @@ -146,31 +146,27 @@ export default class InlineEditorUI extends EditorUI { } /** - * Enable the placeholder text on the editing root, if any was configured. + * Enable the placeholder text on the editing root. */ private _initPlaceholder(): void { const editor = this.editor; const editingView = editor.editing.view; const editingRoot = editingView.document.getRoot()!; - const placeholder = editor.config.get( 'placeholder' ); - let placeholderText; if ( placeholder ) { - placeholderText = typeof placeholder === 'string' ? placeholder : placeholder[ editingRoot.rootName ]; - } + const placeholderText = typeof placeholder === 'string' ? placeholder : placeholder[ editingRoot.rootName ]; - if ( placeholderText ) { - editingRoot.placeholder = placeholderText; + if ( placeholderText ) { + editingRoot.placeholder = placeholderText; + } } - if ( placeholderText ) { - enablePlaceholder( { - view: editingView, - element: editingRoot, - isDirectHost: false, - keepOnFocus: true - } ); - } + enablePlaceholder( { + view: editingView, + element: editingRoot, + isDirectHost: false, + keepOnFocus: true + } ); } } From bf66c004c174da7b93738e21a267deaa16347ed0 Mon Sep 17 00:00:00 2001 From: Marek Lewandowski Date: Wed, 26 Jul 2023 10:02:57 +0200 Subject: [PATCH 12/14] Few API docs corrections related to placeholders. --- .../ckeditor5-editor-multi-root/src/multirooteditorui.ts | 2 +- packages/ckeditor5-engine/src/view/editableelement.ts | 2 ++ packages/ckeditor5-engine/src/view/placeholder.ts | 8 ++++++-- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/packages/ckeditor5-editor-multi-root/src/multirooteditorui.ts b/packages/ckeditor5-editor-multi-root/src/multirooteditorui.ts index 1cd0e30241d..dd1475bd3f0 100644 --- a/packages/ckeditor5-editor-multi-root/src/multirooteditorui.ts +++ b/packages/ckeditor5-editor-multi-root/src/multirooteditorui.ts @@ -189,7 +189,7 @@ export default class MultiRootEditorUI extends EditorUI { } /** - * Enables the placeholder text on a given editable, if the placeholder was configured. + * Enables the placeholder text on a given editable. * * @param editable Editable on which the placeholder should be set. * @param placeholder Placeholder for the editable element. If not set, placeholder value from the diff --git a/packages/ckeditor5-engine/src/view/editableelement.ts b/packages/ckeditor5-engine/src/view/editableelement.ts index 282a9be7f10..d768a723fa4 100644 --- a/packages/ckeditor5-engine/src/view/editableelement.ts +++ b/packages/ckeditor5-engine/src/view/editableelement.ts @@ -45,7 +45,9 @@ export default class EditableElement extends ObservableMixin( ContainerElement ) /** * Placeholder of editable element. Could be updated. * + * ```ts * editor.editing.view.document.getRoot( 'main' ).placeholder = 'New placeholder'; + * ``` * * @observable */ diff --git a/packages/ckeditor5-engine/src/view/placeholder.ts b/packages/ckeditor5-engine/src/view/placeholder.ts index 6f1c657d7e3..30c37da906a 100644 --- a/packages/ckeditor5-engine/src/view/placeholder.ts +++ b/packages/ckeditor5-engine/src/view/placeholder.ts @@ -24,7 +24,7 @@ const documentPlaceholders = new WeakMap Date: Wed, 26 Jul 2023 12:44:46 +0200 Subject: [PATCH 13/14] Apply suggestions from code review --- docs/features/editor-placeholder.md | 6 +++--- packages/ckeditor5-engine/src/view/editableelement.ts | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/features/editor-placeholder.md b/docs/features/editor-placeholder.md index a006cb87411..6b8f04fc08e 100644 --- a/docs/features/editor-placeholder.md +++ b/docs/features/editor-placeholder.md @@ -108,12 +108,12 @@ The editor placeholder text is displayed using a CSS pseudo–element (`::before **Note**: The `.ck-placeholder` class is also used to display placeholders in other places, for instance, {@link features/images-captions image captions}. Make sure your custom styles apply to the right subset of placeholders. -## Updating the placeholder +## Changing the placeholder -The editor placeholder could be updated in runtime changing `placeholder` property in editing root. You can use it also in {@link installation/getting-started/predefined-builds#multi-root-editor `Multi-root editor`} and {@link installation/getting-started/predefined-builds#inline-editor `Inline editor`}. +The editor placeholder could be updated at runtime by changing the `placeholder` property in editing root. ```js -editor.editing.view.document.getRoot( 'main' ).placeholder = 'new placeholder' +editor.editing.view.document.getRoot( 'main' ).placeholder = 'new placeholder'; ``` {@snippet features/update-placeholder} diff --git a/packages/ckeditor5-engine/src/view/editableelement.ts b/packages/ckeditor5-engine/src/view/editableelement.ts index d768a723fa4..eae3e9a967e 100644 --- a/packages/ckeditor5-engine/src/view/editableelement.ts +++ b/packages/ckeditor5-engine/src/view/editableelement.ts @@ -43,7 +43,7 @@ export default class EditableElement extends ObservableMixin( ContainerElement ) declare public isFocused: boolean; /** - * Placeholder of editable element. Could be updated. + * Placeholder of editable element. * * ```ts * editor.editing.view.document.getRoot( 'main' ).placeholder = 'New placeholder'; From 869dd2029f11bfbd74790670ba4ef1b29df4d8b8 Mon Sep 17 00:00:00 2001 From: Marek Lewandowski Date: Wed, 26 Jul 2023 12:46:24 +0200 Subject: [PATCH 14/14] Changed type to an interface. --- packages/ckeditor5-engine/src/view/placeholder.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/ckeditor5-engine/src/view/placeholder.ts b/packages/ckeditor5-engine/src/view/placeholder.ts index 30c37da906a..0e374d08f48 100644 --- a/packages/ckeditor5-engine/src/view/placeholder.ts +++ b/packages/ckeditor5-engine/src/view/placeholder.ts @@ -310,12 +310,12 @@ interface PlaceholderConfig { } /** - * Element which could have a placeholder. + * Element that could have a placeholder. */ -export type PlaceholderableElement = Element & { +export interface PlaceholderableElement extends Element { /** - * Placeholder of the editable element. + * The text of element's placeholder. */ placeholder?: string; -}; +}