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

Commit 5a2031e

Browse files
author
Piotr Jasiun
authored
Merge pull request #114 from ckeditor/t/110
Fix: Moved EditingController, DataController and EditingKeystrokeHandler from StandardEditor to Editor class. Closes #110.
2 parents 7798bc3 + 0ae4e11 commit 5a2031e

File tree

10 files changed

+90
-138
lines changed

10 files changed

+90
-138
lines changed

src/editor/editor.js

Lines changed: 32 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -8,17 +8,21 @@
88
*/
99

1010
import Config from '@ckeditor/ckeditor5-utils/src/config';
11+
import EditingController from '@ckeditor/ckeditor5-engine/src/controller/editingcontroller';
1112
import PluginCollection from '../plugincollection';
1213
import CommandCollection from '../commandcollection';
1314
import Locale from '@ckeditor/ckeditor5-utils/src/locale';
1415
import DataController from '@ckeditor/ckeditor5-engine/src/controller/datacontroller';
1516
import Model from '@ckeditor/ckeditor5-engine/src/model/model';
17+
import EditingKeystrokeHandler from '../editingkeystrokehandler';
1618

1719
import ObservableMixin from '@ckeditor/ckeditor5-utils/src/observablemixin';
1820
import mix from '@ckeditor/ckeditor5-utils/src/mix';
1921

2022
/**
21-
* Class representing a basic editor. It contains a base architecture, without much additional logic.
23+
* Class representing the base of the editor. It is the API all plugins can expect to get when using editor property.
24+
* Editors implementation (like Classic Editor or Inline Editor) should extend this class. They can add their own
25+
* methods and properties.
2226
*
2327
* See also {@link module:core/editor/standardeditor~StandardEditor}.
2428
*
@@ -73,53 +77,57 @@ export default class Editor {
7377
*/
7478
this.t = this.locale.t;
7579

80+
/**
81+
* Defines whether this editor is in read-only mode.
82+
*
83+
* In read-only mode the editor {@link #commands commands} are disabled so it is not possible
84+
* to modify document using them.
85+
*
86+
* @observable
87+
* @member {Boolean} #isReadOnly
88+
*/
89+
this.set( 'isReadOnly', false );
90+
7691
/**
7792
* The editor's model.
7893
*
7994
* The center of the editor's abstract data model.
8095
*
81-
* Besides the model, the editor usually contains two controllers –
82-
* {@link #data data controller} and {@link #editing editing controller}.
83-
* The former is used e.g. when setting or retrieving editor data and contains a useful
84-
* set of methods for operating on the content. The latter controls user input and rendering
85-
* the content for editing.
86-
*
8796
* @readonly
8897
* @member {module:engine/model/model~Model}
8998
*/
9099
this.model = new Model();
91100

101+
// Creates main root.
102+
this.model.document.createRoot();
103+
92104
/**
93105
* The {@link module:engine/controller/datacontroller~DataController data controller}.
106+
* Used e.g. for setting or retrieving editor data.
94107
*
95108
* @readonly
96109
* @member {module:engine/controller/datacontroller~DataController}
97110
*/
98111
this.data = new DataController( this.model );
99112

100113
/**
101-
* Defines whether this editor is in read-only mode.
102-
*
103-
* In read-only mode the editor {@link #commands commands} are disabled so it is not possible
104-
* to modify document using them.
114+
* The {@link module:engine/controller/editingcontroller~EditingController editing controller}.
115+
* Controls user input and rendering the content for editing.
105116
*
106-
* @observable
107-
* @member {Boolean} #isReadOnly
117+
* @readonly
118+
* @member {module:engine/controller/editingcontroller~EditingController}
108119
*/
109-
this.set( 'isReadOnly', false );
120+
this.editing = new EditingController( this.model );
121+
this.editing.view.bind( 'isReadOnly' ).to( this );
110122

