editor.js 4.8 KB

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