8
0

editor.js 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  1. /**
  2. * @license Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
  3. * For licensing, see LICENSE.md.
  4. */
  5. 'use strict';
  6. /**
  7. * Represents a single editor instance.
  8. *
  9. * @class Editor
  10. * @extends Model
  11. */
  12. CKEDITOR.define( [
  13. 'model',
  14. 'editorconfig',
  15. 'plugincollection',
  16. 'creator',
  17. 'ckeditorerror',
  18. 'utils'
  19. ], ( Model, EditorConfig, PluginCollection, Creator, CKEditorError, utils ) => {
  20. class Editor extends Model {
  21. /**
  22. * Creates a new instance of the Editor class.
  23. *
  24. * This constructor should be rarely used. When creating new editor instance use instead the
  25. * {@link CKEDITOR#create CKEDITOR.create() method}.
  26. *
  27. * @param {HTMLElement} element The DOM element that will be the source for the created editor.
  28. * @constructor
  29. */
  30. constructor( element, config ) {
  31. super();
  32. /**
  33. * The original host page element upon which the editor is created. It is only supposed to be provided on
  34. * editor creation and is not subject to be modified.
  35. *
  36. * @readonly
  37. * @property {HTMLElement}
  38. */
  39. this.element = element;
  40. /**
  41. * Holds all configurations specific to this editor instance.
  42. *
  43. * This instance of the {@link Config} class is customized so its {@link Config#get} method will retrieve
  44. * global configurations available in {@link CKEDITOR.config} if configurations are not found in the
  45. * instance itself.
  46. *
  47. * @readonly
  48. * @property {Config}
  49. */
  50. this.config = new EditorConfig( config );
  51. /**
  52. * The plugins loaded and in use by this editor instance.
  53. *
  54. * @readonly
  55. * @property {PluginCollection}
  56. */
  57. this.plugins = new PluginCollection( this );
  58. /**
  59. * The chosen creator.
  60. *
  61. * @property {Creator} _creator
  62. * @protected
  63. */
  64. /**
  65. * The list of detected creators.
  66. *
  67. * @property {Map}
  68. * @protected
  69. */
  70. this._creators = new Map();
  71. }
  72. /**
  73. * Initializes the editor instance object after its creation.
  74. *
  75. * The initialization consists of the following procedures:
  76. *
  77. * * Load and initialize the configured plugins.
  78. * * Fires the editor creator.
  79. *
  80. * This method should be rarely used as `CKEDITOR.create` calls it one should never use the `Editor` constructor
  81. * directly.
  82. *
  83. * @returns {Promise} A promise which resolves once the initialization is completed.
  84. */
  85. init() {
  86. const that = this;
  87. const config = this.config;
  88. return loadPlugins()
  89. .then( initPlugins )
  90. .then( findCreators )
  91. .then( fireCreator );
  92. function loadPlugins() {
  93. return that.plugins.load( config.plugins );
  94. }
  95. function initPlugins( loadedPlugins ) {
  96. // Start with a resolved promise.
  97. let promise = Promise.resolve();
  98. // Chain it with promises that resolve with the init() call of every plugin.
  99. for ( let i = 0; i < loadedPlugins.length; i++ ) {
  100. promise = promise.then( () => loadedPlugins[ i ].init() );
  101. }
  102. // Return the promise chain.
  103. return promise;
  104. }
  105. function findCreators() {
  106. for ( let plugin of that.plugins ) {
  107. if ( plugin instanceof Creator ) {
  108. that._creators.set( plugin.name, plugin );
  109. }
  110. }
  111. }
  112. function fireCreator() {
  113. // Take the name of the creator to use (config or any of the registered ones).
  114. const creatorName = config.creator && ( 'creator-' + config.creator );
  115. let creator;
  116. if ( creatorName ) {
  117. // Take the registered class for the given creator name.
  118. creator = that._creators.get( creatorName );
  119. } else if ( that._creators.size > 1 ) {
  120. /**
  121. * The `config.creator` option was not defined.
  122. *
  123. * This error is thrown when more than one creator is available and the configuration does
  124. * not specify which one to use.
  125. *
  126. * @error editor-undefined-creator
  127. */
  128. throw new CKEditorError( 'editor-undefined-creator: The config.creator option was not defined.' );
  129. } else {
  130. creator = utils.nth( 0, that._creators.values() );
  131. }
  132. if ( !creator ) {
  133. /**
  134. * The creator has not been found.
  135. *
  136. * * If `creatorName` is defined it means that `config.creator` was configured, but such
  137. * plugin does not exist or it does not implement a creator.
  138. * * If `creatorName` is undefined it means that `config.creator` was not configured and
  139. * that none of the loaded plugins implement a creator.
  140. *
  141. * @error editor-creator-404
  142. * @param {String} creatorName
  143. */
  144. throw new CKEditorError(
  145. 'editor-creator-404: The creator has not been found.',
  146. { creatorName: creatorName }
  147. );
  148. }
  149. that._creator = creator;
  150. // Finally fire the creator. It may be asynchronous, returning a promise.
  151. return creator.create();
  152. }
  153. }
  154. /**
  155. * Destroys the editor instance, releasing all resources used by it. If the editor replaced an element, the
  156. * element will be recovered.
  157. *
  158. * @fires destroy
  159. * @returns {Promise} A promise that resolves once the editor instance is fully destroyed.
  160. */
  161. destroy() {
  162. const that = this;
  163. this.fire( 'destroy' );
  164. delete this.element;
  165. return Promise.resolve().then( () => {
  166. return that._creator && that._creator.destroy();
  167. } );
  168. }
  169. }
  170. return Editor;
  171. } );
  172. /**
  173. * Fired when this editor instance is destroyed. The editor at this point is not usable and this event should be used to
  174. * perform the clean-up in any plugin.
  175. *
  176. * @event destroy
  177. */