111123
/**
112-
* The {@link module:engine/controller/editingcontroller~EditingController editing controller}.
113-
*
114-
* This property is set by more specialized editor classes (such as {@link module:core/editor/standardeditor~StandardEditor}),
115-
* however, it's required for features to work as their engine-related parts will try to connect converters.
116-
*
117-
* When defining a virtual editor class, like one working in Node.js, it's possible to plug a virtual
118-
* editing controller which only instantiates necessary properties, but without any observers and listeners.
124+
* Instance of the {@link module:core/editingkeystrokehandler~EditingKeystrokeHandler}.
119125
*
120126
* @readonly
121-
* @member {module:engine/controller/editingcontroller~EditingController} #editing
127+
* @member {module:core/editingkeystrokehandler~EditingKeystrokeHandler}
122128
*/
129+
this.keystrokes = new EditingKeystrokeHandler( this );
130+
this.keystrokes.listenTo( this.editing.view );
123131
}
124132

125133
/**
@@ -173,6 +181,8 @@ export default class Editor {
173181
.then( () => {
174182
this.model.destroy();
175183
this.data.destroy();
184+
this.editing.destroy();
185+
this.keystrokes.destroy();
176186
} );
177187
}
178188

src/editor/standardeditor.js

Lines changed: 4 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -8,16 +8,16 @@
88
*/
99

1010
import Editor from './editor';
11-
import EditingKeystrokeHandler from '../editingkeystrokehandler';
12-
import EditingController from '@ckeditor/ckeditor5-engine/src/controller/editingcontroller';
1311
import isFunction from '@ckeditor/ckeditor5-utils/src/lib/lodash/isFunction';
1412

1513
import getDataFromElement from '@ckeditor/ckeditor5-utils/src/dom/getdatafromelement';
1614
import setDataInElement from '@ckeditor/ckeditor5-utils/src/dom/setdatainelement';
1715

1816
/**
19-
* Class representing a typical browser-based editor. It handles a single source element and
20-
* uses {@link module:engine/controller/editingcontroller~EditingController}.
17+
* The standard editor class, extending base editor by adding methods needed in the typical
18+
* editor implementations: editor with a single editable area created based on the DOM element.
19+
* It provides base API to manage data and to integrate the editor with the form when it is
20+
* initialized on the textarea element.
2121
*
2222
* @extends module:core/editor/editor~Editor
2323
*/
@@ -40,18 +40,6 @@ export default class StandardEditor extends Editor {
4040
*/
4141
this.element = element;
4242

43-
// Documented in Editor.
44-
this.editing = new EditingController( this.model );
45-
this.editing.view.bind( 'isReadOnly' ).to( this );
46-
47-
/**
48-
* Instance of the {@link module:core/editingkeystrokehandler~EditingKeystrokeHandler}.
49-
*
50-
* @readonly
51-
* @member {module:core/editingkeystrokehandler~EditingKeystrokeHandler}
52-
*/
53-
this.keystrokes = new EditingKeystrokeHandler( this );
54-
5543
/**
5644
* Editor UI instance.
5745
*
@@ -63,21 +51,9 @@ export default class StandardEditor extends Editor {
6351
* @member {module:core/editor/editorui~EditorUI} #ui
6452
*/
6553

66-
this.keystrokes.listenTo( this.editing.view );
67-
6854
this._attachToForm();
6955
}
7056

