|
|
@@ -1,351 +0,0 @@
|
|
|
-/**
|
|
|
- * @license Copyright (c) 2003-2016, CKSource - Frederico Knabben. All rights reserved.
|
|
|
- * For licensing, see LICENSE.md.
|
|
|
- */
|
|
|
-
|
|
|
-'use strict';
|
|
|
-
|
|
|
-import ObservableMixin from './utils/observablemixin.js';
|
|
|
-import Config from './utils/config.js';
|
|
|
-import PluginCollection from './plugincollection.js';
|
|
|
-import EditableCollection from './editablecollection.js';
|
|
|
-import CKEditorError from './utils/ckeditorerror.js';
|
|
|
-import Locale from './utils/locale.js';
|
|
|
-import isArray from './utils/lib/lodash/isArray.js';
|
|
|
-import nth from './utils/nth.js';
|
|
|
-import mix from './utils/mix.js';
|
|
|
-
|
|
|
-/**
|
|
|
- * Represents a single editor instance.
|
|
|
- *
|
|
|
- * @memberOf ckeditor5
|
|
|
- * @mixes utils.ObservaleMixin
|
|
|
- */
|
|
|
-export default class Editor {
|
|
|
- /**
|
|
|
- * 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 {Object.<String, HTMLElement>|null} [elements] The DOM elements that will be the source
|
|
|
- * for the created editor.
|
|
|
- * @param {Object} config The editor config.
|
|
|
- */
|
|
|
- constructor( elements, config ) {
|
|
|
- /**
|
|
|
- * The original host page elements upon which the editor is created.
|
|
|
- *
|
|
|
- * @readonly
|
|
|
- * @member {Map.<String, HTMLElement>|null} ckeditor5.Editor#elements
|
|
|
- */
|
|
|
- if ( elements ) {
|
|
|
- this.elements = new Map();
|
|
|
-
|
|
|
- for ( let name in elements ) {
|
|
|
- this.elements.set( name, elements[ name ] );
|
|
|
- }
|
|
|
- } else {
|
|
|
- this.elements = null;
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * Holds all configurations specific to this editor instance.
|
|
|
- *
|
|
|
- * @readonly
|
|
|
- * @member {utils.Config} ckeditor5.Editor#config
|
|
|
- */
|
|
|
- this.config = config = new Config( config );
|
|
|
-
|
|
|
- /**
|
|
|
- * The plugins loaded and in use by this editor instance.
|
|
|
- *
|
|
|
- * @readonly
|
|
|
- * @member {ckeditor5.PluginCollection} ckeditor5.Editor#plugins
|
|
|
- */
|
|
|
- this.plugins = new PluginCollection( this );
|
|
|
-
|
|
|
- /**
|
|
|
- * The editables of the editor.
|
|
|
- *
|
|
|
- * @readonly
|
|
|
- * @member {ckeditor5.EditableCollection} ckeditor5.Editor#editables
|
|
|
- */
|
|
|
- this.editables = new EditableCollection();
|
|
|
-
|
|
|
- /**
|
|
|
- * Commands registered to the editor.
|
|
|
- *
|
|
|
- * @readonly
|
|
|
- * @member {Map.<ckeditor5.command.Command>} ckeditor5.Editor#commands
|
|
|
- */
|
|
|
- this.commands = new Map();
|
|
|
-
|
|
|
- /**
|
|
|
- * @readonly
|
|
|
- * @member {utils.Locale} ckeditor5.Editor#locale
|
|
|
- */
|
|
|
- this.locale = new Locale( config.lang );
|
|
|
-
|
|
|
- /**
|
|
|
- * Shorthand for {@link utils.Locale#t}.
|
|
|
- *
|
|
|
- * @see utils.Locale#t
|
|
|
- * @method ckeditor5.Editor#t
|
|
|
- */
|
|
|
- this.t = this.locale.t;
|
|
|
-
|
|
|
- /**
|
|
|
- * Tree Model document managed by this editor.
|
|
|
- *
|
|
|
- * This property is set by the {@link ckeditor5.creator.Creator}.
|
|
|
- *
|
|
|
- * @readonly
|
|
|
- * @member {engine.model.Document} ckeditor5.Editor#document
|
|
|
- */
|
|
|
-
|
|
|
- /**
|
|
|
- * Instance of the {@link engine.EditingController editing controller}.
|
|
|
- *
|
|
|
- * This property is set by the {@link ckeditor5.creator.Creator}.
|
|
|
- *
|
|
|
- * @readonly
|
|
|
- * @member {engine.EditingController} ckeditor5.Editor#editing
|
|
|
- */
|
|
|
-
|
|
|
- /**
|
|
|
- * Instance of the {@link engine.DataController data controller}.
|
|
|
- *
|
|
|
- * This property is set by the {@link ckeditor5.creator.Creator}.
|
|
|
- *
|
|
|
- * @readonly
|
|
|
- * @member {engine.DataController} ckeditor5.Editor#data
|
|
|
- */
|
|
|
-
|
|
|
- /**
|
|
|
- * Instance of the {@link ckeditor5.KeystrokeHandler}.
|
|
|
- *
|
|
|
- * This property is set by the {@link ckeditor5.creator.Creator}.
|
|
|
- *
|
|
|
- * @readonly
|
|
|
- * @member {engine.treecontroller.DataController} ckeditor5.Editor#keystrokes
|
|
|
- */
|
|
|
-
|
|
|
- /**
|
|
|
- * The chosen creator.
|
|
|
- *
|
|
|
- * @protected
|
|
|
- * @member {ckeditor5.creator.Creator} ckeditor5.Editor#_creator
|
|
|
- */
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * First element from {@link ckeditor5.Editor#elements}.
|
|
|
- *
|
|
|
- * @readonly
|
|
|
- * @type {HTMLElement|null}
|
|
|
- */
|
|
|
- get firstElement() {
|
|
|
- if ( !this.elements ) {
|
|
|
- return null;
|
|
|
- }
|
|
|
-
|
|
|
- return nth( 0, this.elements )[ 1 ];
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * Name of the first element from {@link ckeditor5.Editor#elements}.
|
|
|
- *
|
|
|
- * @readonly
|
|
|
- * @type {String|null}
|
|
|
- */
|
|
|
- get firstElementName() {
|
|
|
- if ( !this.elements ) {
|
|
|
- return null;
|
|
|
- }
|
|
|
-
|
|
|
- return nth( 0, this.elements )[ 0 ];
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * Initializes the editor instance object after its creation.
|
|
|
- *
|
|
|
- * The initialization consists of the following procedures:
|
|
|
- *
|
|
|
- * * Loading and initializing the configured features and creator.
|
|
|
- * * Firing the editor creator.
|
|
|
- *
|
|
|
- * This method should be rarely used as {@link CKEDITOR#create} calls it one should never use the `Editor`
|
|
|
- * constructor directly.
|
|
|
- *
|
|
|
- * @returns {Promise} A promise which resolves once the initialization is completed.
|
|
|
- */
|
|
|
- init() {
|
|
|
- const that = this;
|
|
|
- const config = this.config;
|
|
|
- let creatorName = config.creator;
|
|
|
-
|
|
|
- if ( !creatorName ) {
|
|
|
- /**
|
|
|
- * The `config.creator` option was not defined.
|
|
|
- *
|
|
|
- * @error editor-undefined-creator
|
|
|
- */
|
|
|
- return Promise.reject(
|
|
|
- new CKEditorError( 'editor-undefined-creator: The config.creator option was not defined.' )
|
|
|
- );
|
|
|
- }
|
|
|
-
|
|
|
- return loadPlugins()
|
|
|
- .then( initPlugins )
|
|
|
- .then( fireCreator );
|
|
|
-
|
|
|
- function loadPlugins() {
|
|
|
- let plugins = config.features || [];
|
|
|
-
|
|
|
- // Handle features passed as a string.
|
|
|
- if ( !isArray( plugins ) ) {
|
|
|
- plugins = plugins.split( ',' );
|
|
|
- }
|
|
|
-
|
|
|
- plugins.push( creatorName );
|
|
|
-
|
|
|
- return that.plugins.load( plugins );
|
|
|
- }
|
|
|
-
|
|
|
- function initPlugins( loadedPlugins ) {
|
|
|
- return loadedPlugins.reduce( ( promise, plugin ) => {
|
|
|
- return promise.then( plugin.init.bind( plugin ) );
|
|
|
- }, Promise.resolve() );
|
|
|
- }
|
|
|
-
|
|
|
- function fireCreator() {
|
|
|
- // We can always get the creator by its name because config.creator (which is requried) is passed
|
|
|
- // to PluginCollection.load().
|
|
|
- that._creator = that.plugins.get( creatorName );
|
|
|
-
|
|
|
- // Finally fire the creator. It may be asynchronous, returning a promise.
|
|
|
- return that._creator.create();
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * Destroys the editor instance, releasing all resources used by it. If the editor replaced an element, the
|
|
|
- * element will be recovered.
|
|
|
- *
|
|
|
- * @fires ckeditor5.Editor#destroy
|
|
|
- * @returns {Promise} A promise that resolves once the editor instance is fully destroyed.
|
|
|
- */
|
|
|
- destroy() {
|
|
|
- this.fire( 'destroy' );
|
|
|
- this.stopListening();
|
|
|
-
|
|
|
- // Note: The destruction order should be the reverse of the initialization order.
|
|
|
- return Promise.resolve()
|
|
|
- .then( () => {
|
|
|
- return this._creator && this._creator.destroy();
|
|
|
- } )
|
|
|
- .then( () => this.editables.destroy() );
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * Sets the data in the specified editor's editable root.
|
|
|
- *
|
|
|
- * @param {*} data The data to load.
|
|
|
- * @param {String} [editableRootName] The name of the editable root to which the data should be loaded.
|
|
|
- * If not specified and if there's only one editable root added to the editor, then the data will be loaded
|
|
|
- * to that editable.
|
|
|
- */
|
|
|
- setData( data, editableRootName ) {
|
|
|
- if ( !this.data ) {
|
|
|
- /**
|
|
|
- * Data controller has not been defined yet, so methds like {@link ckeditor5.Editor#setData} and
|
|
|
- * {@link ckeditor5.Editor#getData} cannot be used.
|
|
|
- *
|
|
|
- * @error editor-no-datacontroller
|
|
|
- */
|
|
|
- throw new CKEditorError( 'editor-no-datacontroller: Data controller has not been defined yet.' );
|
|
|
- }
|
|
|
-
|
|
|
- this.data.set( data, editableRootName || this._getDefaultRootName() );
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * Gets the data from the specified editor's editable root.
|
|
|
- *
|
|
|
- * @param {String} [editableRootName] The name of the editable root to get the data from.
|
|
|
- * If not specified and if there's only one editable root added to the editor, then the data will be retrieved
|
|
|
- * from it.
|
|
|
- */
|
|
|
- getData( editableRootName ) {
|
|
|
- if ( !this.data ) {
|
|
|
- throw new CKEditorError( 'editor-no-datacontroller: Data controller has not been defined yet.' );
|
|
|
- }
|
|
|
-
|
|
|
- return this.data.get( editableRootName || this._getDefaultRootName() );
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * Executes specified command with given parameter.
|
|
|
- *
|
|
|
- * @param {String} commandName Name of command to execute.
|
|
|
- * @param {*} [commandParam] If set, command will be executed with this parameter.
|
|
|
- */
|
|
|
- execute( commandName, commandParam ) {
|
|
|
- let command = this.commands.get( commandName );
|
|
|
-
|
|
|
- if ( !command ) {
|
|
|
- /**
|
|
|
- * Specified command has not been added to the editor.
|
|
|
- *
|
|
|
- * @error editor-command-not-found
|
|
|
- */
|
|
|
- throw new CKEditorError( 'editor-command-not-found: Specified command has not been added to the editor.' );
|
|
|
- }
|
|
|
-
|
|
|
- command._execute( commandParam );
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * Returns name of the editable root if there is only one. If there are multiple or no editable roots, throws an error.
|
|
|
- *
|
|
|
- * Note: The error message makes sense only for methods like {@link ckeditor5.Editor#setData} and
|
|
|
- * {@link ckeditor5.Editor#getData}.
|
|
|
- *
|
|
|
- * @private
|
|
|
- * @returns {String}
|
|
|
- */
|
|
|
- _getDefaultRootName() {
|
|
|
- const rootNames = Array.from( this.document.rootNames );
|
|
|
-
|
|
|
- if ( rootNames.length > 1 ) {
|
|
|
- /**
|
|
|
- * The name of the editable root must be specified. There are multiple editable roots added to the editor,
|
|
|
- * so the name of the editable must be specified.
|
|
|
- *
|
|
|
- * @error editor-editable-root-name-missing
|
|
|
- */
|
|
|
- throw new CKEditorError( 'editor-editable-root-name-missing: The name of the editable root must be specified.' );
|
|
|
- }
|
|
|
-
|
|
|
- if ( rootNames.length === 0 ) {
|
|
|
- /**
|
|
|
- * The editor does not contain any editable roots, so the data cannot be set or read from it.
|
|
|
- *
|
|
|
- * @error editor-no-editable-roots
|
|
|
- */
|
|
|
- throw new CKEditorError( 'editor-no-editable-roots: There are no editable roots defined.' );
|
|
|
- }
|
|
|
-
|
|
|
- return rootNames[ 0 ];
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-mix( Editor, ObservableMixin );
|
|
|
-
|
|
|
-/**
|
|
|
- * 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 ckeditor5.Editor#destroy
|
|
|
- */
|