Skip to content
This repository was archived by the owner on Jun 26, 2020. It is now read-only.

Commit cfd8c53

Browse files
authoredJul 3, 2018
Merge pull request #38 from ckeditor/t/37
Feature: Editor can now be created with initial data passed to the constructor. Closes #37. BREAKING CHANGE: The `InlineEditor#element` property was renamed to `InlineEditor#sourceElement`. See ckeditor/ckeditor5-core#64.
2 parents c148346 + 6e17bbf commit cfd8c53

File tree

5 files changed

+159
-15
lines changed

5 files changed

+159
-15
lines changed
 

‎src/inlineeditor.js

+61-13
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import InlineEditorUIView from './inlineeditoruiview';
1717
import setDataInElement from '@ckeditor/ckeditor5-utils/src/dom/setdatainelement';
1818
import getDataFromElement from '@ckeditor/ckeditor5-utils/src/dom/getdatafromelement';
1919
import mix from '@ckeditor/ckeditor5-utils/src/mix';
20+
import isElement from '@ckeditor/ckeditor5-utils/src/lib/lodash/isElement';
2021

2122
/**
2223
* The {@glink builds/guides/overview#inline-editor inline editor} implementation.
@@ -53,24 +54,34 @@ export default class InlineEditor extends Editor {
5354
* {@link module:editor-inline/inlineeditor~InlineEditor.create `InlineEditor.create()`} method instead.
5455
*
5556
* @protected
56-
* @param {HTMLElement} element The DOM element that will be the source for the created editor
57-
* (on which the editor will be initialized).
57+
* @param {HTMLElement|String} sourceElementOrData The DOM element that will be the source for the created editor
58+
* (on which the editor will be initialized) or initial data for the editor. For more information see
59+
* {@link module:editor-inline/inlineeditor~InlineEditor.create `InlineEditor.create()`}.
5860
* @param {module:core/editor/editorconfig~EditorConfig} config The editor configuration.
5961
*/
60-
constructor( element, config ) {
62+
constructor( sourceElementOrData, config ) {
6163
super( config );
6264

63-
this.element = element;
64-
6565
this.data.processor = new HtmlDataProcessor();
6666

6767
this.model.document.createRoot();
6868

69-
this.ui = new InlineEditorUI( this, new InlineEditorUIView( this.locale, element ) );
69+
if ( isElement( sourceElementOrData ) ) {
70+
this.sourceElement = sourceElementOrData;
71+
}
72+
73+
this.ui = new InlineEditorUI( this, new InlineEditorUIView( this.locale, this.sourceElement ) );
7074

7175
attachToForm( this );
7276
}
7377

78+
/**
79+
* @inheritDoc
80+
*/
81+
get element() {
82+
return this.ui.view.editable.element;
83+
}
84+
7485
/**
7586
* Destroys the editor instance, releasing all resources used by it.
7687
*
@@ -86,11 +97,15 @@ export default class InlineEditor extends Editor {
8697
this.ui.destroy();
8798

8899
return super.destroy()
89-
.then( () => setDataInElement( this.element, data ) );
100+
.then( () => {
101+
if ( this.sourceElement ) {
102+
setDataInElement( this.sourceElement, data );
103+
}
104+
} );
90105
}
91106

92107
/**
93-
* Creates a inline editor instance.
108+
* Creates an inline editor instance.
94109
*
95110
* Creating instance when using {@glink builds/index CKEditor build}:
96111
*
@@ -123,23 +138,56 @@ export default class InlineEditor extends Editor {
123138
* console.error( err.stack );
124139
* } );
125140
*
126-
* @param {HTMLElement} element The DOM element that will be the source for the created editor
127-
* (on which the editor will be initialized).
141+
* Creating instance when using initial data instead of a DOM element:
142+
*
143+
* import InlineEditor from '@ckeditor/ckeditor5-editor-inline/src/inlineeditor';
144+
* import Essentials from '@ckeditor/ckeditor5-essentials/src/essentials';
145+
* import Bold from '@ckeditor/ckeditor5-basic-styles/src/bold';
146+
* import Italic from '@ckeditor/ckeditor5-basic-styles/src/italic';
147+
* import ...
148+
*
149+
* InlineEditor
150+
* .create( '<p>Hello world!</p>' )
151+
* .then( editor => {
152+
* console.log( 'Editor was initialized', editor );
153+
*
154+
* // Initial data was provided so `editor.element` needs to be added manually to the DOM.
155+
* document.body.appendChild( editor.element );
156+
* } )
157+
* .catch( err => {
158+
* console.error( err.stack );
159+
* } );
160+
*
161+
* @param {HTMLElement|String} sourceElementOrData The DOM element that will be the source for the created editor
162+
* (on which the editor will be initialized) or initial data for the editor.
163+
*
164+
* If a source element is passed, then its contents will be automatically
165+
* {@link module:editor-classic/inlineeditor~InlineEditor#setData loaded} to the editor on startup and the element
166+
* itself will be used as the editor's editable element.
167+
*
168+
* If a data is provided, then `editor.element` will be created automatically and needs to be added
169+
* manually to the DOM.
128170
* @param {module:core/editor/editorconfig~EditorConfig} config The editor configuration.
129171
* @returns {Promise} A promise resolved once the editor is ready.
130172
* The promise returns the created {@link module:editor-inline/inlineeditor~InlineEditor} instance.
131173
*/
132-
static create( element, config ) {
174+
static create( sourceElementOrData, config ) {
133175
return new Promise( resolve => {
134-
const editor = new this( element, config );
176+
const editor = new this( sourceElementOrData, config );
135177

136178
resolve(
137179
editor.initPlugins()
138180
.then( () => {
139181
editor.ui.init();
140182
editor.fire( 'uiReady' );
141183
} )
142-
.then( () => editor.data.init( getDataFromElement( element ) ) )
184+
.then( () => {
185+
const initialData = isElement( sourceElementOrData ) ?
186+
getDataFromElement( sourceElementOrData ) :
187+
sourceElementOrData;
188+
189+
return editor.data.init( initialData );
190+
} )
143191
.then( () => {
144192
editor.fire( 'dataReady' );
145193
editor.fire( 'ready' );

‎tests/inlineeditor.js

+34-2
Original file line numberDiff line numberDiff line change
@@ -54,11 +54,11 @@ describe( 'InlineEditor', () => {
5454
} );
5555

5656
it( 'has a Data Interface', () => {
57-
testUtils.isMixed( InlineEditor, DataApiMixin );
57+
expect( testUtils.isMixed( InlineEditor, DataApiMixin ) ).to.be.true;
5858
} );
5959

6060
it( 'has a Element Interface', () => {
61-
testUtils.isMixed( InlineEditor, ElementApiMixin );
61+
expect( testUtils.isMixed( InlineEditor, ElementApiMixin ) ).to.be.true;
6262
} );
6363

6464
it( 'creates main root element', () => {
@@ -95,6 +95,30 @@ describe( 'InlineEditor', () => {
9595
} );
9696
} );
9797
} );
98+
99+
it( 'allows to pass data to the constructor', () => {
100+
return InlineEditor.create( '<p>Hello world!</p>', {
101+
plugins: [ Paragraph ]
102+
} ).then( editor => {
103+
expect( editor.getData() ).to.equal( '<p>Hello world!</p>' );
104+
} );
105+
} );
106+
107+
it( 'should have undefined the #sourceElement if editor was initialized with data', () => {
108+
return InlineEditor.create( '<p>Hello world!</p>', {
109+
plugins: [ Paragraph ]
110+
} ).then( editor => {
111+
expect( editor.sourceElement ).to.be.undefined;
112+
} );
113+
} );
114+
115+
it( 'editor.element should contain the whole editor (with UI) element', () => {
116+
return InlineEditor.create( '<p>Hello world!</p>', {
117+
plugins: [ Paragraph ]
118+
} ).then( editor => {
119+
expect( editor.editing.view.getDomRoot() ).to.equal( editor.element );
120+
} );
121+
} );
98122
} );
99123

100124
describe( 'create()', () => {
@@ -264,5 +288,13 @@ describe( 'InlineEditor', () => {
264288
.to.equal( '<p>a</p><heading>b</heading>' );
265289
} );
266290
} );
291+
292+
it( 'should not throw an error if editor was initialized with the data', () => {
293+
return InlineEditor
294+
.create( '<p>Foo.</p>', {
295+
plugins: [ Paragraph, Bold ]
296+
} )
297+
.then( newEditor => newEditor.destroy() );
298+
} );
267299
} );
268300
} );

