editor.js 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. /**
  2. * @license Copyright (c) 2003-2016, CKSource - Frederico Knabben. All rights reserved.
  3. * For licensing, see LICENSE.md.
  4. */
  5. 'use strict';
  6. import ObservableMixin from './observablemixin.js';
  7. import EditorConfig from './editorconfig.js';
  8. import PluginCollection from './plugincollection.js';
  9. import CKEditorError from './ckeditorerror.js';
  10. import isArray from './lib/lodash/isArray.js';
  11. import utils from './utils.js';
  12. /**
  13. * Represents a single editor instance.
  14. *
  15. * @memberOf core
  16. * @mixes core.ObservableMixin
  17. */
  18. export default class Editor {
  19. /**
  20. * Creates a new instance of the Editor class.
  21. *
  22. * This constructor should be rarely used. When creating new editor instance use instead the
  23. * {@link CKEDITOR#create CKEDITOR.create() method}.
  24. *
  25. * @param {HTMLElement} element The DOM element that will be the source for the created editor.
  26. */
  27. constructor( element, config ) {
  28. /**
  29. * The original host page element upon which the editor is created. It is only supposed to be provided on
  30. * editor creation and is not subject to be modified.
  31. *
  32. * @readonly
  33. * @type {HTMLElement}
  34. */
  35. this.element = element;
  36. /**
  37. * Holds all configurations specific to this editor instance.
  38. *
  39. * This instance of the {@link Config} class is customized so its {@link Config#get} method will retrieve
  40. * global configurations available in {@link CKEDITOR.config} if configurations are not found in the
  41. * instance itself.
  42. *
  43. * @readonly
  44. * @type {Config}
  45. */
  46. this.config = new EditorConfig( config );
  47. /**
  48. * The plugins loaded and in use by this editor instance.
  49. *
  50. * @readonly
  51. * @type {PluginCollection}
  52. */
  53. this.plugins = new PluginCollection( this );
  54. /**
  55. * The chosen creator.
  56. *
  57. * @protected
  58. * @type {Creator}
  59. */
  60. }
  61. /**
  62. * Initializes the editor instance object after its creation.
  63. *
  64. * The initialization consists of the following procedures:
  65. *
  66. * * Loading and initializing the configured features and creator.
  67. * * Firing the editor creator.
  68. *
  69. * This method should be rarely used as {@link CKEDITOR#create} calls it one should never use the `Editor`
  70. * constructor directly.
  71. *
  72. * @returns {Promise} A promise which resolves once the initialization is completed.
  73. */
  74. init() {
  75. const that = this;
  76. const config = this.config;
  77. let creatorName = config.creator;
  78. if ( !creatorName ) {
  79. /**
  80. * The `config.creator` option was not defined.
  81. *
  82. * @error editor-undefined-creator
  83. */
  84. return Promise.reject(
  85. new CKEditorError( 'editor-undefined-creator: The config.creator option was not defined.' )
  86. );
  87. }
  88. return loadPlugins()
  89. .then( initPlugins )
  90. .then( fireCreator );
  91. function loadPlugins() {
  92. let plugins = config.features || [];
  93. // Handle features passed as a string.
  94. if ( !isArray( plugins ) ) {
  95. plugins = plugins.split( ',' );
  96. }
  97. plugins.push( creatorName );
  98. return that.plugins.load( plugins );
  99. }
  100. function initPlugins( loadedPlugins ) {
  101. return loadedPlugins.reduce( ( promise, plugin ) => {
  102. return promise.then( plugin.init.bind( plugin ) );
  103. }, Promise.resolve() );
  104. }
  105. function fireCreator() {
  106. // We can always get the creator by its name because config.creator (which is requried) is passed
  107. // to PluginCollection.load().
  108. that._creator = that.plugins.get( creatorName );
  109. // Finally fire the creator. It may be asynchronous, returning a promise.
  110. return that._creator.create();
  111. }
  112. }
  113. /**
  114. * Destroys the editor instance, releasing all resources used by it. If the editor replaced an element, the
  115. * element will be recovered.
  116. *
  117. * @fires {@link core.Editor.destroy destroy}
  118. * @returns {Promise} A promise that resolves once the editor instance is fully destroyed.
  119. */
  120. destroy() {
  121. const that = this;
  122. this.fire( 'destroy' );
  123. this.stopListening();
  124. return Promise.resolve()
  125. .then( () => {
  126. return that._creator && that._creator.destroy();
  127. } )
  128. .then( () => {
  129. delete this.element;
  130. } );
  131. }
  132. setData( data ) {
  133. this.editable.setData( data );
  134. }
  135. getData() {
  136. return this.editable.getData();
  137. }
  138. }
  139. utils.mix( Editor, ObservableMixin );
  140. /**
  141. * Fired when this editor instance is destroyed. The editor at this point is not usable and this event should be used to
  142. * perform the clean-up in any plugin.
  143. *
  144. * @memberOf core.Editor
  145. * @event destroy
  146. */
  147. /**
  148. * @cfg {String[]} features
  149. */
  150. /**
  151. * @cfg {String} creator
  152. */