71-
/**
72-
* @inheritDoc
73-
*/
74-
destroy() {
75-
return Promise.resolve()
76-
.then( () => this.keystrokes.destroy() )
77-
.then( () => this.editing.destroy() )
78-
.then( super.destroy() );
79-
}
80-
8157
/**
8258
* Sets the data in the editor's main root.
8359
*

tests/_utils-tests/classictesteditor.js

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -37,13 +37,6 @@ describe( 'ClassicTestEditor', () => {
3737
expect( editor.element ).to.equal( editorElement );
3838
expect( editor.ui ).to.be.instanceOf( ClassicTestEditorUI );
3939
expect( editor.ui.view ).to.be.instanceOf( BoxedEditorUIView );
40-
} );
41-
42-
it( 'creates model and view roots', () => {
43-
const editor = new ClassicTestEditor( editorElement );
44-
45-
expect( editor.model.document.getRoot() ).to.have.property( 'name', '$root' );
46-
expect( editor.editing.view.getRoot() ).to.have.property( 'name', 'div' );
4740
expect( editor.data.processor ).to.be.instanceof( HtmlDataProcessor );
4841
} );
4942

tests/_utils-tests/modeltesteditor.js

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,15 +21,22 @@ describe( 'ModelTestEditor', () => {
2121
const editor = new ModelTestEditor( { foo: 1 } );
2222

2323
expect( editor ).to.be.instanceof( Editor );
24-
2524
expect( editor.config.get( 'foo' ) ).to.equal( 1 );
25+
expect( editor.data.processor ).to.be.instanceof( HtmlDataProcessor );
2626
} );
2727

28-
it( 'creates model and view roots', () => {
28+
it( 'creates model root', () => {
2929
const editor = new ModelTestEditor( { foo: 1 } );
3030

3131
expect( editor.model.document.getRoot() ).to.have.property( 'name', '$root' );
32-
expect( editor.data.processor ).to.be.instanceof( HtmlDataProcessor );
32+
} );
33+
34+
it( 'should disable editing pipeline and clear main root', () => {
35+
const editor = new ModelTestEditor( { foo: 1 } );
36+
37+
editor.model.document.createRoot( 'second', 'second' );
38+
39+
expect( Array.from( editor.editing.view.roots ) ).to.length( 0 );
3340
} );
3441
} );
3542

tests/_utils-tests/virtualtesteditor.js

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -19,16 +19,8 @@ describe( 'VirtualTestEditor', () => {
1919
const editor = new VirtualTestEditor( { foo: 1 } );
2020

2121
expect( editor ).to.be.instanceof( StandardEditor );
22-
23-
expect( editor.config.get( 'foo' ) ).to.equal( 1 );
24-
} );
25-
26-
it( 'creates model and view roots', () => {
27-
const editor = new VirtualTestEditor( { foo: 1 } );
28-
29-
expect( editor.model.document.getRoot() ).to.have.property( 'name', '$root' );
30-
expect( editor.editing.view.getRoot() ).to.have.property( 'name', 'div' );
3122
expect( editor.data.processor ).to.be.instanceof( HtmlDataProcessor );
23+
expect( editor.config.get( 'foo' ) ).to.equal( 1 );
3224
} );
3325
} );
3426

tests/_utils/classictesteditor.js

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,6 @@ export default class ClassicTestEditor extends StandardEditor {
2323
constructor( element, config ) {
2424
super( element, config );
2525

26-
this.model.document.createRoot();
27-
this.editing.createRoot( 'div' );
2826
this.data.processor = new HtmlDataProcessor();
2927

3028
this.ui = new ClassicTestEditorUI( this, new BoxedEditorUIView( this.locale ) );

tests/_utils/modeltesteditor.js

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,11 @@ export default class ModelTestEditor extends Editor {
1818
constructor( config ) {
1919
super( config );
2020

21-
this.model.document.createRoot();
22-
2321
this.data.processor = new HtmlDataProcessor();
22+
23+
// Disable editing pipeline for model editor.
24+
this.editing.destroy();
25+
this.editing.view.roots.clear();
2426
}
2527

2628
/**

tests/_utils/virtualtesteditor.js

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,6 @@ export default class VirtualTestEditor extends StandardEditor {
1818
constructor( config ) {
1919
super( null, config );
2020

21-
this.model.document.createRoot();
22-
23-
this.editing.createRoot( 'div' );
24-
2521
this.data.processor = new HtmlDataProcessor();
2622
}
2723

tests/editor/editor.js

Lines changed: 39 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,13 @@
88
import Editor from '../../src/editor/editor';
99
import Plugin from '../../src/plugin';
1010
import Config from '@ckeditor/ckeditor5-utils/src/config';
11+
import EditingController from '@ckeditor/ckeditor5-engine/src/controller/editingcontroller';
1112
import PluginCollection from '../../src/plugincollection';
1213
import CommandCollection from '../../src/commandcollection';
1314
import CKEditorError from '@ckeditor/ckeditor5-utils/src/ckeditorerror';
1415
import Locale from '@ckeditor/ckeditor5-utils/src/locale';
1516
import Command from '../../src/command';
17+
import EditingKeystrokeHandler from '../../src/editingkeystrokehandler';
1618

1719
class PluginA extends Plugin {
1820
constructor( editor ) {
@@ -103,6 +105,8 @@ describe( 'Editor', () => {
103105

104106
expect( editor.config ).to.be.an.instanceof( Config );
105107
expect( editor.commands ).to.be.an.instanceof( CommandCollection );
108+
expect( editor.editing ).to.be.instanceof( EditingController );
109+
expect( editor.keystrokes ).to.be.instanceof( EditingKeystrokeHandler );
106110

107111
expect( editor.plugins ).to.be.an.instanceof( PluginCollection );
108112
expect( getPlugins( editor ) ).to.be.empty;
@@ -133,6 +137,31 @@ describe( 'Editor', () => {
133137

134138
expect( editor.config.get( 'bar' ) ).to.equal( 'foo' );
135139
} );
140+
141+
it( 'should bind editing.view#isReadOnly to the editor', () => {
142+
const editor = new Editor();
143+
144+
editor.isReadOnly = false;
145+
146+
expect( editor.editing.view.isReadOnly ).to.false;
147+
148+
editor.isReadOnly = true;
149+
150+
expect( editor.editing.view.isReadOnly ).to.true;
151+
} );
152+
153+
it( 'should create main root element', () => {
154+
const editor = new Editor();
155+
156+
expect( editor.model.document.getRoot( 'main' ) ).to.ok;
157+
} );
158+
159+
it( 'should activate #keystrokes', () => {
160+
const spy = sinon.spy( EditingKeystrokeHandler.prototype, 'listenTo' );
161+
const editor = new Editor();
162+
163+
sinon.assert.calledWith( spy, editor.editing.view );
164+
} );
136165
} );
137166

138167
describe( 'plugins', () => {
@@ -192,15 +221,19 @@ describe( 'Editor', () => {
192221
it( 'should destroy all components it initialized', () => {
193222
const editor = new Editor();
194223

195-
const spy1 = sinon.spy( editor.data, 'destroy' );
196-
const spy2 = sinon.spy( editor.model, 'destroy' );
197-
const spy3 = sinon.spy( editor.plugins, 'destroy' );
224+
const dataDestroySpy = sinon.spy( editor.data, 'destroy' );
225+
const modelDestroySpy = sinon.spy( editor.model, 'destroy' );
226+
const editingDestroySpy = sinon.spy( editor.editing, 'destroy' );
227+
const pluginsDestroySpy = sinon.spy( editor.plugins, 'destroy' );
228+
const keystrokesDestroySpy = sinon.spy( editor.keystrokes, 'destroy' );
198229

199230
return editor.destroy()
200231
.then( () => {
201-
expect( spy1.calledOnce ).to.be.true;
202-
expect( spy2.calledOnce ).to.be.true;
203-
expect( spy3.calledOnce ).to.be.true;
232+
sinon.assert.calledOnce( dataDestroySpy );
233+
sinon.assert.calledOnce( modelDestroySpy );
234+
sinon.assert.calledOnce( editingDestroySpy );
235+
sinon.assert.calledOnce( pluginsDestroySpy );
236+
sinon.assert.calledOnce( keystrokesDestroySpy );
204237
} );
205238
} );
206239
} );

0 commit comments

Comments
 (0)