From 3015814a7abd3621cf53c9adc9992e910c2f8593 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Szymon=20Kup=C5=9B?= Date: Mon, 7 May 2018 15:47:12 +0200 Subject: [PATCH 01/13] Allow to pass data to the constructor instaead of element to replace. --- src/classiceditor.js | 27 +++++++++---- tests/manual/classiceditor-data.html | 18 +++++++++ tests/manual/classiceditor-data.js | 60 ++++++++++++++++++++++++++++ tests/manual/classiceditor-data.md | 18 +++++++++ 4 files changed, 116 insertions(+), 7 deletions(-) create mode 100644 tests/manual/classiceditor-data.html create mode 100644 tests/manual/classiceditor-data.js create mode 100644 tests/manual/classiceditor-data.md diff --git a/src/classiceditor.js b/src/classiceditor.js index 3612150..cca0a7b 100644 --- a/src/classiceditor.js +++ b/src/classiceditor.js @@ -17,6 +17,7 @@ import ClassicEditorUIView from './classiceditoruiview'; import ElementReplacer from '@ckeditor/ckeditor5-utils/src/elementreplacer'; import getDataFromElement from '@ckeditor/ckeditor5-utils/src/dom/getdatafromelement'; import mix from '@ckeditor/ckeditor5-utils/src/mix'; +import isElement from '@ckeditor/ckeditor5-utils/src/lib/lodash/isElement'; /** * The {@glink builds/guides/overview#classic-editor classic editor} implementation. @@ -57,9 +58,13 @@ export default class ClassicEditor extends Editor { * The data will be loaded from it and loaded back to it once the editor is destroyed. * @param {module:core/editor/editorconfig~EditorConfig} config The editor configuration. */ - constructor( element, config ) { + constructor( elementOrData, config ) { super( config ); + if ( isElement( elementOrData ) ) { + this.element = elementOrData; + } + /** * The element replacer instance used to hide the editor element. * @@ -68,8 +73,6 @@ export default class ClassicEditor extends Editor { */ this._elementReplacer = new ElementReplacer(); - this.element = element; - this.data.processor = new HtmlDataProcessor(); this.model.document.createRoot(); @@ -134,19 +137,29 @@ export default class ClassicEditor extends Editor { * @returns {Promise} A promise resolved once the editor is ready. * The promise returns the created {@link module:editor-classic/classiceditor~ClassicEditor} instance. */ - static create( element, config ) { + static create( elementOrData, config ) { return new Promise( resolve => { - const editor = new this( element, config ); + const editor = new this( elementOrData, config ); resolve( editor.initPlugins() .then( () => editor.ui.init() ) .then( () => { - editor._elementReplacer.replace( element, editor.ui.view.element ); + if ( isElement( elementOrData ) ) { + editor._elementReplacer.replace( elementOrData, editor.ui.view.element ); + } + editor.fire( 'uiReady' ); } ) .then( () => editor.editing.view.attachDomRoot( editor.ui.view.editableElement ) ) - .then( () => editor.data.init( getDataFromElement( element ) ) ) + .then( () => { + if ( editor.element ) { + editor.data.init( getDataFromElement( editor.element ) ); + } else { + editor.data.init( elementOrData ); + editor.element = editor.ui.view.element; + } + } ) .then( () => { editor.fire( 'dataReady' ); editor.fire( 'ready' ); diff --git a/tests/manual/classiceditor-data.html b/tests/manual/classiceditor-data.html new file mode 100644 index 0000000..168f3a1 --- /dev/null +++ b/tests/manual/classiceditor-data.html @@ -0,0 +1,18 @@ +

+ + +

+ + diff --git a/tests/manual/classiceditor-data.js b/tests/manual/classiceditor-data.js new file mode 100644 index 0000000..e0f00fc --- /dev/null +++ b/tests/manual/classiceditor-data.js @@ -0,0 +1,60 @@ +/** + * @license Copyright (c) 2003-2018, CKSource - Frederico Knabben. All rights reserved. + * For licensing, see LICENSE.md. + */ + +/* globals console:false, document, window */ + +import ClassicEditor from '../../src/classiceditor'; +import Enter from '@ckeditor/ckeditor5-enter/src/enter'; +import Typing from '@ckeditor/ckeditor5-typing/src/typing'; +import Heading from '@ckeditor/ckeditor5-heading/src/heading'; +import Paragraph from '@ckeditor/ckeditor5-paragraph/src/paragraph'; +import Undo from '@ckeditor/ckeditor5-undo/src/undo'; +import Bold from '@ckeditor/ckeditor5-basic-styles/src/bold'; +import Italic from '@ckeditor/ckeditor5-basic-styles/src/italic'; +import testUtils from '@ckeditor/ckeditor5-utils/tests/_utils/utils'; + +let editor, editable, observer; + +const data = '

Hello world!

This is an editor instance.

'; + +function initEditor() { + ClassicEditor + .create( data, { + plugins: [ Enter, Typing, Paragraph, Undo, Heading, Bold, Italic ], + toolbar: [ 'heading', '|', 'bold', 'italic', 'undo', 'redo' ] + } ) + .then( newEditor => { + console.log( 'Editor was initialized', newEditor ); + console.log( 'You can now play with it using global `editor` and `editable` variables.' ); + + window.editor = editor = newEditor; + window.editable = editable = editor.editing.view.document.getRoot(); + + observer = testUtils.createObserver(); + observer.observe( 'Editable', editable, [ 'isFocused' ] ); + + document.body.appendChild( editor.element ); + } ) + .catch( err => { + console.error( err.stack ); + } ); +} + +function destroyEditor() { + editor.destroy() + .then( () => { + editor.element.remove(); + + window.editor = editor = null; + window.editable = editable = null; + + observer.stopListening(); + observer = null; + console.log( 'Editor was destroyed' ); + } ); +} + +document.getElementById( 'initEditor' ).addEventListener( 'click', initEditor ); +document.getElementById( 'destroyEditor' ).addEventListener( 'click', destroyEditor ); diff --git a/tests/manual/classiceditor-data.md b/tests/manual/classiceditor-data.md new file mode 100644 index 0000000..0831642 --- /dev/null +++ b/tests/manual/classiceditor-data.md @@ -0,0 +1,18 @@ +1. Click "Init editor". +2. Expected: + * Framed editor should be created. + * Original element should disappear. + * There should be a toolbar with "Bold", "Italic", "Undo" and "Redo" buttons. +3. Click "Destroy editor". +4. Expected: + * Editor should be destroyed. + * Original element should be visible. + * The element should contain its data (updated). + * The 'ck-body region' should be removed. + +## Notes: + +* You can play with: + * `editable.isReadOnly`, +* Changes to `editable.isFocused` should be logged to the console. +* Features should work. From 5af49aa637823846f0d7dd79d8c0e64501efd6d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Szymon=20Kup=C5=9B?= Date: Wed, 9 May 2018 10:24:37 +0200 Subject: [PATCH 02/13] Added tests checking data initialization. --- tests/classiceditor.js | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/tests/classiceditor.js b/tests/classiceditor.js index 3ceece2..319d00b 100644 --- a/tests/classiceditor.js +++ b/tests/classiceditor.js @@ -88,6 +88,22 @@ describe( 'ClassicEditor', () => { } ); } ); + it( 'allows to pass data to the constructor', () => { + return ClassicEditor.create( '

Hello world!

', { + plugins: [ Paragraph ] + } ).then( editor => { + expect( editor.getData() ).to.equal( '

Hello world!

' ); + } ); + } ); + + it( 'editor.element should be equal to editor.ui.view.element when data is passed', () => { + return ClassicEditor.create( '

Hello world!

', { + plugins: [ Paragraph ] + } ).then( editor => { + expect( editor.element ).to.equal( editor.ui.view.element ); + } ); + } ); + describe( 'ui', () => { it( 'creates the UI using BoxedEditorUI classes', () => { expect( editor.ui ).to.be.instanceof( ClassicEditorUI ); From 633b5d388e06f5d2ab96156286d53ce06717422a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Szymon=20Kup=C5=9B?= Date: Tue, 15 May 2018 17:12:19 +0200 Subject: [PATCH 03/13] Improved documentation. --- src/classiceditor.js | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/src/classiceditor.js b/src/classiceditor.js index cca0a7b..6d41f39 100644 --- a/src/classiceditor.js +++ b/src/classiceditor.js @@ -54,8 +54,10 @@ export default class ClassicEditor extends Editor { * {@link module:editor-classic/classiceditor~ClassicEditor.create `ClassicEditor.create()`} method instead. * * @protected - * @param {HTMLElement} element The DOM element that will be the source for the created editor. - * The data will be loaded from it and loaded back to it once the editor is destroyed. + * @param {HTMLElement} elementOrData The DOM element that will be the source for the created editor. + * The data will be loaded from it and loaded back to it once the editor is destroyed. If data is provided, `editor.element` + * should be added manually to the DOM after the editor is initialized. For more information see + * {@link module:editor-classic/classiceditor~ClassicEditor.create `ClassicEditor.create()`}. * @param {module:core/editor/editorconfig~EditorConfig} config The editor configuration. */ constructor( elementOrData, config ) { @@ -131,6 +133,29 @@ export default class ClassicEditor extends Editor { * console.error( err.stack ); * } ); * + * Creating instance when using initial data instead of DOM element: + * + * import ClassicEditor from '@ckeditor/ckeditor5-editor-classic/src/classiceditor'; + * import Essentials from '@ckeditor/ckeditor5-essentials/src/essentials'; + * import Bold from '@ckeditor/ckeditor5-basic-styles/src/bold'; + * import Italic from '@ckeditor/ckeditor5-basic-styles/src/italic'; + * import ... + * + * ClassicEditor + * .create( '

Hello world!

', { + * plugins: [ Essentials, Bold, Italic, ... ], + * toolbar: [ 'bold', 'italic', ... ] + * } ) + * .then( editor => { + * console.log( 'Editor was initialized', editor ); + * + * // Initial data was provided so `editor.element` needs to be added manually to the DOM. + * document.body.appendChild( editor.element ); + * } ) + * .catch( err => { + * console.error( err.stack ); + * } ); + * * @param {HTMLElement} element The DOM element that will be the source for the created editor. * The data will be loaded from it and loaded back to it once the editor is destroyed. * @param {module:core/editor/editorconfig~EditorConfig} config The editor configuration. From f38aec793645d0d282935547b9366d2f29d9bf99 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Szymon=20Kup=C5=9B?= Date: Tue, 15 May 2018 18:49:46 +0200 Subject: [PATCH 04/13] Improved manual test with data initialization. --- tests/manual/classiceditor-data.js | 34 +++++++++--------------------- tests/manual/classiceditor-data.md | 19 ++--------------- 2 files changed, 12 insertions(+), 41 deletions(-) diff --git a/tests/manual/classiceditor-data.js b/tests/manual/classiceditor-data.js index e0f00fc..018dfc4 100644 --- a/tests/manual/classiceditor-data.js +++ b/tests/manual/classiceditor-data.js @@ -13,28 +13,19 @@ import Paragraph from '@ckeditor/ckeditor5-paragraph/src/paragraph'; import Undo from '@ckeditor/ckeditor5-undo/src/undo'; import Bold from '@ckeditor/ckeditor5-basic-styles/src/bold'; import Italic from '@ckeditor/ckeditor5-basic-styles/src/italic'; -import testUtils from '@ckeditor/ckeditor5-utils/tests/_utils/utils'; - -let editor, editable, observer; const data = '

Hello world!

This is an editor instance.

'; +window.editors = []; + function initEditor() { ClassicEditor .create( data, { plugins: [ Enter, Typing, Paragraph, Undo, Heading, Bold, Italic ], toolbar: [ 'heading', '|', 'bold', 'italic', 'undo', 'redo' ] } ) - .then( newEditor => { - console.log( 'Editor was initialized', newEditor ); - console.log( 'You can now play with it using global `editor` and `editable` variables.' ); - - window.editor = editor = newEditor; - window.editable = editable = editor.editing.view.document.getRoot(); - - observer = testUtils.createObserver(); - observer.observe( 'Editable', editable, [ 'isFocused' ] ); - + .then( editor => { + window.editors.push( editor ); document.body.appendChild( editor.element ); } ) .catch( err => { @@ -43,17 +34,12 @@ function initEditor() { } function destroyEditor() { - editor.destroy() - .then( () => { - editor.element.remove(); - - window.editor = editor = null; - window.editable = editable = null; - - observer.stopListening(); - observer = null; - console.log( 'Editor was destroyed' ); - } ); + window.editors.forEach( editor => { + editor.destroy() + .then( () => { + editor.element.remove(); + } ); + } ); } document.getElementById( 'initEditor' ).addEventListener( 'click', initEditor ); diff --git a/tests/manual/classiceditor-data.md b/tests/manual/classiceditor-data.md index 0831642..eeffc09 100644 --- a/tests/manual/classiceditor-data.md +++ b/tests/manual/classiceditor-data.md @@ -1,18 +1,3 @@ 1. Click "Init editor". -2. Expected: - * Framed editor should be created. - * Original element should disappear. - * There should be a toolbar with "Bold", "Italic", "Undo" and "Redo" buttons. -3. Click "Destroy editor". -4. Expected: - * Editor should be destroyed. - * Original element should be visible. - * The element should contain its data (updated). - * The 'ck-body region' should be removed. - -## Notes: - -* You can play with: - * `editable.isReadOnly`, -* Changes to `editable.isFocused` should be logged to the console. -* Features should work. +2. New editor instance should be appended to the document with initial data in it. +3. After clicking "Destroy editor" all editors should be removed from the document. From 3232bfbbdd0eb68cf99a60017bf0a5195e336444 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Szymon=20Kup=C5=9B?= Date: Tue, 15 May 2018 18:51:20 +0200 Subject: [PATCH 05/13] Removed unused CSS class. --- tests/manual/classiceditor-data.html | 7 ------- 1 file changed, 7 deletions(-) diff --git a/tests/manual/classiceditor-data.html b/tests/manual/classiceditor-data.html index 168f3a1..7bf3aa6 100644 --- a/tests/manual/classiceditor-data.html +++ b/tests/manual/classiceditor-data.html @@ -8,11 +8,4 @@ width: 10000px; height: 10000px; } - - .ck-editor { - margin-top: 200px; - margin-left: 100px; - margin-bottom: 200px; - width: 450px; - } From 8a7ea542ec9f677b6c55571c5286361269f939be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Szymon=20Kup=C5=9B?= Date: Tue, 15 May 2018 18:55:24 +0200 Subject: [PATCH 06/13] Appending editor to the container in data initialization manual test. --- tests/manual/classiceditor-data.html | 7 +++++++ tests/manual/classiceditor-data.js | 4 +++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/tests/manual/classiceditor-data.html b/tests/manual/classiceditor-data.html index 7bf3aa6..5e2ef53 100644 --- a/tests/manual/classiceditor-data.html +++ b/tests/manual/classiceditor-data.html @@ -3,9 +3,16 @@

+
+ diff --git a/tests/manual/classiceditor-data.js b/tests/manual/classiceditor-data.js index 018dfc4..c246eba 100644 --- a/tests/manual/classiceditor-data.js +++ b/tests/manual/classiceditor-data.js @@ -18,6 +18,8 @@ const data = '

Hello world!

This is an editor instance.

'; window.editors = []; +const container = document.querySelector( '.container' ); + function initEditor() { ClassicEditor .create( data, { @@ -26,7 +28,7 @@ function initEditor() { } ) .then( editor => { window.editors.push( editor ); - document.body.appendChild( editor.element ); + container.appendChild( editor.element ); } ) .catch( err => { console.error( err.stack ); From ffdede7c605df8b89330d7ae3299c253e441a761 Mon Sep 17 00:00:00 2001 From: Kamil Piechaczek Date: Tue, 5 Jun 2018 14:37:51 +0200 Subject: [PATCH 07/13] Minor improvements for the manual test. --- tests/manual/classiceditor-data.html | 2 +- tests/manual/classiceditor-data.js | 12 +++++++----- tests/manual/classiceditor-data.md | 2 +- 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/tests/manual/classiceditor-data.html b/tests/manual/classiceditor-data.html index 5e2ef53..645e161 100644 --- a/tests/manual/classiceditor-data.html +++ b/tests/manual/classiceditor-data.html @@ -1,5 +1,5 @@

- +

diff --git a/tests/manual/classiceditor-data.js b/tests/manual/classiceditor-data.js index c246eba..ddf292b 100644 --- a/tests/manual/classiceditor-data.js +++ b/tests/manual/classiceditor-data.js @@ -14,19 +14,19 @@ import Undo from '@ckeditor/ckeditor5-undo/src/undo'; import Bold from '@ckeditor/ckeditor5-basic-styles/src/bold'; import Italic from '@ckeditor/ckeditor5-basic-styles/src/italic'; -const data = '

Hello world!

This is an editor instance.

'; - window.editors = []; +let counter = 1; const container = document.querySelector( '.container' ); function initEditor() { ClassicEditor - .create( data, { + .create( `

Hello world! #${ counter }

This is an editor instance.

`, { plugins: [ Enter, Typing, Paragraph, Undo, Heading, Bold, Italic ], toolbar: [ 'heading', '|', 'bold', 'italic', 'undo', 'redo' ] } ) .then( editor => { + counter += 1; window.editors.push( editor ); container.appendChild( editor.element ); } ) @@ -35,14 +35,16 @@ function initEditor() { } ); } -function destroyEditor() { +function destroyEditors() { window.editors.forEach( editor => { editor.destroy() .then( () => { editor.element.remove(); } ); } ); + window.editors = []; + counter = 1; } document.getElementById( 'initEditor' ).addEventListener( 'click', initEditor ); -document.getElementById( 'destroyEditor' ).addEventListener( 'click', destroyEditor ); +document.getElementById( 'destroyEditors' ).addEventListener( 'click', destroyEditors ); diff --git a/tests/manual/classiceditor-data.md b/tests/manual/classiceditor-data.md index eeffc09..b7c1b95 100644 --- a/tests/manual/classiceditor-data.md +++ b/tests/manual/classiceditor-data.md @@ -1,3 +1,3 @@ 1. Click "Init editor". -2. New editor instance should be appended to the document with initial data in it. +2. New editor instance should be appended to the document with initial data in it. You can create more than one editor. 3. After clicking "Destroy editor" all editors should be removed from the document. From a9497d212ea1df85187c9facaa30079f661b70a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Piotrek=20Koszuli=C5=84ski?= Date: Wed, 6 Jun 2018 13:54:50 +0200 Subject: [PATCH 08/13] Docs: Improved API docs for the create() method. --- src/classiceditor.js | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/src/classiceditor.js b/src/classiceditor.js index 6d41f39..3c27440 100644 --- a/src/classiceditor.js +++ b/src/classiceditor.js @@ -54,9 +54,8 @@ export default class ClassicEditor extends Editor { * {@link module:editor-classic/classiceditor~ClassicEditor.create `ClassicEditor.create()`} method instead. * * @protected - * @param {HTMLElement} elementOrData The DOM element that will be the source for the created editor. - * The data will be loaded from it and loaded back to it once the editor is destroyed. If data is provided, `editor.element` - * should be added manually to the DOM after the editor is initialized. For more information see + * @param {HTMLElement|String} elementOrData The DOM element that will be the source for the created editor + * or editor's initial data. For more information see * {@link module:editor-classic/classiceditor~ClassicEditor.create `ClassicEditor.create()`}. * @param {module:core/editor/editorconfig~EditorConfig} config The editor configuration. */ @@ -133,7 +132,7 @@ export default class ClassicEditor extends Editor { * console.error( err.stack ); * } ); * - * Creating instance when using initial data instead of DOM element: + * Creating instance when using initial data instead of a DOM element: * * import ClassicEditor from '@ckeditor/ckeditor5-editor-classic/src/classiceditor'; * import Essentials from '@ckeditor/ckeditor5-essentials/src/essentials'; @@ -156,8 +155,22 @@ export default class ClassicEditor extends Editor { * console.error( err.stack ); * } ); * - * @param {HTMLElement} element The DOM element that will be the source for the created editor. - * The data will be loaded from it and loaded back to it once the editor is destroyed. + * @param {HTMLElement|String} elementOrData The DOM element that will be the source for the created editor + * or editor's initial data. + * + * If an element is passed, then it contents will be automatically + * {@link module:editor-classic/classiceditor~ClassicEditor#setData loaded} to the editor on startup + * and the editor element will replace the passed element in the DOM (the original one will be hidden and editor + * will be injected next to it). + * + * Moreover, the data will be set back to the original element once the editor is destroyed and + * (if the element is a `