Procházet zdrojové kódy

Added basic tests and documentation.

Piotrek Koszuliński před 9 roky
rodič
revize
f36f6755d1

+ 73 - 20
packages/ckeditor5-editor-classic/src/classic.js

@@ -16,13 +16,13 @@ import EditableUI from '../ui/editableui/editableui.js';
 import InlineEditableUIView from '../ui/editableui/inline/inlineeditableuiview.js';
 
 import Model from '../ui/model.js';
-import StickyToolbar from '../ui/bindings/stickytoolbar.js';
+import Toolbar from '../ui/bindings/toolbar.js';
 import StickyToolbarView from '../ui/stickytoolbar/stickytoolbarview.js';
 
 import ElementReplacer from '../utils/elementreplacer.js';
 
 /**
- * Classic editor creator using inline editable and sticky toolbar, all
+ * Classic editor. Uses inline editable and sticky toolbar, all
  * enclosed in a boxed UI.
  *
  * @memberOf editor-classic
@@ -30,9 +30,11 @@ import ElementReplacer from '../utils/elementreplacer.js';
  */
 export default class ClassicEditor extends StandardEditor {
 	/**
-	 * Creates an instance of the classic creator.
+	 * Creates an instance of the classic editor.
 	 *
-	 * @param {ckeditor5.Editor} The editor instance.
+	 * @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 {Object} config The editor config.
 	 */
 	constructor( element, config ) {
 		super( element, config );
@@ -43,12 +45,19 @@ export default class ClassicEditor extends StandardEditor {
 
 		this.data.processor = new HtmlDataProcessor();
 
+		/**
+		 * The element replacer instance used to hide editor element.
+		 *
+		 * @private
+		 * @member {utils.ElementReplacer} editor-classic.Classic#_elementReplacer
+		 */
 		this._elementReplacer = new ElementReplacer();
 	}
 
 	/**
-	 * Updates the original editor element with data and destroys
-	 * the UI.
+	 * Destroys the editor instance, releasing all resources used by it.
+	 *
+	 * Updates the original editor element with the data.
 	 *
 	 * @returns {Promise}
 	 */
@@ -60,6 +69,46 @@ export default class ClassicEditor extends StandardEditor {
 			.then( () => super.destroy() );
 	}
 
+	/**
+	 * Creates a classic editor instance.
+	 *
+	 *		ClassicEditor.create( document.querySelector( '#editor' ), {
+	 *			features: [ 'delete', 'enter', 'typing', 'paragraph', 'undo', 'basic-styles/bold', 'basic-styles/italic' ],
+	 *			toolbar: [ 'bold', 'italic', 'undo', 'redo' ]
+	 *		} )
+	 *		.then( editor => {
+	 *			console.log( 'Editor was initialized', editor );
+	 *		} )
+	 *		.catch( err => {
+	 *			console.error( err.stack );
+	 *		} );
+	 *
+	 * @param {HTMLElement} element See {@link ckeditor5.editor.ClassicEditor#constructor}'s param.
+	 * @param {Object} config See {@link ckeditor5.editor.ClassicEditor#constructor}'s param.
+	 * @returns {Promise} Promise resolved once editor is ready.
+	 * @returns {ckeditor5.editor.StandardEditor} return.editor The editor instance.
+	 */
+	static create( element, config ) {
+		return new Promise( ( resolve ) => {
+			const editor = new ClassicEditor( element, config );
+
+			resolve(
+				editor._createUI()
+					.then( () => editor.initPlugins() )
+					.then( () => editor._initUI() )
+					.then( () => editor.loadDataFromEditorElement() )
+					.then( () => editor )
+			);
+		} );
+	}
+
+	/**
+	 * Creates editor UI (the {@link ui.editorUI.BoxedEditorUI boxed version} of it) with a sticky toolbar and an
+	 * inline editable.
+	 *
+	 * @protected
+	 * @returns {Promise}
+	 */
 	_createUI() {
 		const editorUI = new BoxedEditorUI( this );
 		const editorUIView = new BoxedEditorUIView( editorUI.viewModel, this.locale );
@@ -76,39 +125,43 @@ export default class ClassicEditor extends StandardEditor {
 		return Promise.resolve();
 	}
 
+	/**
+	 * Initializes editor UI. The UI has to be {@link #_createUI created} beforehand.
+	 *
+	 * @protected
+	 * @returns {Promise}
+	 */
 	_initUI() {
-		this._toolbar.addButtons( this.config.toolbar );
+		if ( this.config.toolbar ) {
+			this._toolbar.addButtons( this.config.toolbar );
+		}
 
 		return this.ui.init()
 			.then( () => this.editing.view.attachDomRoot( this._editableUI.view.element ) );
 	}
 
-	static create( element, config ) {
-		const editor = new ClassicEditor( element, config );
-
-		return editor._createUI()
-			.then( () => editor.initPlugins() )
-			.then( () => editor._initUI() )
-			.then( () => editor.loadDataFromEditorElement() )
-			.then( () => editor );
-	}
-
 	/**
-	 * Creates editor sticky toolbar and fills it with children using the configuration.
+	 * Creates editor sticky toolbar.
 	 *
 	 * @protected
 	 */
 	_createToolbar() {
-		// Note: StickyToolbar and StickyToolbarView share the same model. It may change in the future.
 		const toolbarModel = new Model();
 		const toolbarView = new StickyToolbarView( toolbarModel, this.locale );
-		const toolbar = new StickyToolbar( toolbarModel, toolbarView, this );
+		const toolbar = new Toolbar( toolbarModel, toolbarView, this );
+
+		toolbarModel.bind( 'isActive' ).to( this.editing.view.getRoot(), 'isFocused' );
 
 		this.ui.add( 'top', toolbar );
 
 		this._toolbar = toolbar;
 	}
 
+	/**
+	 * Creates editor main editable.
+	 *
+	 * @protected
+	 */
 	_createEditableUI() {
 		const editable = this.editing.view.getRoot();
 		const editableUI = new EditableUI( this, editable );

packages/ckeditor5-editor-classic/tests/classiccreator.html → packages/ckeditor5-editor-classic/tests/classic.html


+ 101 - 0
packages/ckeditor5-editor-classic/tests/classic.js

@@ -0,0 +1,101 @@
+/**
+ * @license Copyright (c) 2003-2016, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md.
+ */
+
+/* bender-tags: editor, browser-only */
+
+'use strict';
+
+import BoxedEditorUI from '/ckeditor5/ui/editorui/boxed/boxededitorui.js';
+import BoxedEditorUIView from '/ckeditor5/ui/editorui/boxed/boxededitoruiview.js';
+
+// import EditableUI from '/ckeditor5/ui/editableui/editableui.js';
+// import InlineEditableUIView from '/ckeditor5/ui/editableui/inline/inlineeditableuiview.js';
+
+// import StickyToolbarView from '/ckeditor5/ui/stickytoolbar/stickytoolbarview.js';
+
+import HtmlDataProcessor from '/ckeditor5/engine/dataprocessor/htmldataprocessor.js';
+
+import ClassicEditor from '/ckeditor5/creator-classic/classic.js';
+
+import testUtils from '/tests/ckeditor5/_utils/utils.js';
+import count from '/ckeditor5/utils/count.js';
+
+testUtils.createSinonSandbox();
+
+describe( 'ClassicEditor', () => {
+	let editor, editorElement;
+
+	beforeEach( () => {
+		editorElement = document.createElement( 'div' );
+		editorElement.innerHTML = '<p><strong>foo</strong> bar</p>';
+
+		document.body.appendChild( editorElement );
+	} );
+
+	afterEach( () => {
+		editorElement.remove();
+	} );
+
+	describe( 'create', () => {
+		beforeEach( function() {
+			return ClassicEditor.create( editorElement, {
+					features: [ 'paragraph', 'basic-styles/bold', 'basic-styles/italic' ],
+					toolbar: [ 'bold', 'italic' ]
+				} )
+				.then( newEditor => {
+					editor = newEditor;
+				} );
+		} );
+
+		it( 'create an instance which inherits from the ClassicEditor', () => {
+			expect( editor ).to.be.instanceof( ClassicEditor );
+		} );
+
+		it( 'creates a single div editable root in the view', () => {
+			expect( editor.editing.view.domRoots.size ).to.equal( 1 );
+			expect( editor.editing.view.getRoot() ).to.have.property( 'name', 'div' );
+		} );
+
+		it( 'creates a single document root', () => {
+			expect( count( editor.document.rootNames ) ).to.equal( 1 );
+			expect( editor.document.getRoot() ).to.have.property( 'name', '$root' );
+		} );
+
+		it( 'creates the UI using BoxedEditorUI classes', () => {
+			expect( editor.ui ).to.be.instanceof( BoxedEditorUI );
+			expect( editor.ui.view ).to.be.instanceof( BoxedEditorUIView );
+		} );
+
+		it( 'inserts editor UI next to editor element', () => {
+			expect( editor.ui.view.element.previousSibling ).to.equal( editorElement );
+		} );
+
+		it( 'uses HTMLDataProcessor', () => {
+			expect( editor.data.processor ).to.be.instanceof( HtmlDataProcessor );
+		} );
+
+		it( 'loads data from the editor element', () => {
+			expect( editor.getData() ).to.equal( '<p><strong>foo</strong> bar</p>' );
+		} );
+	} );
+
+	describe( 'destroy', () => {
+		beforeEach( function() {
+			return ClassicEditor.create( editorElement, { features: [ 'paragraph' ] } )
+				.then( newEditor => {
+					editor = newEditor;
+				} );
+		} );
+
+		it( 'sets the data back to the editor element', () => {
+			editor.setData( '<p>foo</p>' );
+
+			return editor.destroy()
+				.then( () => {
+					expect( editorElement.innerHTML ).to.equal( '<p>foo</p>' );
+				} );
+		} );
+	} );
+} );

+ 0 - 185
packages/ckeditor5-editor-classic/tests/classiccreator.js

@@ -1,185 +0,0 @@
-/**
- * @license Copyright (c) 2003-2016, CKSource - Frederico Knabben. All rights reserved.
- * For licensing, see LICENSE.md.
- */
-
-/* bender-tags: creator */
-
-'use strict';
-
-import Editor from '/ckeditor5/editor.js';
-
-import BoxedEditorUI from '/ckeditor5/ui/editorui/boxed/boxededitorui.js';
-import BoxedEditorUIView from '/ckeditor5/ui/editorui/boxed/boxededitoruiview.js';
-
-import EditableUI from '/ckeditor5/ui/editableui/editableui.js';
-import InlineEditableUIView from '/ckeditor5/ui/editableui/inline/inlineeditableuiview.js';
-
-import StickyToolbar from '/ckeditor5/ui/bindings/stickytoolbar.js';
-import StickyToolbarView from '/ckeditor5/ui/stickytoolbar/stickytoolbarview.js';
-
-import StandardCreator from '/ckeditor5/creator/standardcreator.js';
-import ClassicCreator from '/ckeditor5/creator-classic/classiccreator.js';
-import HtmlDataProcessor from '/ckeditor5/engine/dataprocessor/htmldataprocessor.js';
-
-import testUtils from '/tests/ckeditor5/_utils/utils.js';
-
-testUtils.createSinonSandbox();
-
-describe( 'ClassicCreator', () => {
-	let creator, editor, fooElement, barElement;
-
-	beforeEach( function() {
-		fooElement = document.createElement( 'div' );
-		fooElement.setAttribute( 'class', 'first' );
-		fooElement.setAttribute( 'data-test', this.currentTest.title );
-
-		document.body.appendChild( fooElement );
-
-		barElement = document.createElement( 'div' );
-		barElement.setAttribute( 'class', 'second' );
-		barElement.setAttribute( 'data-test', this.currentTest.title );
-
-		document.body.appendChild( barElement );
-
-		editor = new Editor(
-			{
-				foo: fooElement,
-				bar: barElement
-			},
-			{
-				toolbar: [ 'bold', 'italic' ]
-			}
-		);
-
-		creator = new ClassicCreator( editor, new HtmlDataProcessor() );
-	} );
-
-	describe( 'constructor', () => {
-		it( 'inherits from the StandardCreator', () => {
-			expect( creator ).to.be.instanceof( StandardCreator );
-		} );
-
-		it( 'creates a single instance of Editable ', () => {
-			expect( editor.editables ).to.have.length( 1 );
-			expect( editor.editables.get( 0 ).name ).to.equal( 'foo' );
-		} );
-
-		it( 'creates the UI using BoxedEditorUI classes', () => {
-			expect( editor.ui ).to.be.instanceof( BoxedEditorUI );
-			expect( editor.ui.view ).to.be.instanceof( BoxedEditorUIView );
-		} );
-
-		it( 'creates a single document root', () => {
-			expect( editor.document.rootNames ).to.have.members( [ 'foo' ] );
-		} );
-	} );
-
-	describe( 'create', () => {
-		it( 'returns a promise', () => {
-			expect( creator.create() ).to.be.instanceof( Promise );
-		} );
-
-		it( 'calls _replaceElement', () => {
-			const spy = testUtils.sinon.spy( creator, '_replaceElement' );
-
-			return creator.create().then( () => {
-				expect( spy.calledOnce ).to.be.true;
-			} );
-		} );
-
-		it( 'calls _createToolbar', () => {
-			const spy = testUtils.sinon.spy( creator, '_createToolbar' );
-
-			return creator.create().then( () => {
-				expect( spy.calledOnce ).to.be.true;
-			} );
-		} );
-
-		it( 'creates the editable using EditableUI Controller in main region', () => {
-			return creator.create().then( () => {
-				expect( editor.ui.collections.get( 'main' ) ).to.have.length( 1 );
-				expect( editor.ui.collections.get( 'main' ).get( 0 ) ).to.be.instanceof( EditableUI );
-			} );
-		} );
-
-		it( 'creates the editable using InlineEditableUIView in main region', () => {
-			return creator.create().then( () => {
-				expect( editor.ui.collections.get( 'main' ).get( 0 ).view ).to.be.instanceof( InlineEditableUIView );
-			} );
-		} );
-
-		it( 'binds the editable to InlineEditableUIView', () => {
-			return creator.create().then( () => {
-				const editableUIView = editor.ui.collections.get( 'main' ).get( 0 ).view;
-
-				expect( editor.editables.get( 0 ).domElement ).to.equal( editableUIView.element );
-			} );
-		} );
-
-		it( 'initializes the editor.ui', () => {
-			const spy = testUtils.sinon.spy( editor.ui, 'init' );
-
-			return creator.create().then( () => {
-				expect( spy.calledOnce ).to.be.true;
-			} );
-		} );
-
-		it( 'calls loadDataFromEditorElement', () => {
-			const spy = testUtils.sinon.spy( creator, 'loadDataFromEditorElement' );
-
-			return creator.create().then( () => {
-				expect( spy.calledOnce ).to.be.true;
-			} );
-		} );
-	} );
-
-	describe( 'destroy', () => {
-		it( 'returns a promise', () => {
-			return creator.create().then( () => {
-				expect( creator.destroy() ).to.be.instanceof( Promise );
-			} );
-		} );
-
-		it( 'destroys parent class', () => {
-			const spy = testUtils.sinon.spy( StandardCreator.prototype, 'destroy' );
-
-			return creator.create().then( () => {
-				return creator.destroy().then( () => {
-					expect( spy.calledOnce ).to.be.true;
-				} );
-			} );
-		} );
-
-		it( 'calls updateEditorElement', () => {
-			const spy = testUtils.sinon.spy( creator, 'updateEditorElement' );
-
-			return creator.create().then( () => {
-				return creator.destroy().then( () => {
-					expect( spy.calledOnce ).to.be.true;
-				} );
-			} );
-		} );
-
-		it( 'destroys the UI', () => {
-			return creator.create().then( () => {
-				return creator.destroy().then( () => {
-					expect( editor.ui.collections ).to.be.null;
-				} );
-			} );
-		} );
-	} );
-
-	describe( '_createToolbar', () => {
-		it( 'creates toolbar using StickyToolbar and StickyToolbarView', () => {
-			return creator.create().then( () => {
-				expect( editor.ui.collections.get( 'top' ) ).to.have.length( 1 );
-
-				const toolbar = editor.ui.collections.get( 'top' ).get( 0 );
-
-				expect( toolbar ).to.be.instanceof( StickyToolbar );
-				expect( toolbar.view ).to.be.instanceof( StickyToolbarView );
-			} );
-		} );
-	} );
-} );

+ 4 - 1
packages/ckeditor5-editor-classic/tests/manual/classic.js

@@ -17,7 +17,7 @@ function initEditor() {
 		features: [ 'delete', 'enter', 'typing', 'paragraph', 'undo', 'basic-styles/bold', 'basic-styles/italic' ],
 		toolbar: [ 'bold', 'italic', 'undo', 'redo' ]
 	} )
-	.then( ( newEditor ) => {
+	.then( newEditor => {
 		console.log( 'Editor was initialized', newEditor );
 		console.log( 'You can now play with it using global `editor` and `editable` variables.' );
 
@@ -26,6 +26,9 @@ function initEditor() {
 
 		observer = testUtils.createObserver();
 		observer.observe( 'Editable', editable, [ 'isFocused' ] );
+	} )
+	.catch( err => {
+		console.error( err.stack );
 	} );
 }