8
0

controller.js 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  1. /**
  2. * @license Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
  3. * For licensing, see LICENSE.md.
  4. */
  5. 'use strict';
  6. CKEDITOR.define( [
  7. 'collection',
  8. 'model',
  9. 'ckeditorerror',
  10. ], function( Collection, Model, CKEditorError ) {
  11. class Controller extends Model {
  12. /**
  13. * Creates an instance of the {@link Controller} class.
  14. *
  15. * @param {Model} [model] Model of this Controller.
  16. * @param {View} [view] View instance of this Controller.
  17. * @constructor
  18. */
  19. constructor( model, view ) {
  20. super();
  21. /**
  22. * Model of this controller.
  23. *
  24. * @property {Model}
  25. */
  26. this.model = model || null;
  27. /**
  28. * Set `true` after {@link #init}.
  29. *
  30. * @property {Boolean}
  31. */
  32. this.ready = false;
  33. /**
  34. * View of this controller.
  35. *
  36. * @property {View}
  37. */
  38. this.view = view || null;
  39. /**
  40. * A collection of {@link ControllerCollection} instances containing
  41. * child controllers.
  42. *
  43. * @property {Collection}
  44. */
  45. this.collections = new Collection( {
  46. idProperty: 'name'
  47. } );
  48. // Listen to {@link ControllerCollection#add} and {@link ControllerCollection#remove}
  49. // of newly added Collection to synchronize this controller's view and children
  50. // controllers' views in the future.
  51. this.collections.on( 'add', ( evt, collection ) => {
  52. // Set the {@link ControllerCollection#parent} to this controller.
  53. // It allows the collection to determine the {@link #ready} state of this controller
  54. // and accordingly initialize a child controller when added.
  55. collection.parent = this;
  56. this.listenTo( collection, 'add', ( evt, childController, index ) => {
  57. // Child view is added to corresponding region in this controller's view
  58. // when a new Controller joins the collection.
  59. if ( this.ready && childController.view ) {
  60. this.view.addChild( collection.name, childController.view, index );
  61. }
  62. } );
  63. this.listenTo( collection, 'remove', ( evt, childController ) => {
  64. // Child view is removed from corresponding region in this controller's view
  65. // when a new Controller is removed from the the collection.
  66. if ( this.ready && childController.view ) {
  67. this.view.removeChild( collection.name, childController.view );
  68. }
  69. } );
  70. } );
  71. this.collections.on( 'remove', ( evt, collection ) => {
  72. // Release the collection. Once removed from {@link #collections}, it can be
  73. // moved to another controller.
  74. collection.parent = null;
  75. this.stopListening( collection );
  76. } );
  77. }
  78. /**
  79. * Initializes the controller instance. The process includes:
  80. *
  81. * 1. Initialization of the child {@link #view}.
  82. * 2. Initialization of child controllers in {@link #collections}.
  83. * 3. Setting {@link #ready} flag `true`.
  84. *
  85. * @returns {Promise} A Promise resolved when the initialization process is finished.
  86. */
  87. init() {
  88. if ( this.ready ) {
  89. /**
  90. * This Controller already been initialized.
  91. *
  92. * @error ui-controller-init-reinit
  93. */
  94. throw new CKEditorError( 'ui-controller-init-reinit: This Controller already been initialized.' );
  95. }
  96. return Promise.resolve()
  97. .then( this._initView.bind( this ) )
  98. .then( this._initCollections.bind( this ) )
  99. .then( () => {
  100. this.ready = true;
  101. } );
  102. }
  103. /**
  104. * Destroys the controller instance. The process includes:
  105. *
  106. * 1. Destruction of the child {@link #view}.
  107. * 2. Destruction of child controllers in {@link #collections}.
  108. *
  109. * @returns {Promise} A Promise resolved when the destruction process is finished.
  110. */
  111. destroy() {
  112. let promises = [];
  113. let collection, childController;
  114. for ( collection of this.collections ) {
  115. for ( childController of collection ) {
  116. promises.push( childController.destroy() );
  117. collection.remove( childController );
  118. }
  119. this.collections.remove( collection );
  120. }
  121. if ( this.view ) {
  122. promises.push( Promise.resolve().then( () => {
  123. return this.view.destroy();
  124. } ) );
  125. }
  126. promises.push( Promise.resolve().then( () => {
  127. this.model = this.ready = this.view = this.collections = null;
  128. } ) );
  129. return Promise.all( promises );
  130. }
  131. /**
  132. * Initializes the {@link #view} of this controller instance.
  133. *
  134. * @protected
  135. * @returns {Promise} A Promise resolved when initialization process is finished.
  136. */
  137. _initView() {
  138. let promise = Promise.resolve();
  139. if ( this.view ) {
  140. promise = promise.then( this.view.init.bind( this.view ) );
  141. }
  142. return promise;
  143. }
  144. /**
  145. * Initializes the {@link #collections} of this controller instance.
  146. *
  147. * @protected
  148. * @returns {Promise} A Promise resolved when initialization process is finished.
  149. */
  150. _initCollections() {
  151. const promises = [];
  152. let collection, childController;
  153. for ( collection of this.collections ) {
  154. for ( childController of collection ) {
  155. if ( this.view && childController.view ) {
  156. this.view.addChild( collection.name, childController.view );
  157. }
  158. promises.push( childController.init() );
  159. }
  160. }
  161. return Promise.all( promises );
  162. }
  163. }
  164. return Controller;
  165. } );