8
0
Pārlūkot izejas kodu

Merge pull request #15 from cksource/t/9

t/9: Introduced the Editor class, CKEDITOR.create and CKEDITOR.instances.
Piotrek Reinmar Koszuliński 10 gadi atpakaļ
vecāks
revīzija
0cec8a5e0c

+ 53 - 1
packages/ckeditor5-engine/src/ckeditor.js

@@ -3,6 +3,8 @@
  * For licensing, see LICENSE.md.
  */
 
+/* globals document */
+
 'use strict';
 
 /**
@@ -12,8 +14,58 @@
  * @singleton
  */
 
-CKEDITOR.define( function() {
+CKEDITOR.define( [ 'editor', 'mvc/collection', 'promise' ], function( Editor, Collection, Promise ) {
 	var CKEDITOR = {
+		/**
+		 * A collection containing all editor instances created.
+		 *
+		 * @readonly
+		 * @property {Collection}
+		 */
+		instances: new Collection(),
+
+		/**
+		 * Creates an editor instance for the provided DOM element.
+		 *
+		 * The creation of editor instances is an asynchronous operation, therefore a promise is returned by this
+		 * method.
+		 *
+		 *		CKEDITOR.create( '#content' );
+		 *
+		 *		CKEDITOR.create( '#content' ).then( function( editor ) {
+		 *			// Manipulate "editor" here.
+		 *		} );
+		 *
+		 * @param {String|HTMLElement} element An element selector or a DOM element, which will be the source for the
+		 * created instance.
+		 * @returns {Promise} A promise, which will be fulfilled with the created editor.
+		 */
+		create: function( element ) {
+			var that = this;
+
+			return new Promise( function( resolve, reject ) {
+				// If a query selector has been passed, transform it into a real element.
+				if ( typeof element == 'string' ) {
+					element = document.querySelector( element );
+
+					if ( !element ) {
+						reject( new Error( 'Element not found' ) );
+					}
+				}
+
+				var editor = new Editor( element );
+
+				that.instances.add( editor );
+
+				// Remove the editor from `instances` when destroyed.
+				editor.once( 'destroy', function() {
+					that.instances.remove( editor );
+				} );
+
+				resolve( editor );
+			} );
+		},
+
 		/**
 		 * Gets the full URL path for the specified plugin.
 		 *

+ 57 - 0
packages/ckeditor5-engine/src/editor.js

@@ -0,0 +1,57 @@
+/**
+ * @license Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md.
+ */
+
+'use strict';
+
+/**
+ * Represents a single editor instance.
+ *
+ * @class Editor
+ */
+
+CKEDITOR.define( [ 'ckeditor', 'mvc/model', 'utils' ], function( CKEDITOR, Model ) {
+	var Editor = Model.extend( {
+		/**
+		 * Creates a new instance of the Editor class.
+		 *
+		 * This constructor should be rarely used. When creating new editor instance use instead the
+		 * {@link CKEDITOR#create CKEDITOR.create() method}.
+		 *
+		 * @param {HTMLElement} element The DOM element that will be the source for the created editor.
+		 * @constructor
+		 */
+		constructor: function Editor( element ) {
+			/**
+			 * The original host page element upon which the editor is created. It is only supposed to be provided on
+			 * editor creation and is not subject to be modified.
+			 *
+			 * @readonly
+			 * @property {HTMLElement}
+			 */
+			this.element = element;
+		},
+
+		/**
+		 * Destroys the editor instance, releasing all resources used by it. If the editor replaced an element, the
+		 * element will be recovered.
+		 *
+		 * @fires destroy
+		 */
+		destroy: function() {
+			this.fire( 'destroy' );
+
+			delete this.element;
+		}
+	} );
+
+	return Editor;
+} );
+
+/**
+ * Fired when this editor instance is destroyed. The editor at this point is not usable and this event should be used to
+ * perform the clean-up in any plugin.
+ *
+ * @event destroy
+ */

+ 2 - 0
packages/ckeditor5-engine/tests/ckeditor/ckeditor.html

@@ -0,0 +1,2 @@
+<div id="content"></div>
+<div class="editor"></div>

+ 97 - 0
packages/ckeditor5-engine/tests/ckeditor/ckeditor.js

@@ -0,0 +1,97 @@
+/**
+ * @license Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md.
+ */
+
+/* globals describe, it, expect, beforeEach, document */
+
+'use strict';
+
+var modules = bender.amd.require( 'ckeditor', 'editor', 'promise' );
+
+var content = document.getElementById( 'content' );
+
+beforeEach( function() {
+	var CKEDITOR = modules.ckeditor;
+
+	// Destroy all editor instances.
+	while ( CKEDITOR.instances.length ) {
+		CKEDITOR.instances.get( 0 ).destroy();
+	}
+} );
+
+describe( 'create', function() {
+	it( 'should return a promise', function() {
+		var CKEDITOR = modules.ckeditor;
+		var Promise = modules.promise;
+
+		expect( CKEDITOR.create( content ) ).to.be.instanceof( Promise );
+	} );
+
+	it( 'should create a new editor instance', function() {
+		var CKEDITOR = modules.ckeditor;
+		var Editor = modules.editor;
+
+		return CKEDITOR.create( content ).then( function( editor ) {
+			expect( editor ).to.be.instanceof( Editor );
+			expect( editor.element ).to.equal( content );
+		} );
+	} );
+
+	it( 'should create a new editor instance (using a selector)', function() {
+		var CKEDITOR = modules.ckeditor;
+		var Editor = modules.editor;
+
+		return CKEDITOR.create( '.editor' ).then( function( editor ) {
+			expect( editor ).to.be.instanceof( Editor );
+			expect( editor.element ).to.equal( document.querySelector( '.editor' ) );
+		} );
+	} );
+
+	it( 'should add the editor to the `instances` collection', function() {
+		var CKEDITOR = modules.ckeditor;
+
+		return CKEDITOR.create( content ).then( function( editor ) {
+			expect( CKEDITOR.instances ).to.have.length( 1 );
+			expect( CKEDITOR.instances.get( 0 ) ).to.equal( editor );
+		} );
+	} );
+
+	it( 'should remove the editor from the `instances` collection on `destroy` event', function() {
+		var CKEDITOR = modules.ckeditor;
+		var editor1, editor2;
+
+		// Create the first editor.
+		return CKEDITOR.create( content ).then( function( editor ) {
+			editor1 = editor;
+
+			// Create the second editor.
+			return CKEDITOR.create( '.editor' ).then( function( editor ) {
+				editor2 = editor;
+
+				// It should have 2 editors.
+				expect( CKEDITOR.instances ).to.have.length( 2 );
+
+				// Destroy one of them.
+				editor1.destroy();
+
+				// It should have 1 editor now.
+				expect( CKEDITOR.instances ).to.have.length( 1 );
+
+				// Ensure that the remaining is the right one.
+				expect( CKEDITOR.instances.get( 0 ) ).to.equal( editor2 );
+			} );
+		} );
+	} );
+
+	it( 'should be rejected on element not found', function() {
+		var CKEDITOR = modules.ckeditor;
+
+		return CKEDITOR.create( '.undefined' ).then( function() {
+			throw new Error( 'It should not enter this function' );
+		} ).catch( function( error ) {
+			expect( error ).to.be.instanceof( Error );
+			expect( error.message ).to.equal( 'Element not found' );
+		} );
+	} );
+} );

+ 46 - 0
packages/ckeditor5-engine/tests/editor/editor.js

@@ -0,0 +1,46 @@
+/**
+ * @license Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md.
+ */
+
+/* globals describe, it, expect, beforeEach, sinon, document */
+
+'use strict';
+
+var modules = bender.amd.require( 'editor' );
+
+var editor;
+var element;
+
+beforeEach( function() {
+	var Editor = modules.editor;
+
+	element = document.createElement( 'div' );
+	document.body.appendChild( element );
+
+	editor = new Editor( element );
+} );
+
+describe( 'constructor', function() {
+	it( 'should create a new editor instance', function() {
+		expect( editor ).to.have.property( 'element' ).to.equal( element );
+	} );
+} );
+
+describe( 'destroy', function() {
+	it( 'should fire "destroy"', function() {
+		var spy = sinon.spy();
+
+		editor.on( 'destroy', spy );
+
+		editor.destroy();
+
+		sinon.assert.called( spy );
+	} );
+
+	it( 'should delete the "element" property', function() {
+		editor.destroy();
+
+		expect( editor ).to.not.have.property( 'element' );
+	} );
+} );