@ckeditor/ckeditor5-ui 38.1.1 → 38.2.0-alpha.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (134) hide show
  1. package/lang/contexts.json +2 -1
  2. package/package.json +4 -3
  3. package/src/augmentation.d.ts +86 -86
  4. package/src/augmentation.js +5 -5
  5. package/src/bindings/addkeyboardhandlingforgrid.d.ts +27 -27
  6. package/src/bindings/addkeyboardhandlingforgrid.js +107 -107
  7. package/src/bindings/clickoutsidehandler.d.ts +28 -28
  8. package/src/bindings/clickoutsidehandler.js +36 -36
  9. package/src/bindings/csstransitiondisablermixin.d.ts +40 -40
  10. package/src/bindings/csstransitiondisablermixin.js +55 -55
  11. package/src/bindings/injectcsstransitiondisabler.d.ts +59 -59
  12. package/src/bindings/injectcsstransitiondisabler.js +71 -71
  13. package/src/bindings/preventdefault.d.ts +33 -33
  14. package/src/bindings/preventdefault.js +34 -34
  15. package/src/bindings/submithandler.d.ts +57 -57
  16. package/src/bindings/submithandler.js +47 -47
  17. package/src/button/button.d.ts +178 -178
  18. package/src/button/button.js +5 -5
  19. package/src/button/buttonview.d.ts +177 -177
  20. package/src/button/buttonview.js +231 -231
  21. package/src/button/switchbuttonview.d.ts +45 -45
  22. package/src/button/switchbuttonview.js +75 -75
  23. package/src/colorgrid/colorgridview.d.ts +132 -132
  24. package/src/colorgrid/colorgridview.js +124 -124
  25. package/src/colorgrid/colortileview.d.ts +28 -28
  26. package/src/colorgrid/colortileview.js +40 -40
  27. package/src/colorgrid/utils.d.ts +47 -47
  28. package/src/colorgrid/utils.js +84 -84
  29. package/src/colorpicker/colorpickerview.d.ts +137 -110
  30. package/src/colorpicker/colorpickerview.js +270 -253
  31. package/src/colorpicker/utils.d.ts +43 -35
  32. package/src/colorpicker/utils.js +99 -99
  33. package/src/colorselector/colorgridsfragmentview.d.ts +194 -0
  34. package/src/colorselector/colorgridsfragmentview.js +290 -0
  35. package/src/colorselector/colorpickerfragmentview.d.ts +128 -0
  36. package/src/colorselector/colorpickerfragmentview.js +205 -0
  37. package/src/colorselector/colorselectorview.d.ts +242 -0
  38. package/src/colorselector/colorselectorview.js +256 -0
  39. package/src/colorselector/documentcolorcollection.d.ts +70 -0
  40. package/src/colorselector/documentcolorcollection.js +42 -0
  41. package/src/componentfactory.d.ts +81 -81
  42. package/src/componentfactory.js +104 -104
  43. package/src/dropdown/button/dropdownbutton.d.ts +25 -25
  44. package/src/dropdown/button/dropdownbutton.js +5 -5
  45. package/src/dropdown/button/dropdownbuttonview.d.ts +48 -48
  46. package/src/dropdown/button/dropdownbuttonview.js +66 -66
  47. package/src/dropdown/button/splitbuttonview.d.ts +161 -161
  48. package/src/dropdown/button/splitbuttonview.js +152 -152
  49. package/src/dropdown/dropdownpanelfocusable.d.ts +21 -21
  50. package/src/dropdown/dropdownpanelfocusable.js +5 -5
  51. package/src/dropdown/dropdownpanelview.d.ts +62 -62
  52. package/src/dropdown/dropdownpanelview.js +96 -96
  53. package/src/dropdown/dropdownview.d.ts +315 -315
  54. package/src/dropdown/dropdownview.js +378 -378
  55. package/src/dropdown/utils.d.ts +221 -221
  56. package/src/dropdown/utils.js +437 -434
  57. package/src/editableui/editableuiview.d.ts +72 -72
  58. package/src/editableui/editableuiview.js +112 -112
  59. package/src/editableui/inline/inlineeditableuiview.d.ts +40 -40
  60. package/src/editableui/inline/inlineeditableuiview.js +48 -48
  61. package/src/editorui/bodycollection.d.ts +55 -55
  62. package/src/editorui/bodycollection.js +84 -84
  63. package/src/editorui/boxed/boxededitoruiview.d.ts +40 -40
  64. package/src/editorui/boxed/boxededitoruiview.js +81 -81
  65. package/src/editorui/editorui.d.ts +282 -282
  66. package/src/editorui/editorui.js +410 -410
  67. package/src/editorui/editoruiview.d.ts +39 -39
  68. package/src/editorui/editoruiview.js +38 -38
  69. package/src/editorui/poweredby.d.ts +71 -71
  70. package/src/editorui/poweredby.js +294 -294
  71. package/src/focuscycler.d.ts +183 -183
  72. package/src/focuscycler.js +220 -220
  73. package/src/formheader/formheaderview.d.ts +53 -53
  74. package/src/formheader/formheaderview.js +63 -63
  75. package/src/icon/iconview.d.ts +78 -78
  76. package/src/icon/iconview.js +112 -112
  77. package/src/iframe/iframeview.d.ts +50 -50
  78. package/src/iframe/iframeview.js +63 -63
  79. package/src/index.d.ts +63 -62
  80. package/src/index.js +62 -61
  81. package/src/input/inputview.d.ts +121 -121
  82. package/src/input/inputview.js +106 -106
  83. package/src/inputnumber/inputnumberview.d.ts +49 -49
  84. package/src/inputnumber/inputnumberview.js +40 -40
  85. package/src/inputtext/inputtextview.d.ts +18 -18
  86. package/src/inputtext/inputtextview.js +27 -27
  87. package/src/label/labelview.d.ts +36 -36
  88. package/src/label/labelview.js +41 -41
  89. package/src/labeledfield/labeledfieldview.d.ts +182 -182
  90. package/src/labeledfield/labeledfieldview.js +157 -157
  91. package/src/labeledfield/utils.d.ts +93 -93
  92. package/src/labeledfield/utils.js +131 -131
  93. package/src/labeledinput/labeledinputview.d.ts +125 -125
  94. package/src/labeledinput/labeledinputview.js +125 -125
  95. package/src/list/listitemview.d.ts +35 -35
  96. package/src/list/listitemview.js +40 -40
  97. package/src/list/listseparatorview.d.ts +18 -18
  98. package/src/list/listseparatorview.js +28 -28
  99. package/src/list/listview.d.ts +65 -65
  100. package/src/list/listview.js +90 -90
  101. package/src/model.d.ts +22 -22
  102. package/src/model.js +31 -31
  103. package/src/notification/notification.d.ts +211 -211
  104. package/src/notification/notification.js +187 -187
  105. package/src/panel/balloon/balloonpanelview.d.ts +685 -685
  106. package/src/panel/balloon/balloonpanelview.js +988 -988
  107. package/src/panel/balloon/contextualballoon.d.ts +299 -299
  108. package/src/panel/balloon/contextualballoon.js +572 -572
  109. package/src/panel/sticky/stickypanelview.d.ts +156 -132
  110. package/src/panel/sticky/stickypanelview.js +272 -139
  111. package/src/template.d.ts +942 -942
  112. package/src/template.js +1294 -1294
  113. package/src/toolbar/balloon/balloontoolbar.d.ts +122 -122
  114. package/src/toolbar/balloon/balloontoolbar.js +300 -300
  115. package/src/toolbar/block/blockbuttonview.d.ts +35 -35
  116. package/src/toolbar/block/blockbuttonview.js +41 -41
  117. package/src/toolbar/block/blocktoolbar.d.ts +161 -161
  118. package/src/toolbar/block/blocktoolbar.js +391 -391
  119. package/src/toolbar/normalizetoolbarconfig.d.ts +39 -39
  120. package/src/toolbar/normalizetoolbarconfig.js +51 -51
  121. package/src/toolbar/toolbarlinebreakview.d.ts +18 -18
  122. package/src/toolbar/toolbarlinebreakview.js +28 -28
  123. package/src/toolbar/toolbarseparatorview.d.ts +18 -18
  124. package/src/toolbar/toolbarseparatorview.js +28 -28
  125. package/src/toolbar/toolbarview.d.ts +265 -265
  126. package/src/toolbar/toolbarview.js +717 -717
  127. package/src/tooltipmanager.d.ts +180 -180
  128. package/src/tooltipmanager.js +353 -353
  129. package/src/view.d.ts +422 -422
  130. package/src/view.js +396 -396
  131. package/src/viewcollection.d.ts +139 -139
  132. package/src/viewcollection.js +206 -206
  133. package/theme/components/colorpicker/colorpicker.css +10 -0
  134. package/theme/components/colorselector/colorselector.css +35 -0
