| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282 |
- /**
- * @license Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
- * For licensing, see LICENSE.md.
- */
- 'use strict';
- CKEDITOR.define( [
- 'collection',
- 'model',
- 'ckeditorerror',
- ], function( Collection, Model, CKEditorError ) {
- class Controller extends Model {
- /**
- * @constructor
- */
- constructor( model, view ) {
- super();
- /**
- * Model of this controller.
- *
- * @property {Model}
- */
- this.model = model;
- /**
- * View of this controller.
- *
- * @property {View}
- */
- this.view = view;
- /**
- * Set `true` after {@link #init}.
- *
- * @property {Boolean}
- */
- this.ready = false;
- /**
- * Collections of child controllers.
- *
- * @private
- * @property {Collection}
- */
- this._collections = new Collection( {
- idProperty: 'name'
- } );
- }
- /**
- * Initializes the controller instance. The process includes:
- * * initialization of the child {@link #view}.
- * * initialization of child controllers in {@link #_collections}.
- * * setting {@link #ready} flag `true`.
- *
- * @returns {Promise} A Promise resolved when the initialization process is finished.
- */
- init() {
- if ( this.ready ) {
- throw new CKEditorError( 'ui-controller-init-reinit: This Controller already been initialized.' );
- }
- return Promise.resolve()
- .then( this._initView.bind( this ) )
- .then( this._initCollections.bind( this ) )
- .then( () => {
- this.ready = true;
- } );
- }
- /**
- * Initializes the {@link #view} of this controller instance.
- *
- * @protected
- * @returns {Promise} A Promise resolved when initialization process is finished.
- */
- _initView() {
- let promise = Promise.resolve();
- if ( this.view ) {
- promise = promise.then( this.view.init.bind( this.view ) );
- }
- return promise;
- }
- /**
- * Initializes the {@link #_collections} of this controller instance.
- *
- * @protected
- * @returns {Promise} A Promise resolved when initialization process is finished.
- */
- _initCollections() {
- const promises = [];
- let collection, childController;
- for ( collection of this._collections ) {
- for ( childController of collection ) {
- if ( this.view, childController.view ) {
- this.view.addChild( collection.name, childController.view );
- }
- promises.push( childController.init() );
- }
- }
- return Promise.all( promises );
- }
- /**
- * Adds a child controller to one of the {@link #_collections}.
- * If this controller instance is ready, the child view will be initialized when added.
- * If this controller and child controller have views, the child view will be added
- * to corresponding region in this controller's view.
- *
- * @param {String} collectionName One of {@link _collections} the child should be added to.
- * @param {Controller} childController A child controller.
- * @param {Number} [index] Index at which the child will be added to the collection.
- * @returns {Promise} A Promise resolved when the child is added.
- */
- addChild( collectionName, childController, index ) {
- if ( !collectionName ) {
- throw new CKEditorError( 'ui-controller-addchild-badcname' );
- }
- const collection = this._collections.get( collectionName );
- if ( !collection ) {
- throw new CKEditorError( 'ui-controller-addchild-nocol' );
- }
- if ( !childController || !( childController instanceof Controller ) ) {
- throw new CKEditorError( 'ui-controller-addchild-badtype' );
- }
- // ChildController.init() returns Promise.
- let promise = Promise.resolve();
- collection.add( childController, index );
- if ( this.ready ) {
- if ( childController.view ) {
- this.view.addChild( collectionName, childController.view, index );
- }
- if ( !childController.ready ) {
- promise = promise.then( () => {
- return childController.init();
- } );
- }
- }
- return promise;
- }
- /**
- * Removes a child controller from one of the {@link #_collections}.
- * If this controller and child controller have views, the child view will be removed
- * from corresponding region in this controller's view.
- *
- * @param {String} collectionName One of {@link _collections} the child should be removed from.
- * @param {Controller} childController A child controller.
- * @returns {Controller} A child controller instance after removal.
- */
- removeChild( collectionName, childController ) {
- if ( !collectionName ) {
- throw new CKEditorError( 'ui-controller-removechild-badcname' );
- }
- const collection = this._collections.get( collectionName );
- if ( !collection ) {
- throw new CKEditorError( 'ui-controller-removechild-nocol' );
- }
- if ( !childController || !( childController instanceof Controller ) ) {
- throw new CKEditorError( 'ui-controller-removechild-badtype' );
- }
- collection.remove( childController );
- if ( this.ready && childController.view ) {
- this.view.removeChild( collectionName, childController.view );
- }
- return childController;
- }
- /**
- * Returns a child controller from one of the {@link #_collections} at given `index`.
- *
- * @param {String} collectionName One of {@link _collections} the child should be retrieved from.
- * @param {Number} [index] An index of desired controller.
- * @returns {Controller} A child controller instance.
- */
- getChild( collectionName, index ) {
- const collection = this._collections.get( collectionName );
- if ( !collection ) {
- throw new CKEditorError( 'ui-controller-getchild-nocol' );
- }
- return collection.get( index );
- }
- /**
- * Registers a collection in {@link #_collections}.
- *
- * @param {String} collectionName The name of the collection to be registered.
- * @param {Collection} collection Collection to be registered.
- * @param {Boolean} [override] When set `true` it will allow overriding of registered collections.
- */
- register( collectionName, collection, override ) {
- const registered = this._collections.get( collectionName );
- const that = this;
- if ( !( collection instanceof Collection ) ) {
- throw new CKEditorError( 'ui-controller-register-badtype' );
- }
- if ( !registered ) {
- add( collection );
- } else {
- if ( registered !== collection ) {
- if ( !override ) {
- throw new CKEditorError( 'ui-controller-register-noverride' );
- }
- that._collections.remove( registered );
- add( collection );
- }
- }
- function add() {
- collection.name = collectionName;
- that._collections.add( collection );
- }
- }
- /**
- * Destroys the controller instance. The process includes:
- * * destruction of the child {@link #view}.
- * * destruction of child controllers in {@link #_collections}.
- *
- * @returns {Promise} A Promise resolved when the destruction process is finished.
- */
- destroy() {
- let promises = [];
- let collection, childController;
- for ( collection of this._collections ) {
- for ( childController of collection ) {
- if ( this.view && childController.view ) {
- this.view.removeChild( collection.name, childController.view );
- }
- promises.push( childController.destroy() );
- collection.remove( childController );
- }
- this._collections.remove( collection );
- }
- if ( this.view ) {
- promises.push( Promise.resolve().then( () => {
- return this.view.destroy();
- } ) );
- }
- promises.push( Promise.resolve().then( () => {
- this.model = this.view = this._collections = null;
- } ) );
- return Promise.all( promises );
- }
- }
- return Controller;
- } );
|