|
@@ -16,11 +16,12 @@
|
|
|
CKEDITOR.define( [
|
|
CKEDITOR.define( [
|
|
|
'collection',
|
|
'collection',
|
|
|
'model',
|
|
'model',
|
|
|
|
|
+ 'ui/region',
|
|
|
'ui/template',
|
|
'ui/template',
|
|
|
'ckeditorerror',
|
|
'ckeditorerror',
|
|
|
'ui/domemittermixin',
|
|
'ui/domemittermixin',
|
|
|
'utils'
|
|
'utils'
|
|
|
-], ( Collection, Model, Template, CKEditorError, DOMEmitterMixin, utils ) => {
|
|
|
|
|
|
|
+], ( Collection, Model, Region, Template, CKEditorError, DOMEmitterMixin, utils ) => {
|
|
|
class View extends Model {
|
|
class View extends Model {
|
|
|
/**
|
|
/**
|
|
|
* Creates an instance of the {@link View} class.
|
|
* Creates an instance of the {@link View} class.
|
|
@@ -33,135 +34,364 @@ CKEDITOR.define( [
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
|
* Model of this view.
|
|
* Model of this view.
|
|
|
|
|
+ *
|
|
|
|
|
+ * @property {Model}
|
|
|
|
|
+ */
|
|
|
|
|
+ this.model = model || null;
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * Regions of this view. See {@link #register}.
|
|
|
|
|
+ *
|
|
|
|
|
+ * @property {Collection}
|
|
|
*/
|
|
*/
|
|
|
- this.model = new Model( model );
|
|
|
|
|
|
|
+ this.regions = new Collection( {
|
|
|
|
|
+ idProperty: 'name'
|
|
|
|
|
+ } );
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
|
- * Regions which belong to this view.
|
|
|
|
|
|
|
+ * Template of this view.
|
|
|
|
|
+ *
|
|
|
|
|
+ * @property {Object}
|
|
|
*/
|
|
*/
|
|
|
- this.regions = new Collection( null, 'name' );
|
|
|
|
|
|
|
+ this.template = null;
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
|
- * @property {HTMLElement} _el
|
|
|
|
|
|
|
+ * Region selectors of this view. See {@link #register}.
|
|
|
|
|
+ *
|
|
|
|
|
+ * @private
|
|
|
|
|
+ * @property {Object}
|
|
|
*/
|
|
*/
|
|
|
|
|
+ this._regionsSelectors = {};
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
|
- * @property {Template} _template
|
|
|
|
|
|
|
+ * Element of this view.
|
|
|
|
|
+ *
|
|
|
|
|
+ * @private
|
|
|
|
|
+ * @property {HTMLElement}
|
|
|
*/
|
|
*/
|
|
|
|
|
+ this._el = null;
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
|
- * @property {TemplateDefinition} template
|
|
|
|
|
|
|
+ * An instance of Template to generate {@link #_el}.
|
|
|
|
|
+ *
|
|
|
|
|
+ * @private
|
|
|
|
|
+ * @property {Template}
|
|
|
*/
|
|
*/
|
|
|
|
|
+ this._template = null;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
|
- * Element of this view. The element is rendered on first reference.
|
|
|
|
|
|
|
+ * Element of this view. The element is rendered on first reference
|
|
|
|
|
+ * using {@link #template} definition and {@link #_template} object.
|
|
|
*
|
|
*
|
|
|
* @property el
|
|
* @property el
|
|
|
*/
|
|
*/
|
|
|
get el() {
|
|
get el() {
|
|
|
- return this._el || this.render();
|
|
|
|
|
|
|
+ if ( this._el ) {
|
|
|
|
|
+ return this._el;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if ( !this.template ) {
|
|
|
|
|
+ /**
|
|
|
|
|
+ * Attempting to access an element of a view, which has no `template`
|
|
|
|
|
+ * property.
|
|
|
|
|
+ *
|
|
|
|
|
+ * @error ui-view-notemplate
|
|
|
|
|
+ */
|
|
|
|
|
+ throw new CKEditorError( 'ui-view-notemplate' );
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // Prepare pre–defined listeners.
|
|
|
|
|
+ this._prepareElementListeners( this.template );
|
|
|
|
|
+
|
|
|
|
|
+ this._template = new Template( this.template );
|
|
|
|
|
+
|
|
|
|
|
+ return ( this._el = this._template.render() );
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ set el( el ) {
|
|
|
|
|
+ this._el = el;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * Initializes the view.
|
|
|
|
|
+ */
|
|
|
|
|
+ init() {
|
|
|
|
|
+ this._initRegions();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * Adds a child view to one of the {@link #regions} (see {@link #register}) in DOM
|
|
|
|
|
+ * at given, optional index position.
|
|
|
|
|
+ *
|
|
|
|
|
+ * @param {String} regionName One of {@link #regions} the child should be added to.
|
|
|
|
|
+ * @param {View} childView A child view.
|
|
|
|
|
+ * @param {Number} [index] Index at which the child will be added to the region.
|
|
|
|
|
+ */
|
|
|
|
|
+ addChild( regionName, childView, index ) {
|
|
|
|
|
+ if ( !regionName ) {
|
|
|
|
|
+ /**
|
|
|
|
|
+ * The name of the region is required.
|
|
|
|
|
+ *
|
|
|
|
|
+ * @error ui-view-addchild-badrname
|
|
|
|
|
+ */
|
|
|
|
|
+ throw new CKEditorError( 'ui-view-addchild-badrname' );
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ const region = this.regions.get( regionName );
|
|
|
|
|
+
|
|
|
|
|
+ if ( !region ) {
|
|
|
|
|
+ /**
|
|
|
|
|
+ * No such region of given name.
|
|
|
|
|
+ *
|
|
|
|
|
+ * @error ui-view-addchild-noreg
|
|
|
|
|
+ */
|
|
|
|
|
+ throw new CKEditorError( 'ui-view-addchild-noreg' );
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if ( !childView ) {
|
|
|
|
|
+ /**
|
|
|
|
|
+ * No child view passed.
|
|
|
|
|
+ *
|
|
|
|
|
+ * @error ui-view-addchild-no-view
|
|
|
|
|
+ */
|
|
|
|
|
+ throw new CKEditorError( 'ui-view-addchild-no-view' );
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ region.views.add( childView, index );
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * Removes a child view from one of the {@link #regions} (see {@link #register}) in DOM.
|
|
|
|
|
+ *
|
|
|
|
|
+ * @param {String} regionName One of {@link #regions} the view should be removed from.
|
|
|
|
|
+ * @param {View} childVIew A child view.
|
|
|
|
|
+ * @returns {View} A child view instance after removal.
|
|
|
|
|
+ */
|
|
|
|
|
+ removeChild( regionName, childView ) {
|
|
|
|
|
+ if ( !regionName ) {
|
|
|
|
|
+ /**
|
|
|
|
|
+ * The name of the region is required.
|
|
|
|
|
+ *
|
|
|
|
|
+ * @error ui-view-removechild-badrname
|
|
|
|
|
+ */
|
|
|
|
|
+ throw new CKEditorError( 'ui-view-removechild-badrname' );
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ const region = this.regions.get( regionName );
|
|
|
|
|
+
|
|
|
|
|
+ if ( !region ) {
|
|
|
|
|
+ /**
|
|
|
|
|
+ * No such region of given name.
|
|
|
|
|
+ *
|
|
|
|
|
+ * @error ui-view-removechild-noreg
|
|
|
|
|
+ */
|
|
|
|
|
+ throw new CKEditorError( 'ui-view-removechild-noreg' );
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if ( !childView ) {
|
|
|
|
|
+ /**
|
|
|
|
|
+ * The view must be an instance of View.
|
|
|
|
|
+ *
|
|
|
|
|
+ * @error ui-view-removechild-no-view
|
|
|
|
|
+ */
|
|
|
|
|
+ throw new CKEditorError( 'ui-view-removechild-no-view' );
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ region.views.remove( childView );
|
|
|
|
|
+
|
|
|
|
|
+ return childView;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
|
- * Binds a `property` of View's model so the DOM of the View is updated when the `property`
|
|
|
|
|
|
|
+ * Returns a child view from one of the {@link #regions}
|
|
|
|
|
+ * (see {@link #register}) at given `index`.
|
|
|
|
|
+ *
|
|
|
|
|
+ * @param {String} regionName One of {@link #regions} the child should be retrieved from.
|
|
|
|
|
+ * @param {Number} [index] An index of desired view.
|
|
|
|
|
+ * @returns {View} A view instance.
|
|
|
|
|
+ */
|
|
|
|
|
+ getChild( regionName, index ) {
|
|
|
|
|
+ const region = this.regions.get( regionName );
|
|
|
|
|
+
|
|
|
|
|
+ if ( !region ) {
|
|
|
|
|
+ /**
|
|
|
|
|
+ * No such region of given name.
|
|
|
|
|
+ *
|
|
|
|
|
+ * @error ui-view-getchild-noreg
|
|
|
|
|
+ */
|
|
|
|
|
+ throw new CKEditorError( 'ui-view-getchild-noreg' );
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return region.views.get( index );
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * Registers a region in {@link #regions}.
|
|
|
|
|
+ *
|
|
|
|
|
+ * let view = new View();
|
|
|
|
|
+ *
|
|
|
|
|
+ * // region.name == "foo", region.el == view.el.firstChild
|
|
|
|
|
+ * view.register( 'foo', el => el.firstChild );
|
|
|
|
|
+ *
|
|
|
|
|
+ * // region.name == "bar", region.el == view.el.querySelector( 'span' )
|
|
|
|
|
+ * view.register( new Region( 'bar' ), 'span' );
|
|
|
|
|
+ *
|
|
|
|
|
+ * // region.name == "bar", region.el == view.el.querySelector( '#div#id' )
|
|
|
|
|
+ * view.register( 'bar', 'div#id', true );
|
|
|
|
|
+ *
|
|
|
|
|
+ * // region.name == "baz", region.el == null
|
|
|
|
|
+ * view.register( 'baz', true );
|
|
|
|
|
+ *
|
|
|
|
|
+ * @param {String|Region} stringOrRegion The name or an instance of the Region
|
|
|
|
|
+ * to be registered. If `String`, the region will be created on the fly.
|
|
|
|
|
+ * @param {String|Function|true} regionSelector The selector to retrieve region's element
|
|
|
|
|
+ * in DOM when the region instance is initialized (see {@link Region#init}, {@link #init}).
|
|
|
|
|
+ * @param {Boolean} [override] When set `true` it will allow overriding of registered regions.
|
|
|
|
|
+ */
|
|
|
|
|
+ register( ...args ) {
|
|
|
|
|
+ let region, regionName;
|
|
|
|
|
+
|
|
|
|
|
+ if ( typeof args[ 0 ] === 'string' ) {
|
|
|
|
|
+ regionName = args[ 0 ];
|
|
|
|
|
+ region = this.regions.get( regionName ) || new Region( regionName );
|
|
|
|
|
+ } else if ( args[ 0 ] instanceof Region ) {
|
|
|
|
|
+ regionName = args[ 0 ].name;
|
|
|
|
|
+ region = args[ 0 ];
|
|
|
|
|
+ } else {
|
|
|
|
|
+ /**
|
|
|
|
|
+ * A name of the region or an instance of Region is required.
|
|
|
|
|
+ *
|
|
|
|
|
+ * @error ui-view-register-wrongtype
|
|
|
|
|
+ */
|
|
|
|
|
+ throw new CKEditorError( 'ui-view-register-wrongtype' );
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ const regionSelector = args[ 1 ];
|
|
|
|
|
+
|
|
|
|
|
+ if ( !regionSelector || !isValidRegionSelector( regionSelector ) ) {
|
|
|
|
|
+ /**
|
|
|
|
|
+ * The selector must be String, Function or `true`.
|
|
|
|
|
+ *
|
|
|
|
|
+ * @error ui-view-register-badselector
|
|
|
|
|
+ */
|
|
|
|
|
+ throw new CKEditorError( 'ui-view-register-badselector' );
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ const registered = this.regions.get( regionName );
|
|
|
|
|
+
|
|
|
|
|
+ if ( !registered ) {
|
|
|
|
|
+ this.regions.add( region );
|
|
|
|
|
+ } else {
|
|
|
|
|
+ if ( registered !== region ) {
|
|
|
|
|
+ if ( !args[ 2 ] ) {
|
|
|
|
|
+ /**
|
|
|
|
|
+ * Overriding is possible only when `override` flag is set.
|
|
|
|
|
+ *
|
|
|
|
|
+ * @error ui-view-register-override
|
|
|
|
|
+ */
|
|
|
|
|
+ throw new CKEditorError( 'ui-view-register-override' );
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ this.regions.remove( registered );
|
|
|
|
|
+ this.regions.add( region );
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ this._regionsSelectors[ regionName ] = regionSelector;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * Binds an `attribute` of View's model so the DOM of the View is updated when the `attribute`
|
|
|
* changes. It returns a function which, once called in the context of a DOM element,
|
|
* changes. It returns a function which, once called in the context of a DOM element,
|
|
|
* attaches a listener to the model which, in turn, brings changes to DOM.
|
|
* attaches a listener to the model which, in turn, brings changes to DOM.
|
|
|
*
|
|
*
|
|
|
- * @param {String} property Property name in the model to be observed.
|
|
|
|
|
- * @param {Function} [callback] Callback function executed on property change in model.
|
|
|
|
|
|
|
+ * @param {String} attribute Attribute name in the model to be observed.
|
|
|
|
|
+ * @param {Function} [callback] Callback function executed on attribute change in model.
|
|
|
* If not specified, a default DOM `domUpdater` supplied by the template is used.
|
|
* If not specified, a default DOM `domUpdater` supplied by the template is used.
|
|
|
*/
|
|
*/
|
|
|
- bind( property, callback ) {
|
|
|
|
|
|
|
+ bindToAttribute( attribute, callback ) {
|
|
|
/**
|
|
/**
|
|
|
- * Attaches a listener to View's model, which updates DOM when the model's property
|
|
|
|
|
|
|
+ * Attaches a listener to View's model, which updates DOM when the model's attribute
|
|
|
* changes. DOM is either updated by the `domUpdater` function supplied by the template
|
|
* changes. DOM is either updated by the `domUpdater` function supplied by the template
|
|
|
* (like attribute changer or `innerHTML` setter) or custom `callback` passed to {@link #bind}.
|
|
* (like attribute changer or `innerHTML` setter) or custom `callback` passed to {@link #bind}.
|
|
|
*
|
|
*
|
|
|
* This function is called by {@link Template#render}.
|
|
* This function is called by {@link Template#render}.
|
|
|
*
|
|
*
|
|
|
- * @param {HTMLElement} el DOM element to be updated when `property` in model changes.
|
|
|
|
|
|
|
+ * @param {HTMLElement} el DOM element to be updated when `attribute` in model changes.
|
|
|
* @param {Function} domUpdater A function provided by the template which updates corresponding
|
|
* @param {Function} domUpdater A function provided by the template which updates corresponding
|
|
|
* DOM.
|
|
* DOM.
|
|
|
*/
|
|
*/
|
|
|
return ( el, domUpdater ) => {
|
|
return ( el, domUpdater ) => {
|
|
|
- // TODO: Use ES6 default arguments syntax.
|
|
|
|
|
- callback = callback || domUpdater;
|
|
|
|
|
|
|
+ let onModelChange;
|
|
|
|
|
|
|
|
- // Execute callback when the property changes.
|
|
|
|
|
- this.listenTo( this.model, 'change:' + property, onModelChange );
|
|
|
|
|
|
|
+ if ( callback ) {
|
|
|
|
|
+ onModelChange = ( evt, value ) => {
|
|
|
|
|
+ let processedValue = callback( el, value );
|
|
|
|
|
|
|
|
- // Set the initial state of the view.
|
|
|
|
|
- onModelChange( null, this.model[ property ] );
|
|
|
|
|
|
|
+ if ( typeof processedValue != 'undefined' ) {
|
|
|
|
|
+ domUpdater( el, processedValue );
|
|
|
|
|
+ }
|
|
|
|
|
+ };
|
|
|
|
|
+ } else {
|
|
|
|
|
+ onModelChange = ( evt, value ) => domUpdater( el, value );
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
- function onModelChange( evt, value ) {
|
|
|
|
|
- let processedValue = callback( el, value );
|
|
|
|
|
|
|
+ // Execute callback when the attribute changes.
|
|
|
|
|
+ this.listenTo( this.model, 'change:' + attribute, onModelChange );
|
|
|
|
|
|
|
|
- if ( typeof processedValue != 'undefined' ) {
|
|
|
|
|
- domUpdater( el, processedValue );
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ // Set the initial state of the view.
|
|
|
|
|
+ onModelChange( null, this.model[ attribute ] );
|
|
|
};
|
|
};
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
|
- * Renders View's {@link el} using {@link Template} instance.
|
|
|
|
|
- *
|
|
|
|
|
- * @returns {HTMLElement} A root element of the View ({@link el}).
|
|
|
|
|
|
|
+ * Destroys the view instance. The process includes:
|
|
|
|
|
+ * 1. Removal of child views from {@link #regions}.
|
|
|
|
|
+ * 2. Destruction of the {@link #regions}.
|
|
|
|
|
+ * 3. Removal of {#link #_el} from DOM.
|
|
|
*/
|
|
*/
|
|
|
- render() {
|
|
|
|
|
- if ( !this.template ) {
|
|
|
|
|
- /**
|
|
|
|
|
- * This View implements no template to render.
|
|
|
|
|
- *
|
|
|
|
|
- * @error ui-view-notemplate
|
|
|
|
|
- * @param {View} view
|
|
|
|
|
- */
|
|
|
|
|
- throw new CKEditorError(
|
|
|
|
|
- 'ui-view-notemplate: This View implements no template to render.',
|
|
|
|
|
- { view: this }
|
|
|
|
|
- );
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // Prepare pre–defined listeners.
|
|
|
|
|
- this.prepareListeners();
|
|
|
|
|
|
|
+ destroy() {
|
|
|
|
|
+ let childView;
|
|
|
|
|
|
|
|
- this._template = new Template( this.template );
|
|
|
|
|
|
|
+ this.stopListening();
|
|
|
|
|
|
|
|
- return ( this._el = this._template.render() );
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ for ( let region of this.regions ) {
|
|
|
|
|
+ while ( ( childView = this.getChild( region.name, 0 ) ) ) {
|
|
|
|
|
+ this.removeChild( region.name, childView );
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
- /**
|
|
|
|
|
- * Destroys the View.
|
|
|
|
|
- */
|
|
|
|
|
- destroy() {
|
|
|
|
|
- // Drop the reference to the model.
|
|
|
|
|
- this.model = null;
|
|
|
|
|
|
|
+ this.regions.remove( region ).destroy();
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
- // Remove View's element from DOM.
|
|
|
|
|
if ( this.template ) {
|
|
if ( this.template ) {
|
|
|
this.el.remove();
|
|
this.el.remove();
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- // Remove and destroy regions.
|
|
|
|
|
- for ( let region of this.regions ) {
|
|
|
|
|
- this.regions.remove( region ).destroy();
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // Remove all listeners related to this view.
|
|
|
|
|
- this.stopListening();
|
|
|
|
|
|
|
+ this.model = this.regions = this.template = this._regionsSelectors = this._el = this._template = null;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
|
- * Iterates over all "on" properties in {@link template} and replaces
|
|
|
|
|
- * listener definitions with functions which, once executed in a context of
|
|
|
|
|
- * a DOM element, will attach native DOM listeners to elements.
|
|
|
|
|
|
|
+ * Initializes {@link #regions} of this view by passing a DOM element
|
|
|
|
|
+ * generated from {@link #_regionsSelectors} into {@link Region#init}.
|
|
|
*
|
|
*
|
|
|
- * The execution is performed by {@link Template} class.
|
|
|
|
|
|
|
+ * @protected
|
|
|
*/
|
|
*/
|
|
|
- prepareListeners() {
|
|
|
|
|
- if ( this.template ) {
|
|
|
|
|
- this._prepareElementListeners( this.template );
|
|
|
|
|
|
|
+ _initRegions() {
|
|
|
|
|
+ let region, regionEl, regionSelector;
|
|
|
|
|
+
|
|
|
|
|
+ for ( region of this.regions ) {
|
|
|
|
|
+ regionSelector = this._regionsSelectors[ region.name ];
|
|
|
|
|
+
|
|
|
|
|
+ if ( typeof regionSelector == 'string' ) {
|
|
|
|
|
+ regionEl = this.el.querySelector( regionSelector );
|
|
|
|
|
+ } else if ( typeof regionSelector == 'function' ) {
|
|
|
|
|
+ regionEl = regionSelector( this.el );
|
|
|
|
|
+ } else {
|
|
|
|
|
+ regionEl = null;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ region.init( regionEl );
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -171,6 +401,7 @@ CKEDITOR.define( [
|
|
|
* to the element. The listener executes given callback or fires View's event
|
|
* to the element. The listener executes given callback or fires View's event
|
|
|
* of given name.
|
|
* of given name.
|
|
|
*
|
|
*
|
|
|
|
|
+ * @protected
|
|
|
* @param {String|Function} evtNameOrCallback Event name to be fired on View or callback to execute.
|
|
* @param {String|Function} evtNameOrCallback Event name to be fired on View or callback to execute.
|
|
|
* @returns {Function} A function to be executed in the context of an element.
|
|
* @returns {Function} A function to be executed in the context of an element.
|
|
|
*/
|
|
*/
|
|
@@ -220,6 +451,7 @@ CKEDITOR.define( [
|
|
|
* replace each listener declaration with a function which, once executed in a context
|
|
* replace each listener declaration with a function which, once executed in a context
|
|
|
* of an element, attaches native DOM listener to the element.
|
|
* of an element, attaches native DOM listener to the element.
|
|
|
*
|
|
*
|
|
|
|
|
+ * @protected
|
|
|
* @param {TemplateDefinition} def Template definition.
|
|
* @param {TemplateDefinition} def Template definition.
|
|
|
*/
|
|
*/
|
|
|
_prepareElementListeners( def ) {
|
|
_prepareElementListeners( def ) {
|
|
@@ -263,5 +495,18 @@ CKEDITOR.define( [
|
|
|
|
|
|
|
|
utils.extend( View.prototype, DOMEmitterMixin );
|
|
utils.extend( View.prototype, DOMEmitterMixin );
|
|
|
|
|
|
|
|
|
|
+ const validSelectorTypes = new Set( [ 'string', 'boolean', 'function' ] );
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * Check whether region selector is valid.
|
|
|
|
|
+ *
|
|
|
|
|
+ * @protected
|
|
|
|
|
+ * @param {*} selector Selector to be checked.
|
|
|
|
|
+ * @returns {Boolean}
|
|
|
|
|
+ */
|
|
|
|
|
+ function isValidRegionSelector( selector ) {
|
|
|
|
|
+ return validSelectorTypes.has( typeof selector ) && selector !== false;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
return View;
|
|
return View;
|
|
|
} );
|
|
} );
|