package/src/view.js CHANGED
@@ -1,396 +1,396 @@
1
- /**
2
- * @license Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved.
3
- * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
4
- */
5
- /* eslint-disable @typescript-eslint/no-invalid-void-type */
6
- /**
7
- * @module ui/view
8
- */
9
- import ViewCollection from './viewcollection';
10
- import Template from './template';
11
- import { CKEditorError, Collection, DomEmitterMixin, ObservableMixin, isIterable } from '@ckeditor/ckeditor5-utils';
12
- import '../theme/globals/globals.css';
13
- /**
14
- * The basic view class, which represents an HTML element created out of a
15
- * {@link module:ui/view~View#template}. Views are building blocks of the user interface and handle
16
- * interaction
17
- *
18
- * Views {@link module:ui/view~View#registerChild aggregate} children in
19
- * {@link module:ui/view~View#createCollection collections} and manage the life cycle of DOM
20
- * listeners e.g. by handling rendering and destruction.
21
- *
22
- * See the {@link module:ui/template~TemplateDefinition} syntax to learn more about shaping view
23
- * elements, attributes and listeners.
24
- *
25
- * ```ts
26
- * class SampleView extends View {
27
- * constructor( locale ) {
28
- * super( locale );
29
- *
30
- * const bind = this.bindTemplate;
31
- *
32
- * // Views define their interface (state) using observable attributes.
33
- * this.set( 'elementClass', 'bar' );
34
- *
35
- * this.setTemplate( {
36
- * tag: 'p',
37
- *
38
- * // The element of the view can be defined with its children.
39
- * children: [
40
- * 'Hello',
41
- * {
42
- * tag: 'b',
43
- * children: [ 'world!' ]
44
- * }
45
- * ],
46
- * attributes: {
47
- * class: [
48
- * 'foo',
49
- *
50
- * // Observable attributes control the state of the view in DOM.
51
- * bind.to( 'elementClass' )
52
- * ]
53
- * },
54
- * on: {
55
- * // Views listen to DOM events and propagate them.
56
- * click: bind.to( 'clicked' )
57
- * }
58
- * } );
59
- * }
60
- * }
61
- *
62
- * const view = new SampleView( locale );
63
- *
64
- * view.render();
65
- *
66
- * // Append <p class="foo bar">Hello<b>world</b></p> to the <body>
67
- * document.body.appendChild( view.element );
68
- *
69
- * // Change the class attribute to <p class="foo baz">Hello<b>world</b></p>
70
- * view.elementClass = 'baz';
71
- *
72
- * // Respond to the "click" event in DOM by executing a custom action.
73
- * view.on( 'clicked', () => {
74
- * console.log( 'The view has been clicked!' );
75
- * } );
76
- * ```
77
- */
78
- export default class View extends DomEmitterMixin(ObservableMixin()) {
79
- /**
80
- * Creates an instance of the {@link module:ui/view~View} class.
81
- *
82
- * Also see {@link #render}.
83
- *
84
- * @param locale The localization services instance.
85
- */
86
- constructor(locale) {
87
- super();
88
- this.element = null;
89
- this.isRendered = false;
90
- this.locale = locale;
91
- this.t = locale && locale.t;
92
- this._viewCollections = new Collection();
93
- this._unboundChildren = this.createCollection();
94
- // Pass parent locale to its children.
95
- this._viewCollections.on('add', (evt, collection) => {
96
- collection.locale = locale;
97
- collection.t = locale && locale.t;
98
- });
99
- this.decorate('render');
100
- }
101
- /**
102
- * Shorthand for {@link module:ui/template~Template.bind}, a binding
103
- * {@link module:ui/template~BindChain interface} pre–configured for the view instance.
104
- *
105
- * It provides {@link module:ui/template~BindChain#to `to()`} and
106
- * {@link module:ui/template~BindChain#if `if()`} methods that initialize bindings with
107
- * observable attributes and attach DOM listeners.
108
- *
109
- * ```ts
110
- * class SampleView extends View {
111
- * constructor( locale ) {
112
- * super( locale );
113
- *
114
- * const bind = this.bindTemplate;
115
- *
116
- * // These {@link module:utils/observablemixin~Observable observable} attributes will control
117
- * // the state of the view in DOM.
118
- * this.set( {
119
- * elementClass: 'foo',
120
- * isEnabled: true
121
- * } );
122
- *
123
- * this.setTemplate( {
124
- * tag: 'p',
125
- *
126
- * attributes: {
127
- * // The class HTML attribute will follow elementClass
128
- * // and isEnabled view attributes.
129
- * class: [
130
- * bind.to( 'elementClass' )
131
- * bind.if( 'isEnabled', 'present-when-enabled' )
132
- * ]
133
- * },
134
- *
135
- * on: {
136
- * // The view will fire the "clicked" event upon clicking <p> in DOM.
137
- * click: bind.to( 'clicked' )
138
- * }
139
- * } );
140
- * }
141
- * }
142
- * ```
143
- */
144
- get bindTemplate() {
145
- if (this._bindTemplate) {
146
- return this._bindTemplate;
147
- }
148
- return (this._bindTemplate = Template.bind(this, this));
149
- }
150
- /**
151
- * Creates a new collection of views, which can be used as
152
- * {@link module:ui/template~Template#children} of this view.
153
- *
154
- * ```ts
155
- * class SampleView extends View {
156
- * constructor( locale ) {
157
- * super( locale );
158
- *
159
- * const child = new ChildView( locale );
160
- * this.items = this.createCollection( [ child ] );
161
- *
162
- * this.setTemplate( {
163
- * tag: 'p',
164
- *
165
- * // `items` collection will render here.
166
- * children: this.items
167
- * } );
168
- * }
169
- * }
170
- *
171
- * const view = new SampleView( locale );
172
- * view.render();
173
- *
174
- * // It will append <p><child#element></p> to the <body>.
175
- * document.body.appendChild( view.element );
176
- * ```
177
- *
178
- * @param views Initial views of the collection.
179
- * @returns A new collection of view instances.
180
- */
181
- createCollection(views) {
182
- const collection = new ViewCollection(views);
183
- this._viewCollections.add(collection);
184
- return collection;
185
- }
186
- /**
187
- * Registers a new child view under the view instance. Once registered, a child
188
- * view is managed by its parent, including {@link #render rendering}
189
- * and {@link #destroy destruction}.
190
- *
191
- * To revert this, use {@link #deregisterChild}.
192
- *
193
- * ```ts
194
- * class SampleView extends View {
195
- * constructor( locale ) {
196
- * super( locale );
197
- *
198
- * this.childA = new SomeChildView( locale );
199
- * this.childB = new SomeChildView( locale );
200
- *
201
- * this.setTemplate( { tag: 'p' } );
202
- *
203
- * // Register the children.
204
- * this.registerChild( [ this.childA, this.childB ] );
205
- * }
206
- *
207
- * render() {
208
- * super.render();
209
- *
210
- * this.element.appendChild( this.childA.element );
211
- * this.element.appendChild( this.childB.element );
212
- * }
213
- * }
214
- *
215
- * const view = new SampleView( locale );
216
- *
217
- * view.render();
218
- *
219
- * // Will append <p><childA#element><b></b><childB#element></p>.
220
- * document.body.appendChild( view.element );
221
- * ```
222
- *
223
- * **Note**: There's no need to add child views if they're already referenced in the
224
- * {@link #template}:
225
- *
226
- * ```ts
227
- * class SampleView extends View {
228
- * constructor( locale ) {
229
- * super( locale );
230
- *
231
- * this.childA = new SomeChildView( locale );
232
- * this.childB = new SomeChildView( locale );
233
- *
234
- * this.setTemplate( {
235
- * tag: 'p',
236
- *
237
- * // These children will be added automatically. There's no
238
- * // need to call {@link #registerChild} for any of them.
239
- * children: [ this.childA, this.childB ]
240
- * } );
241
- * }
242
- *
243
- * // ...
244
- * }
245
- * ```
246
- *
247
- * @param children Children views to be registered.
248
- */
249
- registerChild(children) {
250
- if (!isIterable(children)) {
251
- children = [children];
252
- }
253
- for (const child of children) {
254
- this._unboundChildren.add(child);
255
- }
256
- }
257
- /**
258
- * The opposite of {@link #registerChild}. Removes a child view from this view instance.
259
- * Once removed, the child is no longer managed by its parent, e.g. it can safely
260
- * become a child of another parent view.
261
- *
262
- * @see #registerChild
263
- * @param children Child views to be removed.
264
- */
265
- deregisterChild(children) {
266
- if (!isIterable(children)) {
267
- children = [children];
268
- }
269
- for (const child of children) {
270
- this._unboundChildren.remove(child);
271
- }
272
- }
273
- /**
274
- * Sets the {@link #template} of the view with with given definition.
275
- *
276
- * A shorthand for:
277
- *
278
- * ```ts
279
- * view.setTemplate( definition );
280
- * ```
281
- *
282
- * @param definition Definition of view's template.
283
- */
284
- setTemplate(definition) {
285
- this.template = new Template(definition);
286
- }
287
- /**
288
- * {@link module:ui/template~Template.extend Extends} the {@link #template} of the view with
289
- * with given definition.
290
- *
291
- * A shorthand for:
292
- *
293
- * ```ts
294
- * Template.extend( view.template, definition );
295
- * ```
296
- *
297
- * **Note**: Is requires the {@link #template} to be already set. See {@link #setTemplate}.
298
- *
299
- * @param definition Definition which extends the {@link #template}.
300
- */
301
- extendTemplate(definition) {
302
- Template.extend(this.template, definition);
303
- }
304
- /**
305
- * Recursively renders the view.
306
- *
307
- * Once the view is rendered:
308
- * * the {@link #element} becomes an HTML element out of {@link #template},
309
- * * the {@link #isRendered} flag is set `true`.
310
- *
311
- * **Note**: The children of the view:
312
- * * defined directly in the {@link #template}
313
- * * residing in collections created by the {@link #createCollection} method,
314
- * * and added by {@link #registerChild}
315
- * are also rendered in the process.
316
- *
317
- * In general, `render()` method is the right place to keep the code which refers to the
318
- * {@link #element} and should be executed at the very beginning of the view's life cycle.
319
- *
320
- * It is possible to {@link module:ui/template~Template.extend} the {@link #template} before
321
- * the view is rendered. To allow an early customization of the view (e.g. by its parent),
322
- * such references should be done in `render()`.
323
- *
324
- * ```ts
325
- * class SampleView extends View {
326
- * constructor() {
327
- * this.setTemplate( {
328
- * // ...
329
- * } );
330
- * },
331
- *
332
- * render() {
333
- * // View#element becomes available.
334
- * super.render();
335
- *
336
- * // The "scroll" listener depends on #element.
337
- * this.listenTo( window, 'scroll', () => {
338
- * // A reference to #element would render the #template and make it non-extendable.
339
- * if ( window.scrollY > 0 ) {
340
- * this.element.scrollLeft = 100;
341
- * } else {
342
- * this.element.scrollLeft = 0;
343
- * }
344
- * } );
345
- * }
346
- * }
347
- *
348
- * const view = new SampleView();
349
- *
350
- * // Let's customize the view before it gets rendered.
351
- * view.extendTemplate( {
352
- * attributes: {
353
- * class: [
354
- * 'additional-class'
355
- * ]
356
- * }
357
- * } );
358
- *
359
- * // Late rendering allows customization of the view.
360
- * view.render();
361
- * ```
362
- */
363
- render() {
364
- if (this.isRendered) {
365
- /**
366
- * This View has already been rendered.
367
- *
368
- * @error ui-view-render-already-rendered
369
- */
370
- throw new CKEditorError('ui-view-render-already-rendered', this);
371
- }
372
- // Render #element of the view.
373
- if (this.template) {
374
- this.element = this.template.render();
375
- // Auto–register view children from #template.
376
- this.registerChild(this.template.getViews());
377
- }
378
- this.isRendered = true;
379
- }
380
- /**
381
- * Recursively destroys the view instance and child views added by {@link #registerChild} and
382
- * residing in collections created by the {@link #createCollection}.
383
- *
384
- * Destruction disables all event listeners:
385
- * * created on the view, e.g. `view.on( 'event', () => {} )`,
386
- * * defined in the {@link #template} for DOM events.
387
- */
388
- destroy() {
389
- this.stopListening();
390
- this._viewCollections.map(c => c.destroy());
391
- // Template isn't obligatory for views.
392
- if (this.template && this.template._revertData) {
393
- this.template.revert(this.element);
394
- }
395
- }
396
- }
1
+ /**
2
+ * @license Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved.
3
+ * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
4
+ */
5
+ /* eslint-disable @typescript-eslint/no-invalid-void-type */
6
+ /**
7
+ * @module ui/view
8
+ */
9
+ import ViewCollection from './viewcollection.js';
10
+ import Template from './template.js';
11
+ import { CKEditorError, Collection, DomEmitterMixin, ObservableMixin, isIterable } from '@ckeditor/ckeditor5-utils';
12
+ import '../theme/globals/globals.css';
13
+ /**
14
+ * The basic view class, which represents an HTML element created out of a
15
+ * {@link module:ui/view~View#template}. Views are building blocks of the user interface and handle
16
+ * interaction
17
+ *
18
+ * Views {@link module:ui/view~View#registerChild aggregate} children in
19
+ * {@link module:ui/view~View#createCollection collections} and manage the life cycle of DOM
20
+ * listeners e.g. by handling rendering and destruction.
21
+ *
22
+ * See the {@link module:ui/template~TemplateDefinition} syntax to learn more about shaping view
23
+ * elements, attributes and listeners.
24
+ *
25
+ * ```ts
26
+ * class SampleView extends View {
27
+ * constructor( locale ) {
28
+ * super( locale );
29
+ *
30
+ * const bind = this.bindTemplate;
31
+ *
32
+ * // Views define their interface (state) using observable attributes.
33
+ * this.set( 'elementClass', 'bar' );
34
+ *
35
+ * this.setTemplate( {
36
+ * tag: 'p',
37
+ *
38
+ * // The element of the view can be defined with its children.
39
+ * children: [
40
+ * 'Hello',
41
+ * {
42
+ * tag: 'b',
43
+ * children: [ 'world!' ]
44
+ * }
45
+ * ],
46
+ * attributes: {
47
+ * class: [
48
+ * 'foo',
49
+ *
50
+ * // Observable attributes control the state of the view in DOM.
51
+ * bind.to( 'elementClass' )
52
+ * ]
53
+ * },
54
+ * on: {
55
+ * // Views listen to DOM events and propagate them.
56
+ * click: bind.to( 'clicked' )
57
+ * }
58
+ * } );
59
+ * }
60
+ * }
61
+ *
62
+ * const view = new SampleView( locale );
63
+ *
64
+ * view.render();
65
+ *
66
+ * // Append <p class="foo bar">Hello<b>world</b></p> to the <body>
67
+ * document.body.appendChild( view.element );
68
+ *
69
+ * // Change the class attribute to <p class="foo baz">Hello<b>world</b></p>
70
+ * view.elementClass = 'baz';
71
+ *
72
+ * // Respond to the "click" event in DOM by executing a custom action.
73
+ * view.on( 'clicked', () => {
74
+ * console.log( 'The view has been clicked!' );
75
+ * } );
76
+ * ```
77
+ */
78
+ export default class View extends DomEmitterMixin(ObservableMixin()) {
79
+ /**
80
+ * Creates an instance of the {@link module:ui/view~View} class.
81
+ *
82
+ * Also see {@link #render}.
83
+ *
84
+ * @param locale The localization services instance.
85
+ */
86
+ constructor(locale) {
87
+ super();
88
+ this.element = null;
89
+ this.isRendered = false;
90
+ this.locale = locale;
91
+ this.t = locale && locale.t;
92
+ this._viewCollections = new Collection();
93
+ this._unboundChildren = this.createCollection();
94
+ // Pass parent locale to its children.
95
+ this._viewCollections.on('add', (evt, collection) => {
96
+ collection.locale = locale;
97
+ collection.t = locale && locale.t;
98
+ });
99
+ this.decorate('render');
100
+ }
101
+ /**
102
+ * Shorthand for {@link module:ui/template~Template.bind}, a binding
103
+ * {@link module:ui/template~BindChain interface} pre–configured for the view instance.
104
+ *
105
+ * It provides {@link module:ui/template~BindChain#to `to()`} and
106
+ * {@link module:ui/template~BindChain#if `if()`} methods that initialize bindings with
107
+ * observable attributes and attach DOM listeners.
108
+ *
109
+ * ```ts
110
+ * class SampleView extends View {
111
+ * constructor( locale ) {
112
+ * super( locale );
113
+ *
114
+ * const bind = this.bindTemplate;
115
+ *
116
+ * // These {@link module:utils/observablemixin~Observable observable} attributes will control
117
+ * // the state of the view in DOM.
118
+ * this.set( {
119
+ * elementClass: 'foo',
120
+ * isEnabled: true
121
+ * } );
122
+ *
123
+ * this.setTemplate( {
124
+ * tag: 'p',
125
+ *
126
+ * attributes: {
127
+ * // The class HTML attribute will follow elementClass
128
+ * // and isEnabled view attributes.
129
+ * class: [
130
+ * bind.to( 'elementClass' )
131
+ * bind.if( 'isEnabled', 'present-when-enabled' )
132
+ * ]
133
+ * },
134
+ *
135
+ * on: {
136
+ * // The view will fire the "clicked" event upon clicking <p> in DOM.
137
+ * click: bind.to( 'clicked' )
138
+ * }
139
+ * } );
140
+ * }
141
+ * }
142
+ * ```
143
+ */
144
+ get bindTemplate() {
145
+ if (this._bindTemplate) {
146
+ return this._bindTemplate;
147
+ }
148
+ return (this._bindTemplate = Template.bind(this, this));
149
+ }
150
+ /**
151
+ * Creates a new collection of views, which can be used as
152
+ * {@link module:ui/template~Template#children} of this view.
153
+ *
154
+ * ```ts
155
+ * class SampleView extends View {
156
+ * constructor( locale ) {
157
+ * super( locale );
158
+ *
159
+ * const child = new ChildView( locale );
160
+ * this.items = this.createCollection( [ child ] );
161
+ *
162
+ * this.setTemplate( {
163
+ * tag: 'p',
164
+ *
165
+ * // `items` collection will render here.
166
+ * children: this.items
167
+ * } );
168
+ * }
169
+ * }
170
+ *
171
+ * const view = new SampleView( locale );
172
+ * view.render();
173
+ *
174
+ * // It will append <p><child#element></p> to the <body>.
175
+ * document.body.appendChild( view.element );
176
+ * ```
177
+ *
178
+ * @param views Initial views of the collection.
179
+ * @returns A new collection of view instances.
180
+ */
181
+ createCollection(views) {
182
+ const collection = new ViewCollection(views);
183
+ this._viewCollections.add(collection);
184
+ return collection;
185
+ }
186
+ /**
187
+ * Registers a new child view under the view instance. Once registered, a child
188
+ * view is managed by its parent, including {@link #render rendering}
189
+ * and {@link #destroy destruction}.
190
+ *
191
+ * To revert this, use {@link #deregisterChild}.
192
+ *
193
+ * ```ts
194
+ * class SampleView extends View {
195
+ * constructor( locale ) {
196
+ * super( locale );
197
+ *
198
+ * this.childA = new SomeChildView( locale );
199
+ * this.childB = new SomeChildView( locale );
200
+ *
201
+ * this.setTemplate( { tag: 'p' } );
202
+ *
203
+ * // Register the children.
204
+ * this.registerChild( [ this.childA, this.childB ] );
205
+ * }
206
+ *
207
+ * render() {
208
+ * super.render();
209
+ *
210
+ * this.element.appendChild( this.childA.element );
211
+ * this.element.appendChild( this.childB.element );
212
+ * }
213
+ * }
214
+ *
215
+ * const view = new SampleView( locale );
216
+ *
217
+ * view.render();
218
+ *
219
+ * // Will append <p><childA#element><b></b><childB#element></p>.
220
+ * document.body.appendChild( view.element );
221
+ * ```
222
+ *
223
+ * **Note**: There's no need to add child views if they're already referenced in the
224
+ * {@link #template}:
225
+ *
226
+ * ```ts
227
+ * class SampleView extends View {
228
+ * constructor( locale ) {
229
+ * super( locale );
230
+ *
231
+ * this.childA = new SomeChildView( locale );
232
+ * this.childB = new SomeChildView( locale );
233
+ *
234
+ * this.setTemplate( {
235
+ * tag: 'p',
236
+ *
237
+ * // These children will be added automatically. There's no
238
+ * // need to call {@link #registerChild} for any of them.
239
+ * children: [ this.childA, this.childB ]
240
+ * } );
241
+ * }
242
+ *
243
+ * // ...
244
+ * }
245
+ * ```
246
+ *
247
+ * @param children Children views to be registered.
248
+ */
249
+ registerChild(children) {
250
+ if (!isIterable(children)) {
251
+ children = [children];
252
+ }
253
+ for (const child of children) {
254
+ this._unboundChildren.add(child);
255
+ }
256
+ }
257
+ /**
258
+ * The opposite of {@link #registerChild}. Removes a child view from this view instance.
259
+ * Once removed, the child is no longer managed by its parent, e.g. it can safely
260
+ * become a child of another parent view.
261
+ *
262
+ * @see #registerChild
263
+ * @param children Child views to be removed.
264
+ */
265
+ deregisterChild(children) {
266
+ if (!isIterable(children)) {
267
+ children = [children];
268
+ }
269
+ for (const child of children) {
270
+ this._unboundChildren.remove(child);
271
+ }
272
+ }
273
+ /**
274
+ * Sets the {@link #template} of the view with with given definition.
275
+ *
276
+ * A shorthand for:
277
+ *
278
+ * ```ts
279
+ * view.setTemplate( definition );
280
+ * ```
281
+ *
282
+ * @param definition Definition of view's template.
283
+ */
284
+ setTemplate(definition) {
285
+ this.template = new Template(definition);
286
+ }
287
+ /**
288
+ * {@link module:ui/template~Template.extend Extends} the {@link #template} of the view with
289
+ * with given definition.
290
+ *
291
+ * A shorthand for:
292
+ *
293
+ * ```ts
294
+ * Template.extend( view.template, definition );
295
+ * ```
296
+ *
297
+ * **Note**: Is requires the {@link #template} to be already set. See {@link #setTemplate}.
298
+ *
299
+ * @param definition Definition which extends the {@link #template}.
300
+ */
301
+ extendTemplate(definition) {
302
+ Template.extend(this.template, definition);
303
+ }
304
+ /**
305
+ * Recursively renders the view.
306
+ *
307
+ * Once the view is rendered:
308
+ * * the {@link #element} becomes an HTML element out of {@link #template},
309
+ * * the {@link #isRendered} flag is set `true`.
310
+ *
311
+ * **Note**: The children of the view:
312
+ * * defined directly in the {@link #template}
313
+ * * residing in collections created by the {@link #createCollection} method,
314
+ * * and added by {@link #registerChild}
315
+ * are also rendered in the process.
316
+ *
317
+ * In general, `render()` method is the right place to keep the code which refers to the
318
+ * {@link #element} and should be executed at the very beginning of the view's life cycle.
319
+ *
320
+ * It is possible to {@link module:ui/template~Template.extend} the {@link #template} before
321
+ * the view is rendered. To allow an early customization of the view (e.g. by its parent),
322
+ * such references should be done in `render()`.
323
+ *
324
+ * ```ts
325
+ * class SampleView extends View {
326
+ * constructor() {
327
+ * this.setTemplate( {
328
+ * // ...
329
+ * } );
330
+ * },
331
+ *
332
+ * render() {
333
+ * // View#element becomes available.
334
+ * super.render();
335
+ *
336
+ * // The "scroll" listener depends on #element.
337
+ * this.listenTo( window, 'scroll', () => {
338
+ * // A reference to #element would render the #template and make it non-extendable.
339
+ * if ( window.scrollY > 0 ) {
340
+ * this.element.scrollLeft = 100;
341
+ * } else {
342
+ * this.element.scrollLeft = 0;
343
+ * }
344
+ * } );
345
+ * }
346
+ * }
347
+ *
348
+ * const view = new SampleView();
349
+ *
350
+ * // Let's customize the view before it gets rendered.
351
+ * view.extendTemplate( {
352
+ * attributes: {
353
+ * class: [
354
+ * 'additional-class'
355
+ * ]
356
+ * }
357
+ * } );
358
+ *
359
+ * // Late rendering allows customization of the view.
360
+ * view.render();
361
+ * ```
362
+ */
363
+ render() {
364
+ if (this.isRendered) {
365
+ /**
366
+ * This View has already been rendered.
367
+ *
368
+ * @error ui-view-render-already-rendered
369
+ */
370
+ throw new CKEditorError('ui-view-render-already-rendered', this);
371
+ }
372
+ // Render #element of the view.
373
+ if (this.template) {
374
+ this.element = this.template.render();
375
+ // Auto–register view children from #template.
376
+ this.registerChild(this.template.getViews());
377
+ }
378
+ this.isRendered = true;
379
+ }
380
+ /**
381
+ * Recursively destroys the view instance and child views added by {@link #registerChild} and
382
+ * residing in collections created by the {@link #createCollection}.
383
+ *
384
+ * Destruction disables all event listeners:
385
+ * * created on the view, e.g. `view.on( 'event', () => {} )`,
386
+ * * defined in the {@link #template} for DOM events.
387
+ */
388
+ destroy() {
389
+ this.stopListening();
390
+ this._viewCollections.map(c => c.destroy());
391
+ // Template isn't obligatory for views.
392
+ if (this.template && this.template._revertData) {
393
+ this.template.revert(this.element);
394
+ }
395
+ }
396
+ }