‎tests/manual/inlineeditor-data.html

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<p>
2+
<button id="destroyEditors">Destroy editors</button>
3+
<button id="initEditor">Init editor</button>
4+
</p>
5+
6+
<div class="container"></div>
7+
8+
<style>
9+
body {
10+
width: 10000px;
11+
height: 10000px;
12+
}
13+
14+
.container {
15+
padding: 20px;
16+
width: 500px;
17+
}
18+
</style>

‎tests/manual/inlineeditor-data.js

+43
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
/**
2+
* @license Copyright (c) 2003-2018, CKSource - Frederico Knabben. All rights reserved.
3+
* For licensing, see LICENSE.md.
4+
*/
5+
6+
/* globals console:false, document, window */
7+
8+
import InlineEditor from '../../src/inlineeditor';
9+
import ArticlePluginSet from '@ckeditor/ckeditor5-core/tests/_utils/articlepluginset';
10+
11+
window.editors = [];
12+
const container = document.querySelector( '.container' );
13+
let counter = 1;
14+
15+
function initEditor() {
16+
InlineEditor
17+
.create( `<h2>Editor ${ counter }</h2><p>This is an editor instance.</p>`, {
18+
plugins: [ ArticlePluginSet ],
19+
toolbar: [ 'heading', '|', 'bold', 'italic', 'link', 'bulletedList', 'numberedList', 'blockQuote', 'undo', 'redo' ]
20+
} )
21+
.then( editor => {
22+
counter += 1;
23+
window.editors.push( editor );
24+
container.appendChild( editor.element );
25+
} )
26+
.catch( err => {
27+
console.error( err.stack );
28+
} );
29+
}
30+
31+
function destroyEditors() {
32+
window.editors.forEach( editor => {
33+
editor.destroy()
34+
.then( () => {
35+
editor.element.remove();
36+
} );
37+
} );
38+
window.editors = [];
39+
counter = 1;
40+
}
41+
42+
document.getElementById( 'initEditor' ).addEventListener( 'click', initEditor );
43+
document.getElementById( 'destroyEditors' ).addEventListener( 'click', destroyEditors );

‎tests/manual/inlineeditor-data.md

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
1. Click "Init editor".
2+
2. New editor instance should be appended to the document with initial data in it. You can create more than one editor.
3+
3. After clicking "Destroy editor" all editors should be removed from the document.

0 commit comments

Comments
 (0)
This repository has been archived.