@ckeditor/ckeditor5-font 38.1.0 → 38.1.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.
- package/build/font.js +1 -1
- package/build/font.js.map +1 -0
- package/package.json +3 -3
- package/src/augmentation.d.ts +58 -58
- package/src/augmentation.js +5 -5
- package/src/documentcolorcollection.d.ts +70 -70
- package/src/documentcolorcollection.js +42 -42
- package/src/font.d.ts +33 -33
- package/src/font.js +37 -37
- package/src/fontbackgroundcolor/fontbackgroundcolorcommand.d.ts +26 -26
- package/src/fontbackgroundcolor/fontbackgroundcolorcommand.js +25 -25
- package/src/fontbackgroundcolor/fontbackgroundcolorediting.d.ts +26 -26
- package/src/fontbackgroundcolor/fontbackgroundcolorediting.js +123 -123
- package/src/fontbackgroundcolor/fontbackgroundcolorui.d.ts +22 -22
- package/src/fontbackgroundcolor/fontbackgroundcolorui.js +33 -33
- package/src/fontbackgroundcolor.d.ts +30 -30
- package/src/fontbackgroundcolor.js +34 -34
- package/src/fontcolor/fontcolorcommand.d.ts +25 -25
- package/src/fontcolor/fontcolorcommand.js +24 -24
- package/src/fontcolor/fontcolorediting.d.ts +26 -26
- package/src/fontcolor/fontcolorediting.js +134 -134
- package/src/fontcolor/fontcolorui.d.ts +22 -22
- package/src/fontcolor/fontcolorui.js +33 -33
- package/src/fontcolor.d.ts +29 -29
- package/src/fontcolor.js +33 -33
- package/src/fontcommand.d.ts +48 -48
- package/src/fontcommand.js +79 -79
- package/src/fontconfig.d.ts +373 -373
- package/src/fontconfig.js +5 -5
- package/src/fontfamily/fontfamilycommand.d.ts +25 -25
- package/src/fontfamily/fontfamilycommand.js +24 -24
- package/src/fontfamily/fontfamilyediting.d.ts +39 -39
- package/src/fontfamily/fontfamilyediting.js +115 -115
- package/src/fontfamily/fontfamilyui.d.ts +30 -30
- package/src/fontfamily/fontfamilyui.js +114 -114
- package/src/fontfamily/utils.d.ts +15 -15
- package/src/fontfamily/utils.js +80 -80
- package/src/fontfamily.d.ts +29 -29
- package/src/fontfamily.js +33 -33
- package/src/fontsize/fontsizecommand.d.ts +25 -25
- package/src/fontsize/fontsizecommand.js +24 -24
- package/src/fontsize/fontsizeediting.d.ts +44 -44
- package/src/fontsize/fontsizeediting.js +165 -165
- package/src/fontsize/fontsizeui.d.ts +31 -31
- package/src/fontsize/fontsizeui.js +122 -122
- package/src/fontsize/utils.d.ts +12 -12
- package/src/fontsize/utils.js +166 -166
- package/src/fontsize.d.ts +37 -37
- package/src/fontsize.js +43 -43
- package/src/index.d.ts +27 -27
- package/src/index.js +21 -21
- package/src/ui/colortableview.d.ts +459 -459
- package/src/ui/colortableview.js +645 -645
- package/src/ui/colorui.d.ts +67 -67
- package/src/ui/colorui.js +128 -128
- package/src/utils.d.ts +79 -79
- package/src/utils.js +98 -98
package/src/ui/colortableview.js
CHANGED
|
@@ -1,645 +1,645 @@
|
|
|
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
|
-
/**
|
|
6
|
-
* @module font/ui/colortableview
|
|
7
|
-
*/
|
|
8
|
-
import { icons } from 'ckeditor5/src/core';
|
|
9
|
-
import { ButtonView, ColorGridView, ColorTileView, FocusCycler, LabelView, Template, View, ViewCollection, ColorPickerView, icons as uiIcons } from 'ckeditor5/src/ui';
|
|
10
|
-
import { FocusTracker, KeystrokeHandler } from 'ckeditor5/src/utils';
|
|
11
|
-
import DocumentColorCollection from '../documentcolorcollection';
|
|
12
|
-
import '../../theme/fontcolor.css';
|
|
13
|
-
/**
|
|
14
|
-
* A class which represents a view with the following sub–components:
|
|
15
|
-
*
|
|
16
|
-
* * A {@link module:font/ui/colortableview~ColorTableView#colorGridsPageView color grids component},
|
|
17
|
-
* * A {@link module:font/ui/colortableview~ColorTableView#colorPickerPageView color picker component}.
|
|
18
|
-
*/
|
|
19
|
-
export default class ColorTableView extends View {
|
|
20
|
-
/**
|
|
21
|
-
* Creates a view to be inserted as a child of {@link module:ui/dropdown/dropdownview~DropdownView}.
|
|
22
|
-
*
|
|
23
|
-
* @param locale The localization services instance.
|
|
24
|
-
* @param colors An array with definitions of colors to be displayed in the table.
|
|
25
|
-
* @param columns The number of columns in the color grid.
|
|
26
|
-
* @param removeButtonLabel The label of the button responsible for removing the color.
|
|
27
|
-
* @param colorPickerLabel The label of the button responsible for color picker appearing.
|
|
28
|
-
* @param documentColorsLabel The label for the section with the document colors.
|
|
29
|
-
* @param documentColorsCount The number of colors in the document colors section inside the color dropdown.
|
|
30
|
-
* @param colorPickerConfig The configuration of color picker feature.
|
|
31
|
-
*/
|
|
32
|
-
constructor(locale, { colors, columns, removeButtonLabel, documentColorsLabel, documentColorsCount, colorPickerLabel, colorPickerConfig }) {
|
|
33
|
-
super(locale);
|
|
34
|
-
this.items = this.createCollection();
|
|
35
|
-
this.focusTracker = new FocusTracker();
|
|
36
|
-
this.keystrokes = new KeystrokeHandler();
|
|
37
|
-
this._focusables = new ViewCollection();
|
|
38
|
-
this._colorPickerConfig = colorPickerConfig;
|
|
39
|
-
this._focusCycler = new FocusCycler({
|
|
40
|
-
focusables: this._focusables,
|
|
41
|
-
focusTracker: this.focusTracker,
|
|
42
|
-
keystrokeHandler: this.keystrokes,
|
|
43
|
-
actions: {
|
|
44
|
-
// Navigate list items backwards using the <kbd>Shift</kbd> + <kbd>Tab</kbd> keystroke.
|
|
45
|
-
focusPrevious: 'shift + tab',
|
|
46
|
-
// Navigate list items forwards using the <kbd>Tab</kbd> key.
|
|
47
|
-
focusNext: 'tab'
|
|
48
|
-
}
|
|
49
|
-
});
|
|
50
|
-
this.colorGridsPageView = new ColorGridsPageView(locale, {
|
|
51
|
-
colors, columns, removeButtonLabel, documentColorsLabel, documentColorsCount, colorPickerLabel,
|
|
52
|
-
focusTracker: this.focusTracker,
|
|
53
|
-
focusables: this._focusables
|
|
54
|
-
});
|
|
55
|
-
this.colorPickerPageView = new ColorPickerPageView(locale, {
|
|
56
|
-
focusables: this._focusables,
|
|
57
|
-
focusTracker: this.focusTracker,
|
|
58
|
-
keystrokes: this.keystrokes,
|
|
59
|
-
colorPickerConfig
|
|
60
|
-
});
|
|
61
|
-
this.set('_isColorGridsPageVisible', true);
|
|
62
|
-
this.set('_isColorPickerPageVisible', false);
|
|
63
|
-
this.set('selectedColor', undefined);
|
|
64
|
-
this.colorGridsPageView.bind('isVisible').to(this, '_isColorGridsPageVisible');
|
|
65
|
-
this.colorPickerPageView.bind('isVisible').to(this, '_isColorPickerPageVisible');
|
|
66
|
-
/**
|
|
67
|
-
* This is kind of bindings. Unfortunately we could not use this.bind() method because the same property
|
|
68
|
-
* can not be binded twice. So this is work around how to bind 'selectedColor' property between components.
|
|
69
|
-
*/
|
|
70
|
-
this.on('change:selectedColor', (evt, evtName, data) => {
|
|
71
|
-
this.colorGridsPageView.set('selectedColor', data);
|
|
72
|
-
this.colorPickerPageView.set('selectedColor', data);
|
|
73
|
-
});
|
|
74
|
-
this.colorGridsPageView.on('change:selectedColor', (evt, evtName, data) => {
|
|
75
|
-
this.set('selectedColor', data);
|
|
76
|
-
});
|
|
77
|
-
this.colorPickerPageView.on('change:selectedColor', (evt, evtName, data) => {
|
|
78
|
-
this.set('selectedColor', data);
|
|
79
|
-
});
|
|
80
|
-
this.setTemplate({
|
|
81
|
-
tag: 'div',
|
|
82
|
-
attributes: {
|
|
83
|
-
class: [
|
|
84
|
-
'ck',
|
|
85
|
-
'ck-color-table'
|
|
86
|
-
]
|
|
87
|
-
},
|
|
88
|
-
children: this.items
|
|
89
|
-
});
|
|
90
|
-
}
|
|
91
|
-
/**
|
|
92
|
-
* @inheritDoc
|
|
93
|
-
*/
|
|
94
|
-
render() {
|
|
95
|
-
super.render();
|
|
96
|
-
// Start listening for the keystrokes coming from #element.
|
|
97
|
-
this.keystrokes.listenTo(this.element);
|
|
98
|
-
}
|
|
99
|
-
/**
|
|
100
|
-
* @inheritDoc
|
|
101
|
-
*/
|
|
102
|
-
destroy() {
|
|
103
|
-
super.destroy();
|
|
104
|
-
this.focusTracker.destroy();
|
|
105
|
-
this.keystrokes.destroy();
|
|
106
|
-
}
|
|
107
|
-
/**
|
|
108
|
-
* Appends static and document color grid views.
|
|
109
|
-
*/
|
|
110
|
-
appendGrids() {
|
|
111
|
-
if (this.items.length) {
|
|
112
|
-
return;
|
|
113
|
-
}
|
|
114
|
-
this.items.add(this.colorGridsPageView);
|
|
115
|
-
this.colorGridsPageView.delegate('execute').to(this);
|
|
116
|
-
this.colorGridsPageView.delegate('showColorPicker').to(this);
|
|
117
|
-
}
|
|
118
|
-
/**
|
|
119
|
-
* Renders UI in dropdown. Which sub-components are rendered
|
|
120
|
-
* depends on the component configuration.
|
|
121
|
-
*/
|
|
122
|
-
appendUI() {
|
|
123
|
-
this.appendGrids();
|
|
124
|
-
if (this._colorPickerConfig) {
|
|
125
|
-
this._appendColorPicker();
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
/**
|
|
129
|
-
* Show "Color picker" and hide "Color grids".
|
|
130
|
-
*/
|
|
131
|
-
showColorPicker() {
|
|
132
|
-
if (!this.colorPickerPageView.colorPickerView) {
|
|
133
|
-
return;
|
|
134
|
-
}
|
|
135
|
-
this.set('_isColorPickerPageVisible', true);
|
|
136
|
-
this.colorPickerPageView.focus();
|
|
137
|
-
this.set('_isColorGridsPageVisible', false);
|
|
138
|
-
}
|
|
139
|
-
/**
|
|
140
|
-
* Show "Color grids" and hide "Color picker".
|
|
141
|
-
*/
|
|
142
|
-
showColorGrids() {
|
|
143
|
-
this.set('_isColorGridsPageVisible', true);
|
|
144
|
-
this.set('_isColorPickerPageVisible', false);
|
|
145
|
-
}
|
|
146
|
-
/**
|
|
147
|
-
* Focuses the first focusable element in {@link #items}.
|
|
148
|
-
*/
|
|
149
|
-
focus() {
|
|
150
|
-
this._focusCycler.focusFirst();
|
|
151
|
-
}
|
|
152
|
-
/**
|
|
153
|
-
* Focuses the last focusable element in {@link #items}.
|
|
154
|
-
*/
|
|
155
|
-
focusLast() {
|
|
156
|
-
this._focusCycler.focusLast();
|
|
157
|
-
}
|
|
158
|
-
/**
|
|
159
|
-
* Scans through the editor model and searches for text node attributes with the given attribute name.
|
|
160
|
-
* Found entries are set as document colors.
|
|
161
|
-
*
|
|
162
|
-
* All the previously stored document colors will be lost in the process.
|
|
163
|
-
*
|
|
164
|
-
* @param model The model used as a source to obtain the document colors.
|
|
165
|
-
* @param attributeName Determines the name of the related model's attribute for a given dropdown.
|
|
166
|
-
*/
|
|
167
|
-
updateDocumentColors(model, attributeName) {
|
|
168
|
-
this.colorGridsPageView.updateDocumentColors(model, attributeName);
|
|
169
|
-
}
|
|
170
|
-
/**
|
|
171
|
-
* Refreshes the state of the selected color in one or both {@link module:ui/colorgrid/colorgridview~ColorGridView}s
|
|
172
|
-
* available in the {@link module:font/ui/colortableview~ColorTableView}. It guarantees that the selection will occur only in one
|
|
173
|
-
* of them.
|
|
174
|
-
*/
|
|
175
|
-
updateSelectedColors() {
|
|
176
|
-
this.colorGridsPageView.updateSelectedColors();
|
|
177
|
-
}
|
|
178
|
-
/**
|
|
179
|
-
* Appends the color picker view.
|
|
180
|
-
*/
|
|
181
|
-
_appendColorPicker() {
|
|
182
|
-
if (this.items.length === 2) {
|
|
183
|
-
return;
|
|
184
|
-
}
|
|
185
|
-
this.items.add(this.colorPickerPageView);
|
|
186
|
-
if (this.colorGridsPageView.colorPickerButtonView) {
|
|
187
|
-
this.colorGridsPageView.colorPickerButtonView.on('execute', () => {
|
|
188
|
-
this.showColorPicker();
|
|
189
|
-
});
|
|
190
|
-
}
|
|
191
|
-
this.colorGridsPageView.addColorPickerButton();
|
|
192
|
-
this.colorPickerPageView.delegate('execute').to(this);
|
|
193
|
-
this.colorPickerPageView.delegate('cancel').to(this);
|
|
194
|
-
}
|
|
195
|
-
}
|
|
196
|
-
/**
|
|
197
|
-
* A class which represents a view with the following sub–components:
|
|
198
|
-
*
|
|
199
|
-
* * A remove color button,
|
|
200
|
-
* * A static {@link module:ui/colorgrid/colorgridview~ColorGridView} of colors defined in the configuration,
|
|
201
|
-
* * A dynamic {@link module:ui/colorgrid/colorgridview~ColorGridView} of colors used in the document.
|
|
202
|
-
* * If color picker is configured, the "Color Picker" button is visible too.
|
|
203
|
-
*/
|
|
204
|
-
class ColorGridsPageView extends View {
|
|
205
|
-
/**
|
|
206
|
-
* Creates a view to be inserted as a child of {@link module:ui/dropdown/dropdownview~DropdownView}.
|
|
207
|
-
*
|
|
208
|
-
* @param locale The localization services instance.
|
|
209
|
-
* @param colors An array with definitions of colors to be displayed in the table.
|
|
210
|
-
* @param columns The number of columns in the color grid.
|
|
211
|
-
* @param removeButtonLabel The label of the button responsible for removing the color.
|
|
212
|
-
* @param colorPickerLabel The label of the button responsible for color picker appearing.
|
|
213
|
-
* @param documentColorsLabel The label for the section with the document colors.
|
|
214
|
-
* @param documentColorsCount The number of colors in the document colors section inside the color dropdown.
|
|
215
|
-
* @param focusTracker Tracks information about the DOM focus in the list.
|
|
216
|
-
* @param focusables A collection of views that can be focused in the view.
|
|
217
|
-
*/
|
|
218
|
-
constructor(locale, { colors, columns, removeButtonLabel, documentColorsLabel, documentColorsCount, colorPickerLabel, focusTracker, focusables }) {
|
|
219
|
-
super(locale);
|
|
220
|
-
const bind = this.bindTemplate;
|
|
221
|
-
this.set('isVisible', true);
|
|
222
|
-
this.focusTracker = focusTracker;
|
|
223
|
-
this.items = this.createCollection();
|
|
224
|
-
this.colorDefinitions = colors;
|
|
225
|
-
this.columns = columns;
|
|
226
|
-
this.documentColors = new DocumentColorCollection();
|
|
227
|
-
this.documentColorsCount = documentColorsCount;
|
|
228
|
-
this._focusables = focusables;
|
|
229
|
-
this._removeButtonLabel = removeButtonLabel;
|
|
230
|
-
this._colorPickerLabel = colorPickerLabel;
|
|
231
|
-
this._documentColorsLabel = documentColorsLabel;
|
|
232
|
-
this.setTemplate({
|
|
233
|
-
tag: 'div',
|
|
234
|
-
attributes: {
|
|
235
|
-
class: [
|
|
236
|
-
'ck-color-grids-page-view',
|
|
237
|
-
bind.if('isVisible', 'ck-hidden', value => !value)
|
|
238
|
-
]
|
|
239
|
-
},
|
|
240
|
-
children: this.items
|
|
241
|
-
});
|
|
242
|
-
this.removeColorButtonView = this._createRemoveColorButton();
|
|
243
|
-
this.items.add(this.removeColorButtonView);
|
|
244
|
-
}
|
|
245
|
-
/**
|
|
246
|
-
* Scans through the editor model and searches for text node attributes with the given attribute name.
|
|
247
|
-
* Found entries are set as document colors.
|
|
248
|
-
*
|
|
249
|
-
* All the previously stored document colors will be lost in the process.
|
|
250
|
-
*
|
|
251
|
-
* @param model The model used as a source to obtain the document colors.
|
|
252
|
-
* @param attributeName Determines the name of the related model's attribute for a given dropdown.
|
|
253
|
-
*/
|
|
254
|
-
updateDocumentColors(model, attributeName) {
|
|
255
|
-
const document = model.document;
|
|
256
|
-
const maxCount = this.documentColorsCount;
|
|
257
|
-
this.documentColors.clear();
|
|
258
|
-
for (const rootName of document.getRootNames()) {
|
|
259
|
-
const root = document.getRoot(rootName);
|
|
260
|
-
const range = model.createRangeIn(root);
|
|
261
|
-
for (const node of range.getItems()) {
|
|
262
|
-
if (node.is('$textProxy') && node.hasAttribute(attributeName)) {
|
|
263
|
-
this._addColorToDocumentColors(node.getAttribute(attributeName));
|
|
264
|
-
if (this.documentColors.length >= maxCount) {
|
|
265
|
-
return;
|
|
266
|
-
}
|
|
267
|
-
}
|
|
268
|
-
}
|
|
269
|
-
}
|
|
270
|
-
}
|
|
271
|
-
/**
|
|
272
|
-
* Refreshes the state of the selected color in one or both {@link module:ui/colorgrid/colorgridview~ColorGridView}s
|
|
273
|
-
* available in the {@link module:font/ui/colortableview~ColorTableView}. It guarantees that the selection will occur only in one
|
|
274
|
-
* of them.
|
|
275
|
-
*/
|
|
276
|
-
updateSelectedColors() {
|
|
277
|
-
const documentColorsGrid = this.documentColorsGrid;
|
|
278
|
-
const staticColorsGrid = this.staticColorsGrid;
|
|
279
|
-
const selectedColor = this.selectedColor;
|
|
280
|
-
staticColorsGrid.selectedColor = selectedColor;
|
|
281
|
-
if (documentColorsGrid) {
|
|
282
|
-
documentColorsGrid.selectedColor = selectedColor;
|
|
283
|
-
}
|
|
284
|
-
}
|
|
285
|
-
/**
|
|
286
|
-
* @inheritDoc
|
|
287
|
-
*/
|
|
288
|
-
render() {
|
|
289
|
-
super.render();
|
|
290
|
-
this.staticColorsGrid = this._createStaticColorsGrid();
|
|
291
|
-
this.items.add(this.staticColorsGrid);
|
|
292
|
-
if (this.documentColorsCount) {
|
|
293
|
-
// Create a label for document colors.
|
|
294
|
-
const bind = Template.bind(this.documentColors, this.documentColors);
|
|
295
|
-
const label = new LabelView(this.locale);
|
|
296
|
-
label.text = this._documentColorsLabel;
|
|
297
|
-
label.extendTemplate({
|
|
298
|
-
attributes: {
|
|
299
|
-
class: [
|
|
300
|
-
'ck',
|
|
301
|
-
'ck-color-grid__label',
|
|
302
|
-
bind.if('isEmpty', 'ck-hidden')
|
|
303
|
-
]
|
|
304
|
-
}
|
|
305
|
-
});
|
|
306
|
-
this.items.add(label);
|
|
307
|
-
this.documentColorsGrid = this._createDocumentColorsGrid();
|
|
308
|
-
this.items.add(this.documentColorsGrid);
|
|
309
|
-
}
|
|
310
|
-
this._createColorPickerButton();
|
|
311
|
-
this._addColorTablesElementsToFocusTracker();
|
|
312
|
-
this.focus();
|
|
313
|
-
}
|
|
314
|
-
/**
|
|
315
|
-
* Focuses the component.
|
|
316
|
-
*/
|
|
317
|
-
focus() {
|
|
318
|
-
this.removeColorButtonView.focus();
|
|
319
|
-
}
|
|
320
|
-
/**
|
|
321
|
-
* @inheritDoc
|
|
322
|
-
*/
|
|
323
|
-
destroy() {
|
|
324
|
-
super.destroy();
|
|
325
|
-
}
|
|
326
|
-
/**
|
|
327
|
-
* Handles displaying the color picker button (if it was previously created) and making it focusable.
|
|
328
|
-
*/
|
|
329
|
-
addColorPickerButton() {
|
|
330
|
-
if (this.colorPickerButtonView) {
|
|
331
|
-
this.items.add(this.colorPickerButtonView);
|
|
332
|
-
this.focusTracker.add(this.colorPickerButtonView.element);
|
|
333
|
-
this._focusables.add(this.colorPickerButtonView);
|
|
334
|
-
}
|
|
335
|
-
}
|
|
336
|
-
/**
|
|
337
|
-
* Adds color table elements to focus tracker.
|
|
338
|
-
*/
|
|
339
|
-
_addColorTablesElementsToFocusTracker() {
|
|
340
|
-
this.focusTracker.add(this.removeColorButtonView.element);
|
|
341
|
-
this._focusables.add(this.removeColorButtonView);
|
|
342
|
-
if (this.staticColorsGrid) {
|
|
343
|
-
this.focusTracker.add(this.staticColorsGrid.element);
|
|
344
|
-
this._focusables.add(this.staticColorsGrid);
|
|
345
|
-
}
|
|
346
|
-
if (this.documentColorsGrid) {
|
|
347
|
-
this.focusTracker.add(this.documentColorsGrid.element);
|
|
348
|
-
this._focusables.add(this.documentColorsGrid);
|
|
349
|
-
}
|
|
350
|
-
}
|
|
351
|
-
/**
|
|
352
|
-
* Creates the button responsible for displaying the color picker component.
|
|
353
|
-
*/
|
|
354
|
-
_createColorPickerButton() {
|
|
355
|
-
this.colorPickerButtonView = new ButtonView();
|
|
356
|
-
this.colorPickerButtonView.set({
|
|
357
|
-
label: this._colorPickerLabel,
|
|
358
|
-
withText: true,
|
|
359
|
-
icon: uiIcons.colorPaletteIcon,
|
|
360
|
-
class: 'ck-color-table__color-picker'
|
|
361
|
-
});
|
|
362
|
-
this.colorPickerButtonView.on('execute', () => {
|
|
363
|
-
this.fire('showColorPicker');
|
|
364
|
-
});
|
|
365
|
-
}
|
|
366
|
-
/**
|
|
367
|
-
* Adds the remove color button as a child of the current view.
|
|
368
|
-
*/
|
|
369
|
-
_createRemoveColorButton() {
|
|
370
|
-
const buttonView = new ButtonView();
|
|
371
|
-
buttonView.set({
|
|
372
|
-
withText: true,
|
|
373
|
-
icon: icons.eraser,
|
|
374
|
-
label: this._removeButtonLabel
|
|
375
|
-
});
|
|
376
|
-
buttonView.class = 'ck-color-table__remove-color';
|
|
377
|
-
buttonView.on('execute', () => {
|
|
378
|
-
this.fire('execute', {
|
|
379
|
-
value: null,
|
|
380
|
-
source: 'removeColorButton'
|
|
381
|
-
});
|
|
382
|
-
});
|
|
383
|
-
buttonView.render();
|
|
384
|
-
return buttonView;
|
|
385
|
-
}
|
|
386
|
-
/**
|
|
387
|
-
* Creates a static color table grid based on the editor configuration.
|
|
388
|
-
*/
|
|
389
|
-
_createStaticColorsGrid() {
|
|
390
|
-
const colorGrid = new ColorGridView(this.locale, {
|
|
391
|
-
colorDefinitions: this.colorDefinitions,
|
|
392
|
-
columns: this.columns
|
|
393
|
-
});
|
|
394
|
-
colorGrid.on('execute', (evt, data) => {
|
|
395
|
-
this.fire('execute', {
|
|
396
|
-
value: data.value,
|
|
397
|
-
source: 'staticColorsGrid'
|
|
398
|
-
});
|
|
399
|
-
});
|
|
400
|
-
return colorGrid;
|
|
401
|
-
}
|
|
402
|
-
/**
|
|
403
|
-
* Creates the document colors section view and binds it to {@link #documentColors}.
|
|
404
|
-
*/
|
|
405
|
-
_createDocumentColorsGrid() {
|
|
406
|
-
const bind = Template.bind(this.documentColors, this.documentColors);
|
|
407
|
-
const documentColorsGrid = new ColorGridView(this.locale, {
|
|
408
|
-
columns: this.columns
|
|
409
|
-
});
|
|
410
|
-
documentColorsGrid.extendTemplate({
|
|
411
|
-
attributes: {
|
|
412
|
-
class: bind.if('isEmpty', 'ck-hidden')
|
|
413
|
-
}
|
|
414
|
-
});
|
|
415
|
-
documentColorsGrid.items.bindTo(this.documentColors).using(colorObj => {
|
|
416
|
-
const colorTile = new ColorTileView();
|
|
417
|
-
colorTile.set({
|
|
418
|
-
color: colorObj.color,
|
|
419
|
-
hasBorder: colorObj.options && colorObj.options.hasBorder
|
|
420
|
-
});
|
|
421
|
-
if (colorObj.label) {
|
|
422
|
-
colorTile.set({
|
|
423
|
-
label: colorObj.label,
|
|
424
|
-
tooltip: true
|
|
425
|
-
});
|
|
426
|
-
}
|
|
427
|
-
colorTile.on('execute', () => {
|
|
428
|
-
this.fire('execute', {
|
|
429
|
-
value: colorObj.color,
|
|
430
|
-
source: 'documentColorsGrid'
|
|
431
|
-
});
|
|
432
|
-
});
|
|
433
|
-
return colorTile;
|
|
434
|
-
});
|
|
435
|
-
// Selected color should be cleared when document colors became empty.
|
|
436
|
-
this.documentColors.on('change:isEmpty', (evt, name, val) => {
|
|
437
|
-
if (val) {
|
|
438
|
-
documentColorsGrid.selectedColor = null;
|
|
439
|
-
}
|
|
440
|
-
});
|
|
441
|
-
return documentColorsGrid;
|
|
442
|
-
}
|
|
443
|
-
/**
|
|
444
|
-
* Adds a given color to the document colors list. If possible, the method will attempt to use
|
|
445
|
-
* data from the {@link #colorDefinitions} (label, color options).
|
|
446
|
-
*
|
|
447
|
-
* @param color A string that stores the value of the recently applied color.
|
|
448
|
-
*/
|
|
449
|
-
_addColorToDocumentColors(color) {
|
|
450
|
-
const predefinedColor = this.colorDefinitions
|
|
451
|
-
.find(definition => definition.color === color);
|
|
452
|
-
if (!predefinedColor) {
|
|
453
|
-
this.documentColors.add({
|
|
454
|
-
color,
|
|
455
|
-
label: color,
|
|
456
|
-
options: {
|
|
457
|
-
hasBorder: false
|
|
458
|
-
}
|
|
459
|
-
});
|
|
460
|
-
}
|
|
461
|
-
else {
|
|
462
|
-
this.documentColors.add(Object.assign({}, predefinedColor));
|
|
463
|
-
}
|
|
464
|
-
}
|
|
465
|
-
}
|
|
466
|
-
/**
|
|
467
|
-
* A class which represents a color picker component view with the following sub–components:
|
|
468
|
-
*
|
|
469
|
-
* * Color picker saturation and hue sliders,
|
|
470
|
-
* * Input accepting colors in HEX format,
|
|
471
|
-
* * "Save" and "Cancel" action buttons.
|
|
472
|
-
*/
|
|
473
|
-
class ColorPickerPageView extends View {
|
|
474
|
-
/**
|
|
475
|
-
* @param locale The localization services instance.
|
|
476
|
-
* @param focusTracker Tracks information about the DOM focus in the list.
|
|
477
|
-
* @param focusables A collection of views that can be focused in the view..
|
|
478
|
-
* @param keystrokes An instance of the {@link module:utils/keystrokehandler~KeystrokeHandler}.
|
|
479
|
-
* @param colorPickerConfig The configuration of color picker feature.
|
|
480
|
-
*/
|
|
481
|
-
constructor(locale, { focusTracker, focusables, keystrokes, colorPickerConfig }) {
|
|
482
|
-
super(locale);
|
|
483
|
-
this.items = this.createCollection();
|
|
484
|
-
this.focusTracker = focusTracker;
|
|
485
|
-
this.keystrokes = keystrokes;
|
|
486
|
-
this.set('isVisible', false);
|
|
487
|
-
this.set('selectedColor', undefined);
|
|
488
|
-
this._focusables = focusables;
|
|
489
|
-
this._pickerConfig = colorPickerConfig;
|
|
490
|
-
const bind = this.bindTemplate;
|
|
491
|
-
const { saveButtonView, cancelButtonView } = this._createActionButtons();
|
|
492
|
-
this.saveButtonView = saveButtonView;
|
|
493
|
-
this.cancelButtonView = cancelButtonView;
|
|
494
|
-
this.actionBarView = this._createActionBarView({ saveButtonView, cancelButtonView });
|
|
495
|
-
this.setTemplate({
|
|
496
|
-
tag: 'div',
|
|
497
|
-
attributes: {
|
|
498
|
-
class: [
|
|
499
|
-
'ck-color-picker-page-view',
|
|
500
|
-
bind.if('isVisible', 'ck-hidden', value => !value)
|
|
501
|
-
]
|
|
502
|
-
},
|
|
503
|
-
children: this.items
|
|
504
|
-
});
|
|
505
|
-
}
|
|
506
|
-
/**
|
|
507
|
-
* @inheritDoc
|
|
508
|
-
*/
|
|
509
|
-
render() {
|
|
510
|
-
super.render();
|
|
511
|
-
const colorPickerView = new ColorPickerView(this.locale, this._pickerConfig);
|
|
512
|
-
this.colorPickerView = colorPickerView;
|
|
513
|
-
this.colorPickerView.render();
|
|
514
|
-
if (this.selectedColor) {
|
|
515
|
-
colorPickerView.color = this.selectedColor;
|
|
516
|
-
}
|
|
517
|
-
this.listenTo(this, 'change:selectedColor', (evt, name, value) => {
|
|
518
|
-
colorPickerView.color = value;
|
|
519
|
-
});
|
|
520
|
-
this.items.add(this.colorPickerView);
|
|
521
|
-
this.items.add(this.actionBarView);
|
|
522
|
-
this._addColorPickersElementsToFocusTracker();
|
|
523
|
-
this._stopPropagationOnArrowsKeys();
|
|
524
|
-
this._executeOnEnterPress();
|
|
525
|
-
this._executeUponColorChange();
|
|
526
|
-
}
|
|
527
|
-
/**
|
|
528
|
-
* @inheritDoc
|
|
529
|
-
*/
|
|
530
|
-
destroy() {
|
|
531
|
-
super.destroy();
|
|
532
|
-
}
|
|
533
|
-
/**
|
|
534
|
-
* Focuses the color picker.
|
|
535
|
-
*/
|
|
536
|
-
focus() {
|
|
537
|
-
this.colorPickerView.focus();
|
|
538
|
-
}
|
|
539
|
-
/**
|
|
540
|
-
* When color picker is focused and "enter" is pressed it executes command.
|
|
541
|
-
*/
|
|
542
|
-
_executeOnEnterPress() {
|
|
543
|
-
this.keystrokes.set('enter', evt => {
|
|
544
|
-
if (this.isVisible && this.focusTracker.focusedElement !== this.cancelButtonView.element) {
|
|
545
|
-
this.fire('execute', {
|
|
546
|
-
value: this.selectedColor
|
|
547
|
-
});
|
|
548
|
-
evt.stopPropagation();
|
|
549
|
-
evt.preventDefault();
|
|
550
|
-
}
|
|
551
|
-
});
|
|
552
|
-
}
|
|
553
|
-
/**
|
|
554
|
-
* Removes default behavior of arrow keys in dropdown.
|
|
555
|
-
*/
|
|
556
|
-
_stopPropagationOnArrowsKeys() {
|
|
557
|
-
const stopPropagation = (data) => data.stopPropagation();
|
|
558
|
-
this.keystrokes.set('arrowright', stopPropagation);
|
|
559
|
-
this.keystrokes.set('arrowleft', stopPropagation);
|
|
560
|
-
this.keystrokes.set('arrowup', stopPropagation);
|
|
561
|
-
this.keystrokes.set('arrowdown', stopPropagation);
|
|
562
|
-
}
|
|
563
|
-
/**
|
|
564
|
-
* Adds color picker elements to focus tracker.
|
|
565
|
-
*/
|
|
566
|
-
_addColorPickersElementsToFocusTracker() {
|
|
567
|
-
for (const slider of this.colorPickerView.slidersView) {
|
|
568
|
-
this.focusTracker.add(slider.element);
|
|
569
|
-
this._focusables.add(slider);
|
|
570
|
-
}
|
|
571
|
-
this.focusTracker.add(this.colorPickerView.hexInputRow.children.get(1).element);
|
|
572
|
-
this._focusables.add(this.colorPickerView.hexInputRow.children.get(1));
|
|
573
|
-
this.focusTracker.add(this.saveButtonView.element);
|
|
574
|
-
this._focusables.add(this.saveButtonView);
|
|
575
|
-
this.focusTracker.add(this.cancelButtonView.element);
|
|
576
|
-
this._focusables.add(this.cancelButtonView);
|
|
577
|
-
}
|
|
578
|
-
/**
|
|
579
|
-
* Creates bar containing "Save" and "Cancel" buttons.
|
|
580
|
-
*/
|
|
581
|
-
_createActionBarView({ saveButtonView, cancelButtonView }) {
|
|
582
|
-
const actionBarRow = new View();
|
|
583
|
-
const children = this.createCollection();
|
|
584
|
-
children.add(saveButtonView);
|
|
585
|
-
children.add(cancelButtonView);
|
|
586
|
-
actionBarRow.setTemplate({
|
|
587
|
-
tag: 'div',
|
|
588
|
-
attributes: {
|
|
589
|
-
class: [
|
|
590
|
-
'ck',
|
|
591
|
-
'ck-color-table_action-bar'
|
|
592
|
-
]
|
|
593
|
-
},
|
|
594
|
-
children
|
|
595
|
-
});
|
|
596
|
-
return actionBarRow;
|
|
597
|
-
}
|
|
598
|
-
/**
|
|
599
|
-
* Creates "Save" and "Cancel" buttons.
|
|
600
|
-
*/
|
|
601
|
-
_createActionButtons() {
|
|
602
|
-
const locale = this.locale;
|
|
603
|
-
const t = locale.t;
|
|
604
|
-
const saveButtonView = new ButtonView(locale);
|
|
605
|
-
const cancelButtonView = new ButtonView(locale);
|
|
606
|
-
saveButtonView.set({
|
|
607
|
-
icon: icons.check,
|
|
608
|
-
class: 'ck-button-save',
|
|
609
|
-
withText: false,
|
|
610
|
-
label: t('Accept'),
|
|
611
|
-
type: 'button'
|
|
612
|
-
});
|
|
613
|
-
cancelButtonView.set({
|
|
614
|
-
icon: icons.cancel,
|
|
615
|
-
class: 'ck-button-cancel',
|
|
616
|
-
withText: false,
|
|
617
|
-
label: t('Cancel')
|
|
618
|
-
});
|
|
619
|
-
saveButtonView.on('execute', () => {
|
|
620
|
-
this.fire('execute', {
|
|
621
|
-
source: 'saveButton',
|
|
622
|
-
value: this.selectedColor
|
|
623
|
-
});
|
|
624
|
-
});
|
|
625
|
-
cancelButtonView.on('execute', () => {
|
|
626
|
-
this.fire('cancel');
|
|
627
|
-
});
|
|
628
|
-
return {
|
|
629
|
-
saveButtonView, cancelButtonView
|
|
630
|
-
};
|
|
631
|
-
}
|
|
632
|
-
/**
|
|
633
|
-
* Fires the `execute` event if color in color picker changed.
|
|
634
|
-
*
|
|
635
|
-
* @fires execute
|
|
636
|
-
*/
|
|
637
|
-
_executeUponColorChange() {
|
|
638
|
-
this.colorPickerView.on('change:color', (evt, evtName, newValue) => {
|
|
639
|
-
this.fire('execute', {
|
|
640
|
-
value: newValue,
|
|
641
|
-
source: 'colorPicker'
|
|
642
|
-
});
|
|
643
|
-
});
|
|
644
|
-
}
|
|
645
|
-
}
|
|
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
|
+
/**
|
|
6
|
+
* @module font/ui/colortableview
|
|
7
|
+
*/
|
|
8
|
+
import { icons } from 'ckeditor5/src/core';
|
|
9
|
+
import { ButtonView, ColorGridView, ColorTileView, FocusCycler, LabelView, Template, View, ViewCollection, ColorPickerView, icons as uiIcons } from 'ckeditor5/src/ui';
|
|
10
|
+
import { FocusTracker, KeystrokeHandler } from 'ckeditor5/src/utils';
|
|
11
|
+
import DocumentColorCollection from '../documentcolorcollection';
|
|
12
|
+
import '../../theme/fontcolor.css';
|
|
13
|
+
/**
|
|
14
|
+
* A class which represents a view with the following sub–components:
|
|
15
|
+
*
|
|
16
|
+
* * A {@link module:font/ui/colortableview~ColorTableView#colorGridsPageView color grids component},
|
|
17
|
+
* * A {@link module:font/ui/colortableview~ColorTableView#colorPickerPageView color picker component}.
|
|
18
|
+
*/
|
|
19
|
+
export default class ColorTableView extends View {
|
|
20
|
+
/**
|
|
21
|
+
* Creates a view to be inserted as a child of {@link module:ui/dropdown/dropdownview~DropdownView}.
|
|
22
|
+
*
|
|
23
|
+
* @param locale The localization services instance.
|
|
24
|
+
* @param colors An array with definitions of colors to be displayed in the table.
|
|
25
|
+
* @param columns The number of columns in the color grid.
|
|
26
|
+
* @param removeButtonLabel The label of the button responsible for removing the color.
|
|
27
|
+
* @param colorPickerLabel The label of the button responsible for color picker appearing.
|
|
28
|
+
* @param documentColorsLabel The label for the section with the document colors.
|
|
29
|
+
* @param documentColorsCount The number of colors in the document colors section inside the color dropdown.
|
|
30
|
+
* @param colorPickerConfig The configuration of color picker feature.
|
|
31
|
+
*/
|
|
32
|
+
constructor(locale, { colors, columns, removeButtonLabel, documentColorsLabel, documentColorsCount, colorPickerLabel, colorPickerConfig }) {
|
|
33
|
+
super(locale);
|
|
34
|
+
this.items = this.createCollection();
|
|
35
|
+
this.focusTracker = new FocusTracker();
|
|
36
|
+
this.keystrokes = new KeystrokeHandler();
|
|
37
|
+
this._focusables = new ViewCollection();
|
|
38
|
+
this._colorPickerConfig = colorPickerConfig;
|
|
39
|
+
this._focusCycler = new FocusCycler({
|
|
40
|
+
focusables: this._focusables,
|
|
41
|
+
focusTracker: this.focusTracker,
|
|
42
|
+
keystrokeHandler: this.keystrokes,
|
|
43
|
+
actions: {
|
|
44
|
+
// Navigate list items backwards using the <kbd>Shift</kbd> + <kbd>Tab</kbd> keystroke.
|
|
45
|
+
focusPrevious: 'shift + tab',
|
|
46
|
+
// Navigate list items forwards using the <kbd>Tab</kbd> key.
|
|
47
|
+
focusNext: 'tab'
|
|
48
|
+
}
|
|
49
|
+
});
|
|
50
|
+
this.colorGridsPageView = new ColorGridsPageView(locale, {
|
|
51
|
+
colors, columns, removeButtonLabel, documentColorsLabel, documentColorsCount, colorPickerLabel,
|
|
52
|
+
focusTracker: this.focusTracker,
|
|
53
|
+
focusables: this._focusables
|
|
54
|
+
});
|
|
55
|
+
this.colorPickerPageView = new ColorPickerPageView(locale, {
|
|
56
|
+
focusables: this._focusables,
|
|
57
|
+
focusTracker: this.focusTracker,
|
|
58
|
+
keystrokes: this.keystrokes,
|
|
59
|
+
colorPickerConfig
|
|
60
|
+
});
|
|
61
|
+
this.set('_isColorGridsPageVisible', true);
|
|
62
|
+
this.set('_isColorPickerPageVisible', false);
|
|
63
|
+
this.set('selectedColor', undefined);
|
|
64
|
+
this.colorGridsPageView.bind('isVisible').to(this, '_isColorGridsPageVisible');
|
|
65
|
+
this.colorPickerPageView.bind('isVisible').to(this, '_isColorPickerPageVisible');
|
|
66
|
+
/**
|
|
67
|
+
* This is kind of bindings. Unfortunately we could not use this.bind() method because the same property
|
|
68
|
+
* can not be binded twice. So this is work around how to bind 'selectedColor' property between components.
|
|
69
|
+
*/
|
|
70
|
+
this.on('change:selectedColor', (evt, evtName, data) => {
|
|
71
|
+
this.colorGridsPageView.set('selectedColor', data);
|
|
72
|
+
this.colorPickerPageView.set('selectedColor', data);
|
|
73
|
+
});
|
|
74
|
+
this.colorGridsPageView.on('change:selectedColor', (evt, evtName, data) => {
|
|
75
|
+
this.set('selectedColor', data);
|
|
76
|
+
});
|
|
77
|
+
this.colorPickerPageView.on('change:selectedColor', (evt, evtName, data) => {
|
|
78
|
+
this.set('selectedColor', data);
|
|
79
|
+
});
|
|
80
|
+
this.setTemplate({
|
|
81
|
+
tag: 'div',
|
|
82
|
+
attributes: {
|
|
83
|
+
class: [
|
|
84
|
+
'ck',
|
|
85
|
+
'ck-color-table'
|
|
86
|
+
]
|
|
87
|
+
},
|
|
88
|
+
children: this.items
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* @inheritDoc
|
|
93
|
+
*/
|
|
94
|
+
render() {
|
|
95
|
+
super.render();
|
|
96
|
+
// Start listening for the keystrokes coming from #element.
|
|
97
|
+
this.keystrokes.listenTo(this.element);
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* @inheritDoc
|
|
101
|
+
*/
|
|
102
|
+
destroy() {
|
|
103
|
+
super.destroy();
|
|
104
|
+
this.focusTracker.destroy();
|
|
105
|
+
this.keystrokes.destroy();
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Appends static and document color grid views.
|
|
109
|
+
*/
|
|
110
|
+
appendGrids() {
|
|
111
|
+
if (this.items.length) {
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
114
|
+
this.items.add(this.colorGridsPageView);
|
|
115
|
+
this.colorGridsPageView.delegate('execute').to(this);
|
|
116
|
+
this.colorGridsPageView.delegate('showColorPicker').to(this);
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Renders UI in dropdown. Which sub-components are rendered
|
|
120
|
+
* depends on the component configuration.
|
|
121
|
+
*/
|
|
122
|
+
appendUI() {
|
|
123
|
+
this.appendGrids();
|
|
124
|
+
if (this._colorPickerConfig) {
|
|
125
|
+
this._appendColorPicker();
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Show "Color picker" and hide "Color grids".
|
|
130
|
+
*/
|
|
131
|
+
showColorPicker() {
|
|
132
|
+
if (!this.colorPickerPageView.colorPickerView) {
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
135
|
+
this.set('_isColorPickerPageVisible', true);
|
|
136
|
+
this.colorPickerPageView.focus();
|
|
137
|
+
this.set('_isColorGridsPageVisible', false);
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Show "Color grids" and hide "Color picker".
|
|
141
|
+
*/
|
|
142
|
+
showColorGrids() {
|
|
143
|
+
this.set('_isColorGridsPageVisible', true);
|
|
144
|
+
this.set('_isColorPickerPageVisible', false);
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Focuses the first focusable element in {@link #items}.
|
|
148
|
+
*/
|
|
149
|
+
focus() {
|
|
150
|
+
this._focusCycler.focusFirst();
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Focuses the last focusable element in {@link #items}.
|
|
154
|
+
*/
|
|
155
|
+
focusLast() {
|
|
156
|
+
this._focusCycler.focusLast();
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Scans through the editor model and searches for text node attributes with the given attribute name.
|
|
160
|
+
* Found entries are set as document colors.
|
|
161
|
+
*
|
|
162
|
+
* All the previously stored document colors will be lost in the process.
|
|
163
|
+
*
|
|
164
|
+
* @param model The model used as a source to obtain the document colors.
|
|
165
|
+
* @param attributeName Determines the name of the related model's attribute for a given dropdown.
|
|
166
|
+
*/
|
|
167
|
+
updateDocumentColors(model, attributeName) {
|
|
168
|
+
this.colorGridsPageView.updateDocumentColors(model, attributeName);
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* Refreshes the state of the selected color in one or both {@link module:ui/colorgrid/colorgridview~ColorGridView}s
|
|
172
|
+
* available in the {@link module:font/ui/colortableview~ColorTableView}. It guarantees that the selection will occur only in one
|
|
173
|
+
* of them.
|
|
174
|
+
*/
|
|
175
|
+
updateSelectedColors() {
|
|
176
|
+
this.colorGridsPageView.updateSelectedColors();
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* Appends the color picker view.
|
|
180
|
+
*/
|
|
181
|
+
_appendColorPicker() {
|
|
182
|
+
if (this.items.length === 2) {
|
|
183
|
+
return;
|
|
184
|
+
}
|
|
185
|
+
this.items.add(this.colorPickerPageView);
|
|
186
|
+
if (this.colorGridsPageView.colorPickerButtonView) {
|
|
187
|
+
this.colorGridsPageView.colorPickerButtonView.on('execute', () => {
|
|
188
|
+
this.showColorPicker();
|
|
189
|
+
});
|
|
190
|
+
}
|
|
191
|
+
this.colorGridsPageView.addColorPickerButton();
|
|
192
|
+
this.colorPickerPageView.delegate('execute').to(this);
|
|
193
|
+
this.colorPickerPageView.delegate('cancel').to(this);
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
/**
|
|
197
|
+
* A class which represents a view with the following sub–components:
|
|
198
|
+
*
|
|
199
|
+
* * A remove color button,
|
|
200
|
+
* * A static {@link module:ui/colorgrid/colorgridview~ColorGridView} of colors defined in the configuration,
|
|
201
|
+
* * A dynamic {@link module:ui/colorgrid/colorgridview~ColorGridView} of colors used in the document.
|
|
202
|
+
* * If color picker is configured, the "Color Picker" button is visible too.
|
|
203
|
+
*/
|
|
204
|
+
class ColorGridsPageView extends View {
|
|
205
|
+
/**
|
|
206
|
+
* Creates a view to be inserted as a child of {@link module:ui/dropdown/dropdownview~DropdownView}.
|
|
207
|
+
*
|
|
208
|
+
* @param locale The localization services instance.
|
|
209
|
+
* @param colors An array with definitions of colors to be displayed in the table.
|
|
210
|
+
* @param columns The number of columns in the color grid.
|
|
211
|
+
* @param removeButtonLabel The label of the button responsible for removing the color.
|
|
212
|
+
* @param colorPickerLabel The label of the button responsible for color picker appearing.
|
|
213
|
+
* @param documentColorsLabel The label for the section with the document colors.
|
|
214
|
+
* @param documentColorsCount The number of colors in the document colors section inside the color dropdown.
|
|
215
|
+
* @param focusTracker Tracks information about the DOM focus in the list.
|
|
216
|
+
* @param focusables A collection of views that can be focused in the view.
|
|
217
|
+
*/
|
|
218
|
+
constructor(locale, { colors, columns, removeButtonLabel, documentColorsLabel, documentColorsCount, colorPickerLabel, focusTracker, focusables }) {
|
|
219
|
+
super(locale);
|
|
220
|
+
const bind = this.bindTemplate;
|
|
221
|
+
this.set('isVisible', true);
|
|
222
|
+
this.focusTracker = focusTracker;
|
|
223
|
+
this.items = this.createCollection();
|
|
224
|
+
this.colorDefinitions = colors;
|
|
225
|
+
this.columns = columns;
|
|
226
|
+
this.documentColors = new DocumentColorCollection();
|
|
227
|
+
this.documentColorsCount = documentColorsCount;
|
|
228
|
+
this._focusables = focusables;
|
|
229
|
+
this._removeButtonLabel = removeButtonLabel;
|
|
230
|
+
this._colorPickerLabel = colorPickerLabel;
|
|
231
|
+
this._documentColorsLabel = documentColorsLabel;
|
|
232
|
+
this.setTemplate({
|
|
233
|
+
tag: 'div',
|
|
234
|
+
attributes: {
|
|
235
|
+
class: [
|
|
236
|
+
'ck-color-grids-page-view',
|
|
237
|
+
bind.if('isVisible', 'ck-hidden', value => !value)
|
|
238
|
+
]
|
|
239
|
+
},
|
|
240
|
+
children: this.items
|
|
241
|
+
});
|
|
242
|
+
this.removeColorButtonView = this._createRemoveColorButton();
|
|
243
|
+
this.items.add(this.removeColorButtonView);
|
|
244
|
+
}
|
|
245
|
+
/**
|
|
246
|
+
* Scans through the editor model and searches for text node attributes with the given attribute name.
|
|
247
|
+
* Found entries are set as document colors.
|
|
248
|
+
*
|
|
249
|
+
* All the previously stored document colors will be lost in the process.
|
|
250
|
+
*
|
|
251
|
+
* @param model The model used as a source to obtain the document colors.
|
|
252
|
+
* @param attributeName Determines the name of the related model's attribute for a given dropdown.
|
|
253
|
+
*/
|
|
254
|
+
updateDocumentColors(model, attributeName) {
|
|
255
|
+
const document = model.document;
|
|
256
|
+
const maxCount = this.documentColorsCount;
|
|
257
|
+
this.documentColors.clear();
|
|
258
|
+
for (const rootName of document.getRootNames()) {
|
|
259
|
+
const root = document.getRoot(rootName);
|
|
260
|
+
const range = model.createRangeIn(root);
|
|
261
|
+
for (const node of range.getItems()) {
|
|
262
|
+
if (node.is('$textProxy') && node.hasAttribute(attributeName)) {
|
|
263
|
+
this._addColorToDocumentColors(node.getAttribute(attributeName));
|
|
264
|
+
if (this.documentColors.length >= maxCount) {
|
|
265
|
+
return;
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
/**
|
|
272
|
+
* Refreshes the state of the selected color in one or both {@link module:ui/colorgrid/colorgridview~ColorGridView}s
|
|
273
|
+
* available in the {@link module:font/ui/colortableview~ColorTableView}. It guarantees that the selection will occur only in one
|
|
274
|
+
* of them.
|
|
275
|
+
*/
|
|
276
|
+
updateSelectedColors() {
|
|
277
|
+
const documentColorsGrid = this.documentColorsGrid;
|
|
278
|
+
const staticColorsGrid = this.staticColorsGrid;
|
|
279
|
+
const selectedColor = this.selectedColor;
|
|
280
|
+
staticColorsGrid.selectedColor = selectedColor;
|
|
281
|
+
if (documentColorsGrid) {
|
|
282
|
+
documentColorsGrid.selectedColor = selectedColor;
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
/**
|
|
286
|
+
* @inheritDoc
|
|
287
|
+
*/
|
|
288
|
+
render() {
|
|
289
|
+
super.render();
|
|
290
|
+
this.staticColorsGrid = this._createStaticColorsGrid();
|
|
291
|
+
this.items.add(this.staticColorsGrid);
|
|
292
|
+
if (this.documentColorsCount) {
|
|
293
|
+
// Create a label for document colors.
|
|
294
|
+
const bind = Template.bind(this.documentColors, this.documentColors);
|
|
295
|
+
const label = new LabelView(this.locale);
|
|
296
|
+
label.text = this._documentColorsLabel;
|
|
297
|
+
label.extendTemplate({
|
|
298
|
+
attributes: {
|
|
299
|
+
class: [
|
|
300
|
+
'ck',
|
|
301
|
+
'ck-color-grid__label',
|
|
302
|
+
bind.if('isEmpty', 'ck-hidden')
|
|
303
|
+
]
|
|
304
|
+
}
|
|
305
|
+
});
|
|
306
|
+
this.items.add(label);
|
|
307
|
+
this.documentColorsGrid = this._createDocumentColorsGrid();
|
|
308
|
+
this.items.add(this.documentColorsGrid);
|
|
309
|
+
}
|
|
310
|
+
this._createColorPickerButton();
|
|
311
|
+
this._addColorTablesElementsToFocusTracker();
|
|
312
|
+
this.focus();
|
|
313
|
+
}
|
|
314
|
+
/**
|
|
315
|
+
* Focuses the component.
|
|
316
|
+
*/
|
|
317
|
+
focus() {
|
|
318
|
+
this.removeColorButtonView.focus();
|
|
319
|
+
}
|
|
320
|
+
/**
|
|
321
|
+
* @inheritDoc
|
|
322
|
+
*/
|
|
323
|
+
destroy() {
|
|
324
|
+
super.destroy();
|
|
325
|
+
}
|
|
326
|
+
/**
|
|
327
|
+
* Handles displaying the color picker button (if it was previously created) and making it focusable.
|
|
328
|
+
*/
|
|
329
|
+
addColorPickerButton() {
|
|
330
|
+
if (this.colorPickerButtonView) {
|
|
331
|
+
this.items.add(this.colorPickerButtonView);
|
|
332
|
+
this.focusTracker.add(this.colorPickerButtonView.element);
|
|
333
|
+
this._focusables.add(this.colorPickerButtonView);
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
/**
|
|
337
|
+
* Adds color table elements to focus tracker.
|
|
338
|
+
*/
|
|
339
|
+
_addColorTablesElementsToFocusTracker() {
|
|
340
|
+
this.focusTracker.add(this.removeColorButtonView.element);
|
|
341
|
+
this._focusables.add(this.removeColorButtonView);
|
|
342
|
+
if (this.staticColorsGrid) {
|
|
343
|
+
this.focusTracker.add(this.staticColorsGrid.element);
|
|
344
|
+
this._focusables.add(this.staticColorsGrid);
|
|
345
|
+
}
|
|
346
|
+
if (this.documentColorsGrid) {
|
|
347
|
+
this.focusTracker.add(this.documentColorsGrid.element);
|
|
348
|
+
this._focusables.add(this.documentColorsGrid);
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
/**
|
|
352
|
+
* Creates the button responsible for displaying the color picker component.
|
|
353
|
+
*/
|
|
354
|
+
_createColorPickerButton() {
|
|
355
|
+
this.colorPickerButtonView = new ButtonView();
|
|
356
|
+
this.colorPickerButtonView.set({
|
|
357
|
+
label: this._colorPickerLabel,
|
|
358
|
+
withText: true,
|
|
359
|
+
icon: uiIcons.colorPaletteIcon,
|
|
360
|
+
class: 'ck-color-table__color-picker'
|
|
361
|
+
});
|
|
362
|
+
this.colorPickerButtonView.on('execute', () => {
|
|
363
|
+
this.fire('showColorPicker');
|
|
364
|
+
});
|
|
365
|
+
}
|
|
366
|
+
/**
|
|
367
|
+
* Adds the remove color button as a child of the current view.
|
|
368
|
+
*/
|
|
369
|
+
_createRemoveColorButton() {
|
|
370
|
+
const buttonView = new ButtonView();
|
|
371
|
+
buttonView.set({
|
|
372
|
+
withText: true,
|
|
373
|
+
icon: icons.eraser,
|
|
374
|
+
label: this._removeButtonLabel
|
|
375
|
+
});
|
|
376
|
+
buttonView.class = 'ck-color-table__remove-color';
|
|
377
|
+
buttonView.on('execute', () => {
|
|
378
|
+
this.fire('execute', {
|
|
379
|
+
value: null,
|
|
380
|
+
source: 'removeColorButton'
|
|
381
|
+
});
|
|
382
|
+
});
|
|
383
|
+
buttonView.render();
|
|
384
|
+
return buttonView;
|
|
385
|
+
}
|
|
386
|
+
/**
|
|
387
|
+
* Creates a static color table grid based on the editor configuration.
|
|
388
|
+
*/
|
|
389
|
+
_createStaticColorsGrid() {
|
|
390
|
+
const colorGrid = new ColorGridView(this.locale, {
|
|
391
|
+
colorDefinitions: this.colorDefinitions,
|
|
392
|
+
columns: this.columns
|
|
393
|
+
});
|
|
394
|
+
colorGrid.on('execute', (evt, data) => {
|
|
395
|
+
this.fire('execute', {
|
|
396
|
+
value: data.value,
|
|
397
|
+
source: 'staticColorsGrid'
|
|
398
|
+
});
|
|
399
|
+
});
|
|
400
|
+
return colorGrid;
|
|
401
|
+
}
|
|
402
|
+
/**
|
|
403
|
+
* Creates the document colors section view and binds it to {@link #documentColors}.
|
|
404
|
+
*/
|
|
405
|
+
_createDocumentColorsGrid() {
|
|
406
|
+
const bind = Template.bind(this.documentColors, this.documentColors);
|
|
407
|
+
const documentColorsGrid = new ColorGridView(this.locale, {
|
|
408
|
+
columns: this.columns
|
|
409
|
+
});
|
|
410
|
+
documentColorsGrid.extendTemplate({
|
|
411
|
+
attributes: {
|
|
412
|
+
class: bind.if('isEmpty', 'ck-hidden')
|
|
413
|
+
}
|
|
414
|
+
});
|
|
415
|
+
documentColorsGrid.items.bindTo(this.documentColors).using(colorObj => {
|
|
416
|
+
const colorTile = new ColorTileView();
|
|
417
|
+
colorTile.set({
|
|
418
|
+
color: colorObj.color,
|
|
419
|
+
hasBorder: colorObj.options && colorObj.options.hasBorder
|
|
420
|
+
});
|
|
421
|
+
if (colorObj.label) {
|
|
422
|
+
colorTile.set({
|
|
423
|
+
label: colorObj.label,
|
|
424
|
+
tooltip: true
|
|
425
|
+
});
|
|
426
|
+
}
|
|
427
|
+
colorTile.on('execute', () => {
|
|
428
|
+
this.fire('execute', {
|
|
429
|
+
value: colorObj.color,
|
|
430
|
+
source: 'documentColorsGrid'
|
|
431
|
+
});
|
|
432
|
+
});
|
|
433
|
+
return colorTile;
|
|
434
|
+
});
|
|
435
|
+
// Selected color should be cleared when document colors became empty.
|
|
436
|
+
this.documentColors.on('change:isEmpty', (evt, name, val) => {
|
|
437
|
+
if (val) {
|
|
438
|
+
documentColorsGrid.selectedColor = null;
|
|
439
|
+
}
|
|
440
|
+
});
|
|
441
|
+
return documentColorsGrid;
|
|
442
|
+
}
|
|
443
|
+
/**
|
|
444
|
+
* Adds a given color to the document colors list. If possible, the method will attempt to use
|
|
445
|
+
* data from the {@link #colorDefinitions} (label, color options).
|
|
446
|
+
*
|
|
447
|
+
* @param color A string that stores the value of the recently applied color.
|
|
448
|
+
*/
|
|
449
|
+
_addColorToDocumentColors(color) {
|
|
450
|
+
const predefinedColor = this.colorDefinitions
|
|
451
|
+
.find(definition => definition.color === color);
|
|
452
|
+
if (!predefinedColor) {
|
|
453
|
+
this.documentColors.add({
|
|
454
|
+
color,
|
|
455
|
+
label: color,
|
|
456
|
+
options: {
|
|
457
|
+
hasBorder: false
|
|
458
|
+
}
|
|
459
|
+
});
|
|
460
|
+
}
|
|
461
|
+
else {
|
|
462
|
+
this.documentColors.add(Object.assign({}, predefinedColor));
|
|
463
|
+
}
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
/**
|
|
467
|
+
* A class which represents a color picker component view with the following sub–components:
|
|
468
|
+
*
|
|
469
|
+
* * Color picker saturation and hue sliders,
|
|
470
|
+
* * Input accepting colors in HEX format,
|
|
471
|
+
* * "Save" and "Cancel" action buttons.
|
|
472
|
+
*/
|
|
473
|
+
class ColorPickerPageView extends View {
|
|
474
|
+
/**
|
|
475
|
+
* @param locale The localization services instance.
|
|
476
|
+
* @param focusTracker Tracks information about the DOM focus in the list.
|
|
477
|
+
* @param focusables A collection of views that can be focused in the view..
|
|
478
|
+
* @param keystrokes An instance of the {@link module:utils/keystrokehandler~KeystrokeHandler}.
|
|
479
|
+
* @param colorPickerConfig The configuration of color picker feature.
|
|
480
|
+
*/
|
|
481
|
+
constructor(locale, { focusTracker, focusables, keystrokes, colorPickerConfig }) {
|
|
482
|
+
super(locale);
|
|
483
|
+
this.items = this.createCollection();
|
|
484
|
+
this.focusTracker = focusTracker;
|
|
485
|
+
this.keystrokes = keystrokes;
|
|
486
|
+
this.set('isVisible', false);
|
|
487
|
+
this.set('selectedColor', undefined);
|
|
488
|
+
this._focusables = focusables;
|
|
489
|
+
this._pickerConfig = colorPickerConfig;
|
|
490
|
+
const bind = this.bindTemplate;
|
|
491
|
+
const { saveButtonView, cancelButtonView } = this._createActionButtons();
|
|
492
|
+
this.saveButtonView = saveButtonView;
|
|
493
|
+
this.cancelButtonView = cancelButtonView;
|
|
494
|
+
this.actionBarView = this._createActionBarView({ saveButtonView, cancelButtonView });
|
|
495
|
+
this.setTemplate({
|
|
496
|
+
tag: 'div',
|
|
497
|
+
attributes: {
|
|
498
|
+
class: [
|
|
499
|
+
'ck-color-picker-page-view',
|
|
500
|
+
bind.if('isVisible', 'ck-hidden', value => !value)
|
|
501
|
+
]
|
|
502
|
+
},
|
|
503
|
+
children: this.items
|
|
504
|
+
});
|
|
505
|
+
}
|
|
506
|
+
/**
|
|
507
|
+
* @inheritDoc
|
|
508
|
+
*/
|
|
509
|
+
render() {
|
|
510
|
+
super.render();
|
|
511
|
+
const colorPickerView = new ColorPickerView(this.locale, this._pickerConfig);
|
|
512
|
+
this.colorPickerView = colorPickerView;
|
|
513
|
+
this.colorPickerView.render();
|
|
514
|
+
if (this.selectedColor) {
|
|
515
|
+
colorPickerView.color = this.selectedColor;
|
|
516
|
+
}
|
|
517
|
+
this.listenTo(this, 'change:selectedColor', (evt, name, value) => {
|
|
518
|
+
colorPickerView.color = value;
|
|
519
|
+
});
|
|
520
|
+
this.items.add(this.colorPickerView);
|
|
521
|
+
this.items.add(this.actionBarView);
|
|
522
|
+
this._addColorPickersElementsToFocusTracker();
|
|
523
|
+
this._stopPropagationOnArrowsKeys();
|
|
524
|
+
this._executeOnEnterPress();
|
|
525
|
+
this._executeUponColorChange();
|
|
526
|
+
}
|
|
527
|
+
/**
|
|
528
|
+
* @inheritDoc
|
|
529
|
+
*/
|
|
530
|
+
destroy() {
|
|
531
|
+
super.destroy();
|
|
532
|
+
}
|
|
533
|
+
/**
|
|
534
|
+
* Focuses the color picker.
|
|
535
|
+
*/
|
|
536
|
+
focus() {
|
|
537
|
+
this.colorPickerView.focus();
|
|
538
|
+
}
|
|
539
|
+
/**
|
|
540
|
+
* When color picker is focused and "enter" is pressed it executes command.
|
|
541
|
+
*/
|
|
542
|
+
_executeOnEnterPress() {
|
|
543
|
+
this.keystrokes.set('enter', evt => {
|
|
544
|
+
if (this.isVisible && this.focusTracker.focusedElement !== this.cancelButtonView.element) {
|
|
545
|
+
this.fire('execute', {
|
|
546
|
+
value: this.selectedColor
|
|
547
|
+
});
|
|
548
|
+
evt.stopPropagation();
|
|
549
|
+
evt.preventDefault();
|
|
550
|
+
}
|
|
551
|
+
});
|
|
552
|
+
}
|
|
553
|
+
/**
|
|
554
|
+
* Removes default behavior of arrow keys in dropdown.
|
|
555
|
+
*/
|
|
556
|
+
_stopPropagationOnArrowsKeys() {
|
|
557
|
+
const stopPropagation = (data) => data.stopPropagation();
|
|
558
|
+
this.keystrokes.set('arrowright', stopPropagation);
|
|
559
|
+
this.keystrokes.set('arrowleft', stopPropagation);
|
|
560
|
+
this.keystrokes.set('arrowup', stopPropagation);
|
|
561
|
+
this.keystrokes.set('arrowdown', stopPropagation);
|
|
562
|
+
}
|
|
563
|
+
/**
|
|
564
|
+
* Adds color picker elements to focus tracker.
|
|
565
|
+
*/
|
|
566
|
+
_addColorPickersElementsToFocusTracker() {
|
|
567
|
+
for (const slider of this.colorPickerView.slidersView) {
|
|
568
|
+
this.focusTracker.add(slider.element);
|
|
569
|
+
this._focusables.add(slider);
|
|
570
|
+
}
|
|
571
|
+
this.focusTracker.add(this.colorPickerView.hexInputRow.children.get(1).element);
|
|
572
|
+
this._focusables.add(this.colorPickerView.hexInputRow.children.get(1));
|
|
573
|
+
this.focusTracker.add(this.saveButtonView.element);
|
|
574
|
+
this._focusables.add(this.saveButtonView);
|
|
575
|
+
this.focusTracker.add(this.cancelButtonView.element);
|
|
576
|
+
this._focusables.add(this.cancelButtonView);
|
|
577
|
+
}
|
|
578
|
+
/**
|
|
579
|
+
* Creates bar containing "Save" and "Cancel" buttons.
|
|
580
|
+
*/
|
|
581
|
+
_createActionBarView({ saveButtonView, cancelButtonView }) {
|
|
582
|
+
const actionBarRow = new View();
|
|
583
|
+
const children = this.createCollection();
|
|
584
|
+
children.add(saveButtonView);
|
|
585
|
+
children.add(cancelButtonView);
|
|
586
|
+
actionBarRow.setTemplate({
|
|
587
|
+
tag: 'div',
|
|
588
|
+
attributes: {
|
|
589
|
+
class: [
|
|
590
|
+
'ck',
|
|
591
|
+
'ck-color-table_action-bar'
|
|
592
|
+
]
|
|
593
|
+
},
|
|
594
|
+
children
|
|
595
|
+
});
|
|
596
|
+
return actionBarRow;
|
|
597
|
+
}
|
|
598
|
+
/**
|
|
599
|
+
* Creates "Save" and "Cancel" buttons.
|
|
600
|
+
*/
|
|
601
|
+
_createActionButtons() {
|
|
602
|
+
const locale = this.locale;
|
|
603
|
+
const t = locale.t;
|
|
604
|
+
const saveButtonView = new ButtonView(locale);
|
|
605
|
+
const cancelButtonView = new ButtonView(locale);
|
|
606
|
+
saveButtonView.set({
|
|
607
|
+
icon: icons.check,
|
|
608
|
+
class: 'ck-button-save',
|
|
609
|
+
withText: false,
|
|
610
|
+
label: t('Accept'),
|
|
611
|
+
type: 'button'
|
|
612
|
+
});
|
|
613
|
+
cancelButtonView.set({
|
|
614
|
+
icon: icons.cancel,
|
|
615
|
+
class: 'ck-button-cancel',
|
|
616
|
+
withText: false,
|
|
617
|
+
label: t('Cancel')
|
|
618
|
+
});
|
|
619
|
+
saveButtonView.on('execute', () => {
|
|
620
|
+
this.fire('execute', {
|
|
621
|
+
source: 'saveButton',
|
|
622
|
+
value: this.selectedColor
|
|
623
|
+
});
|
|
624
|
+
});
|
|
625
|
+
cancelButtonView.on('execute', () => {
|
|
626
|
+
this.fire('cancel');
|
|
627
|
+
});
|
|
628
|
+
return {
|
|
629
|
+
saveButtonView, cancelButtonView
|
|
630
|
+
};
|
|
631
|
+
}
|
|
632
|
+
/**
|
|
633
|
+
* Fires the `execute` event if color in color picker changed.
|
|
634
|
+
*
|
|
635
|
+
* @fires execute
|
|
636
|
+
*/
|
|
637
|
+
_executeUponColorChange() {
|
|
638
|
+
this.colorPickerView.on('change:color', (evt, evtName, newValue) => {
|
|
639
|
+
this.fire('execute', {
|
|
640
|
+
value: newValue,
|
|
641
|
+
source: 'colorPicker'
|
|
642
|
+
});
|
|
643
|
+
});
|
|
644
|
+
}
|
|
645
|
+
}
|