1 |
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 | import { Plugin } from 'ckeditor5/src/core';
|
9 | import { ButtonView, SplitButtonView, createDropdown, focusChildOnDropdownOpen } from 'ckeditor5/src/ui';
|
10 | import ListPropertiesView from './ui/listpropertiesview';
|
11 | import bulletedListIcon from '../../theme/icons/bulletedlist.svg';
|
12 | import numberedListIcon from '../../theme/icons/numberedlist.svg';
|
13 | import listStyleDiscIcon from '../../theme/icons/liststyledisc.svg';
|
14 | import listStyleCircleIcon from '../../theme/icons/liststylecircle.svg';
|
15 | import listStyleSquareIcon from '../../theme/icons/liststylesquare.svg';
|
16 | import listStyleDecimalIcon from '../../theme/icons/liststyledecimal.svg';
|
17 | import listStyleDecimalWithLeadingZeroIcon from '../../theme/icons/liststyledecimalleadingzero.svg';
|
18 | import listStyleLowerRomanIcon from '../../theme/icons/liststylelowerroman.svg';
|
19 | import listStyleUpperRomanIcon from '../../theme/icons/liststyleupperroman.svg';
|
20 | import listStyleLowerLatinIcon from '../../theme/icons/liststylelowerlatin.svg';
|
21 | import listStyleUpperLatinIcon from '../../theme/icons/liststyleupperlatin.svg';
|
22 | import '../../theme/liststyles.css';
|
23 |
|
24 |
|
25 |
|
26 |
|
27 |
|
28 |
|
29 |
|
30 | export default class ListPropertiesUI extends Plugin {
|
31 | |
32 |
|
33 |
|
34 | static get pluginName() {
|
35 | return 'ListPropertiesUI';
|
36 | }
|
37 | init() {
|
38 | const editor = this.editor;
|
39 | const t = editor.locale.t;
|
40 | const enabledProperties = editor.config.get('list.properties');
|
41 |
|
42 |
|
43 |
|
44 | if (enabledProperties.styles) {
|
45 | editor.ui.componentFactory.add('bulletedList', getDropdownViewCreator({
|
46 | editor,
|
47 | parentCommandName: 'bulletedList',
|
48 | buttonLabel: t('Bulleted List'),
|
49 | buttonIcon: bulletedListIcon,
|
50 | styleGridAriaLabel: t('Bulleted list styles toolbar'),
|
51 | styleDefinitions: [
|
52 | {
|
53 | label: t('Toggle the disc list style'),
|
54 | tooltip: t('Disc'),
|
55 | type: 'disc',
|
56 | icon: listStyleDiscIcon
|
57 | },
|
58 | {
|
59 | label: t('Toggle the circle list style'),
|
60 | tooltip: t('Circle'),
|
61 | type: 'circle',
|
62 | icon: listStyleCircleIcon
|
63 | },
|
64 | {
|
65 | label: t('Toggle the square list style'),
|
66 | tooltip: t('Square'),
|
67 | type: 'square',
|
68 | icon: listStyleSquareIcon
|
69 | }
|
70 | ]
|
71 | }));
|
72 | }
|
73 |
|
74 |
|
75 |
|
76 | if (enabledProperties.styles || enabledProperties.startIndex || enabledProperties.reversed) {
|
77 | editor.ui.componentFactory.add('numberedList', getDropdownViewCreator({
|
78 | editor,
|
79 | parentCommandName: 'numberedList',
|
80 | buttonLabel: t('Numbered List'),
|
81 | buttonIcon: numberedListIcon,
|
82 | styleGridAriaLabel: t('Numbered list styles toolbar'),
|
83 | styleDefinitions: [
|
84 | {
|
85 | label: t('Toggle the decimal list style'),
|
86 | tooltip: t('Decimal'),
|
87 | type: 'decimal',
|
88 | icon: listStyleDecimalIcon
|
89 | },
|
90 | {
|
91 | label: t('Toggle the decimal with leading zero list style'),
|
92 | tooltip: t('Decimal with leading zero'),
|
93 | type: 'decimal-leading-zero',
|
94 | icon: listStyleDecimalWithLeadingZeroIcon
|
95 | },
|
96 | {
|
97 | label: t('Toggle the lower–roman list style'),
|
98 | tooltip: t('Lower–roman'),
|
99 | type: 'lower-roman',
|
100 | icon: listStyleLowerRomanIcon
|
101 | },
|
102 | {
|
103 | label: t('Toggle the upper–roman list style'),
|
104 | tooltip: t('Upper-roman'),
|
105 | type: 'upper-roman',
|
106 | icon: listStyleUpperRomanIcon
|
107 | },
|
108 | {
|
109 | label: t('Toggle the lower–latin list style'),
|
110 | tooltip: t('Lower-latin'),
|
111 | type: 'lower-latin',
|
112 | icon: listStyleLowerLatinIcon
|
113 | },
|
114 | {
|
115 | label: t('Toggle the upper–latin list style'),
|
116 | tooltip: t('Upper-latin'),
|
117 | type: 'upper-latin',
|
118 | icon: listStyleUpperLatinIcon
|
119 | }
|
120 | ]
|
121 | }));
|
122 | }
|
123 | }
|
124 | }
|
125 |
|
126 |
|
127 |
|
128 |
|
129 |
|
130 |
|
131 |
|
132 |
|
133 |
|
134 |
|
135 |
|
136 |
|
137 |
|
138 | function getDropdownViewCreator({ editor, parentCommandName, buttonLabel, buttonIcon, styleGridAriaLabel, styleDefinitions }) {
|
139 | const parentCommand = editor.commands.get(parentCommandName);
|
140 | return (locale) => {
|
141 | const dropdownView = createDropdown(locale, SplitButtonView);
|
142 | const mainButtonView = dropdownView.buttonView;
|
143 | dropdownView.bind('isEnabled').to(parentCommand);
|
144 | dropdownView.class = 'ck-list-styles-dropdown';
|
145 |
|
146 | mainButtonView.on('execute', () => {
|
147 | editor.execute(parentCommandName);
|
148 | editor.editing.view.focus();
|
149 | });
|
150 | mainButtonView.set({
|
151 | label: buttonLabel,
|
152 | icon: buttonIcon,
|
153 | tooltip: true,
|
154 | isToggleable: true
|
155 | });
|
156 | mainButtonView.bind('isOn').to(parentCommand, 'value', value => !!value);
|
157 | dropdownView.once('change:isOpen', () => {
|
158 | const listPropertiesView = createListPropertiesView({
|
159 | editor,
|
160 | dropdownView,
|
161 | parentCommandName,
|
162 | styleGridAriaLabel,
|
163 | styleDefinitions
|
164 | });
|
165 | dropdownView.panelView.children.add(listPropertiesView);
|
166 | });
|
167 |
|
168 |
|
169 | dropdownView.on('execute', () => {
|
170 | editor.editing.view.focus();
|
171 | });
|
172 | return dropdownView;
|
173 | };
|
174 | }
|
175 |
|
176 |
|
177 |
|
178 |
|
179 |
|
180 |
|
181 |
|
182 |
|
183 |
|
184 |
|
185 | function getStyleButtonCreator({ editor, listStyleCommand, parentCommandName }) {
|
186 | const locale = editor.locale;
|
187 | const parentCommand = editor.commands.get(parentCommandName);
|
188 | return ({ label, type, icon, tooltip }) => {
|
189 | const button = new ButtonView(locale);
|
190 | button.set({ label, icon, tooltip });
|
191 | listStyleCommand.on('change:value', () => {
|
192 | button.isOn = listStyleCommand.value === type;
|
193 | });
|
194 | button.on('execute', () => {
|
195 |
|
196 | if (parentCommand.value) {
|
197 |
|
198 |
|
199 | if (listStyleCommand.value !== type) {
|
200 | editor.execute('listStyle', { type });
|
201 | }
|
202 |
|
203 | else {
|
204 | editor.execute('listStyle', { type: listStyleCommand.defaultType });
|
205 | }
|
206 | }
|
207 |
|
208 | else {
|
209 | editor.model.change(() => {
|
210 | editor.execute('listStyle', { type });
|
211 | });
|
212 | }
|
213 | });
|
214 | return button;
|
215 | };
|
216 | }
|
217 |
|
218 |
|
219 |
|
220 |
|
221 |
|
222 |
|
223 |
|
224 |
|
225 |
|
226 |
|
227 | function createListPropertiesView({ editor, dropdownView, parentCommandName, styleDefinitions, styleGridAriaLabel }) {
|
228 | const locale = editor.locale;
|
229 | const enabledProperties = editor.config.get('list.properties');
|
230 | let styleButtonViews = null;
|
231 | if (parentCommandName != 'numberedList') {
|
232 | enabledProperties.startIndex = false;
|
233 | enabledProperties.reversed = false;
|
234 | }
|
235 | if (enabledProperties.styles) {
|
236 | const listStyleCommand = editor.commands.get('listStyle');
|
237 | const styleButtonCreator = getStyleButtonCreator({
|
238 | editor,
|
239 | parentCommandName,
|
240 | listStyleCommand
|
241 | });
|
242 |
|
243 | const isStyleTypeSupported = typeof listStyleCommand.isStyleTypeSupported == 'function' ?
|
244 | (styleDefinition) => listStyleCommand.isStyleTypeSupported(styleDefinition.type) :
|
245 | () => true;
|
246 | styleButtonViews = styleDefinitions.filter(isStyleTypeSupported).map(styleButtonCreator);
|
247 | }
|
248 | const listPropertiesView = new ListPropertiesView(locale, {
|
249 | styleGridAriaLabel,
|
250 | enabledProperties,
|
251 | styleButtonViews
|
252 | });
|
253 | if (enabledProperties.styles) {
|
254 |
|
255 | focusChildOnDropdownOpen(dropdownView, () => {
|
256 | return listPropertiesView.stylesView.children.find((child) => child.isOn);
|
257 | });
|
258 | }
|
259 | if (enabledProperties.startIndex) {
|
260 | const listStartCommand = editor.commands.get('listStart');
|
261 | listPropertiesView.startIndexFieldView.bind('isEnabled').to(listStartCommand);
|
262 | listPropertiesView.startIndexFieldView.fieldView.bind('value').to(listStartCommand);
|
263 | listPropertiesView.on('listStart', (evt, data) => editor.execute('listStart', data));
|
264 | }
|
265 | if (enabledProperties.reversed) {
|
266 | const listReversedCommand = editor.commands.get('listReversed');
|
267 | listPropertiesView.reversedSwitchButtonView.bind('isEnabled').to(listReversedCommand);
|
268 | listPropertiesView.reversedSwitchButtonView.bind('isOn').to(listReversedCommand, 'value', value => !!value);
|
269 | listPropertiesView.on('listReversed', () => {
|
270 | const isReversed = listReversedCommand.value;
|
271 | editor.execute('listReversed', { reversed: !isReversed });
|
272 | });
|
273 | }
|
274 |
|
275 | listPropertiesView.delegate('execute').to(dropdownView);
|
276 | return listPropertiesView;
|
277 | }
|