@ckeditor/ckeditor5-bookmark 0.0.0-nightly-next-20250302.0 → 0.0.0-nightly-20250303.0
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/bookmark.js +2 -2
- package/build/translations/af.js +1 -1
- package/build/translations/ar.js +1 -1
- package/build/translations/ast.js +1 -1
- package/build/translations/az.js +1 -1
- package/build/translations/bg.js +1 -1
- package/build/translations/bn.js +1 -1
- package/build/translations/bs.js +1 -1
- package/build/translations/ca.js +1 -1
- package/build/translations/cs.js +1 -1
- package/build/translations/da.js +1 -1
- package/build/translations/de-ch.js +1 -1
- package/build/translations/de.js +1 -1
- package/build/translations/el.js +1 -1
- package/build/translations/en-au.js +1 -1
- package/build/translations/en-gb.js +1 -1
- package/build/translations/eo.js +1 -1
- package/build/translations/es-co.js +1 -1
- package/build/translations/es.js +1 -1
- package/build/translations/et.js +1 -1
- package/build/translations/eu.js +1 -1
- package/build/translations/fa.js +1 -1
- package/build/translations/fi.js +1 -1
- package/build/translations/fr.js +1 -1
- package/build/translations/gl.js +1 -1
- package/build/translations/gu.js +1 -1
- package/build/translations/he.js +1 -1
- package/build/translations/hi.js +1 -1
- package/build/translations/hr.js +1 -1
- package/build/translations/hu.js +1 -1
- package/build/translations/hy.js +1 -1
- package/build/translations/id.js +1 -1
- package/build/translations/it.js +1 -1
- package/build/translations/ja.js +1 -1
- package/build/translations/jv.js +1 -1
- package/build/translations/kk.js +1 -1
- package/build/translations/km.js +1 -1
- package/build/translations/kn.js +1 -1
- package/build/translations/ko.js +1 -1
- package/build/translations/ku.js +1 -1
- package/build/translations/lt.js +1 -1
- package/build/translations/lv.js +1 -1
- package/build/translations/ms.js +1 -1
- package/build/translations/nb.js +1 -1
- package/build/translations/ne.js +1 -1
- package/build/translations/nl.js +1 -1
- package/build/translations/no.js +1 -1
- package/build/translations/oc.js +1 -1
- package/build/translations/pl.js +1 -1
- package/build/translations/pt-br.js +1 -1
- package/build/translations/pt.js +1 -1
- package/build/translations/ro.js +1 -1
- package/build/translations/ru.js +1 -1
- package/build/translations/si.js +1 -1
- package/build/translations/sk.js +1 -1
- package/build/translations/sl.js +1 -1
- package/build/translations/sq.js +1 -1
- package/build/translations/sr-latn.js +1 -1
- package/build/translations/sr.js +1 -1
- package/build/translations/sv.js +1 -1
- package/build/translations/th.js +1 -1
- package/build/translations/ti.js +1 -1
- package/build/translations/tk.js +1 -1
- package/build/translations/tr.js +1 -1
- package/build/translations/tt.js +1 -1
- package/build/translations/ug.js +1 -1
- package/build/translations/uk.js +1 -1
- package/build/translations/ur.js +1 -1
- package/build/translations/uz.js +1 -1
- package/build/translations/vi.js +1 -1
- package/build/translations/zh-cn.js +1 -1
- package/build/translations/zh.js +1 -1
- package/ckeditor5-metadata.json +1 -1
- package/dist/index-editor.css +101 -56
- package/dist/index.css +119 -59
- package/dist/index.css.map +1 -1
- package/dist/index.js +389 -282
- package/dist/index.js.map +1 -1
- package/lang/contexts.json +3 -5
- package/package.json +7 -8
- package/src/bookmarkconfig.d.ts +0 -24
- package/src/bookmarkediting.d.ts +1 -9
- package/src/bookmarkediting.js +9 -23
- package/src/bookmarkui.d.ts +57 -24
- package/src/bookmarkui.js +212 -207
- package/src/ui/bookmarkactionsview.d.ts +102 -0
- package/src/ui/bookmarkactionsview.js +154 -0
- package/src/ui/bookmarkformview.d.ts +14 -24
- package/src/ui/bookmarkformview.js +62 -103
- package/theme/bookmark.css +46 -0
- package/theme/bookmarkactions.css +44 -0
- package/theme/bookmarkform.css +38 -0
- package/theme/bookmarktoolbar.css +0 -4
package/src/bookmarkui.js
CHANGED
|
@@ -2,13 +2,15 @@
|
|
|
2
2
|
* @license Copyright (c) 2003-2025, CKSource Holding sp. z o.o. All rights reserved.
|
|
3
3
|
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-licensing-options
|
|
4
4
|
*/
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
import {
|
|
5
|
+
/**
|
|
6
|
+
* @module bookmark/bookmarkui
|
|
7
|
+
*/
|
|
8
|
+
import { Plugin, icons } from 'ckeditor5/src/core.js';
|
|
9
|
+
import { ButtonView, ContextualBalloon, CssTransitionDisablerMixin, MenuBarMenuListItemButtonView, clickOutsideHandler } from 'ckeditor5/src/ui.js';
|
|
10
|
+
import { ClickObserver } from 'ckeditor5/src/engine.js';
|
|
9
11
|
import BookmarkFormView from './ui/bookmarkformview.js';
|
|
12
|
+
import BookmarkActionsView from './ui/bookmarkactionsview.js';
|
|
10
13
|
import BookmarkEditing from './bookmarkediting.js';
|
|
11
|
-
import '../theme/bookmarktoolbar.css';
|
|
12
14
|
const VISUAL_SELECTION_MARKER_NAME = 'bookmark-ui';
|
|
13
15
|
/**
|
|
14
16
|
* The UI plugin of the bookmark feature.
|
|
@@ -17,19 +19,22 @@ const VISUAL_SELECTION_MARKER_NAME = 'bookmark-ui';
|
|
|
17
19
|
* which inserts the `bookmark` element upon selection.
|
|
18
20
|
*/
|
|
19
21
|
export default class BookmarkUI extends Plugin {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
22
|
+
constructor() {
|
|
23
|
+
super(...arguments);
|
|
24
|
+
/**
|
|
25
|
+
* The actions view displayed inside of the balloon.
|
|
26
|
+
*/
|
|
27
|
+
this.actionsView = null;
|
|
28
|
+
/**
|
|
29
|
+
* The form view displayed inside the balloon.
|
|
30
|
+
*/
|
|
31
|
+
this.formView = null;
|
|
32
|
+
}
|
|
28
33
|
/**
|
|
29
34
|
* @inheritDoc
|
|
30
35
|
*/
|
|
31
36
|
static get requires() {
|
|
32
|
-
return [BookmarkEditing, ContextualBalloon
|
|
37
|
+
return [BookmarkEditing, ContextualBalloon];
|
|
33
38
|
}
|
|
34
39
|
/**
|
|
35
40
|
* @inheritDoc
|
|
@@ -48,13 +53,11 @@ export default class BookmarkUI extends Plugin {
|
|
|
48
53
|
*/
|
|
49
54
|
init() {
|
|
50
55
|
const editor = this.editor;
|
|
56
|
+
editor.editing.view.addObserver(ClickObserver);
|
|
51
57
|
this._balloon = editor.plugins.get(ContextualBalloon);
|
|
52
|
-
// Register the link provider in link plugin to display the link form.
|
|
53
|
-
if (editor.plugins.has('LinkUI')) {
|
|
54
|
-
this._registerLinkProvider();
|
|
55
|
-
}
|
|
56
58
|
// Create toolbar buttons.
|
|
57
|
-
this.
|
|
59
|
+
this._createToolbarBookmarkButton();
|
|
60
|
+
this._enableBalloonActivators();
|
|
58
61
|
// Renders a fake visual selection marker on an expanded selection.
|
|
59
62
|
editor.conversion.for('editingDowncast').markerToHighlight({
|
|
60
63
|
model: VISUAL_SELECTION_MARKER_NAME,
|
|
@@ -75,35 +78,6 @@ export default class BookmarkUI extends Plugin {
|
|
|
75
78
|
}
|
|
76
79
|
});
|
|
77
80
|
}
|
|
78
|
-
/**
|
|
79
|
-
* @inheritDoc
|
|
80
|
-
*/
|
|
81
|
-
afterInit() {
|
|
82
|
-
const editor = this.editor;
|
|
83
|
-
const t = editor.locale.t;
|
|
84
|
-
const widgetToolbarRepository = this.editor.plugins.get(WidgetToolbarRepository);
|
|
85
|
-
const defaultPositions = BalloonPanelView.defaultPositions;
|
|
86
|
-
widgetToolbarRepository.register('bookmark', {
|
|
87
|
-
ariaLabel: t('Bookmark toolbar'),
|
|
88
|
-
items: editor.config.get('bookmark.toolbar'),
|
|
89
|
-
getRelatedElement: getSelectedBookmarkWidget,
|
|
90
|
-
// Override positions to the same list as for balloon panel default
|
|
91
|
-
// so widget toolbar will try to use same position as form view.
|
|
92
|
-
positions: [
|
|
93
|
-
defaultPositions.southArrowNorth,
|
|
94
|
-
defaultPositions.southArrowNorthMiddleWest,
|
|
95
|
-
defaultPositions.southArrowNorthMiddleEast,
|
|
96
|
-
defaultPositions.southArrowNorthWest,
|
|
97
|
-
defaultPositions.southArrowNorthEast,
|
|
98
|
-
defaultPositions.northArrowSouth,
|
|
99
|
-
defaultPositions.northArrowSouthMiddleWest,
|
|
100
|
-
defaultPositions.northArrowSouthMiddleEast,
|
|
101
|
-
defaultPositions.northArrowSouthWest,
|
|
102
|
-
defaultPositions.northArrowSouthEast,
|
|
103
|
-
defaultPositions.viewportStickyNorth
|
|
104
|
-
]
|
|
105
|
-
});
|
|
106
|
-
}
|
|
107
81
|
/**
|
|
108
82
|
* @inheritDoc
|
|
109
83
|
*/
|
|
@@ -113,36 +87,61 @@ export default class BookmarkUI extends Plugin {
|
|
|
113
87
|
if (this.formView) {
|
|
114
88
|
this.formView.destroy();
|
|
115
89
|
}
|
|
90
|
+
if (this.actionsView) {
|
|
91
|
+
this.actionsView.destroy();
|
|
92
|
+
}
|
|
116
93
|
}
|
|
117
94
|
/**
|
|
118
95
|
* Creates views.
|
|
119
96
|
*/
|
|
120
97
|
_createViews() {
|
|
98
|
+
this.actionsView = this._createActionsView();
|
|
121
99
|
this.formView = this._createFormView();
|
|
122
100
|
// Attach lifecycle actions to the the balloon.
|
|
123
101
|
this._enableUserBalloonInteractions();
|
|
124
102
|
}
|
|
103
|
+
/**
|
|
104
|
+
* Creates the {@link module:bookmark/ui/bookmarkactionsview~BookmarkActionsView} instance.
|
|
105
|
+
*/
|
|
106
|
+
_createActionsView() {
|
|
107
|
+
const editor = this.editor;
|
|
108
|
+
const actionsView = new BookmarkActionsView(editor.locale);
|
|
109
|
+
const updateBookmarkCommand = editor.commands.get('updateBookmark');
|
|
110
|
+
const deleteCommand = editor.commands.get('delete');
|
|
111
|
+
actionsView.bind('id').to(updateBookmarkCommand, 'value');
|
|
112
|
+
actionsView.editButtonView.bind('isEnabled').to(updateBookmarkCommand);
|
|
113
|
+
actionsView.removeButtonView.bind('isEnabled').to(deleteCommand);
|
|
114
|
+
// Display edit form view after clicking on the "Edit" button.
|
|
115
|
+
this.listenTo(actionsView, 'edit', () => {
|
|
116
|
+
this._addFormView();
|
|
117
|
+
});
|
|
118
|
+
// Execute remove command after clicking on the "Remove" button.
|
|
119
|
+
this.listenTo(actionsView, 'remove', () => {
|
|
120
|
+
this._hideUI();
|
|
121
|
+
editor.execute('delete');
|
|
122
|
+
});
|
|
123
|
+
// Close the panel on esc key press when the **actions have focus**.
|
|
124
|
+
actionsView.keystrokes.set('Esc', (data, cancel) => {
|
|
125
|
+
this._hideUI();
|
|
126
|
+
cancel();
|
|
127
|
+
});
|
|
128
|
+
return actionsView;
|
|
129
|
+
}
|
|
125
130
|
/**
|
|
126
131
|
* Creates the {@link module:bookmark/ui/bookmarkformview~BookmarkFormView} instance.
|
|
127
132
|
*/
|
|
128
133
|
_createFormView() {
|
|
129
134
|
const editor = this.editor;
|
|
130
135
|
const locale = editor.locale;
|
|
131
|
-
const t = locale.t;
|
|
132
136
|
const insertBookmarkCommand = editor.commands.get('insertBookmark');
|
|
133
137
|
const updateBookmarkCommand = editor.commands.get('updateBookmark');
|
|
134
138
|
const commands = [insertBookmarkCommand, updateBookmarkCommand];
|
|
135
139
|
const formView = new (CssTransitionDisablerMixin(BookmarkFormView))(locale, getFormValidators(editor));
|
|
136
140
|
formView.idInputView.fieldView.bind('value').to(updateBookmarkCommand, 'value');
|
|
137
|
-
formView.saveButtonView.bind('label').to(updateBookmarkCommand, 'value', value => value ? t('Save') : t('Insert'));
|
|
138
141
|
// Form elements should be read-only when corresponding commands are disabled.
|
|
139
142
|
formView.idInputView.bind('isEnabled').toMany(commands, 'isEnabled', (...areEnabled) => areEnabled.some(isEnabled => isEnabled));
|
|
140
143
|
// Disable the "save" button if the command is disabled.
|
|
141
|
-
formView.
|
|
142
|
-
// Close the panel on form after clicking back button.
|
|
143
|
-
this.listenTo(formView, 'cancel', () => {
|
|
144
|
-
this._hideFormView();
|
|
145
|
-
});
|
|
144
|
+
formView.buttonView.bind('isEnabled').toMany(commands, 'isEnabled', (...areEnabled) => areEnabled.some(isEnabled => isEnabled));
|
|
146
145
|
// Execute link command after clicking the "Save" button.
|
|
147
146
|
this.listenTo(formView, 'submit', () => {
|
|
148
147
|
if (formView.isValid()) {
|
|
@@ -153,134 +152,41 @@ export default class BookmarkUI extends Plugin {
|
|
|
153
152
|
else {
|
|
154
153
|
editor.execute('insertBookmark', { bookmarkId: value });
|
|
155
154
|
}
|
|
156
|
-
this.
|
|
155
|
+
this._closeFormView();
|
|
157
156
|
}
|
|
158
157
|
});
|
|
159
158
|
// Update balloon position when form error changes.
|
|
160
159
|
this.listenTo(formView.idInputView, 'change:errorText', () => {
|
|
161
160
|
editor.ui.update();
|
|
162
161
|
});
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
* the list of the bookmarks from the link form.
|
|
168
|
-
*/
|
|
169
|
-
_registerLinkProvider() {
|
|
170
|
-
const t = this.editor.locale.t;
|
|
171
|
-
const linksUI = this.editor.plugins.get('LinkUI');
|
|
172
|
-
const bookmarkEditing = this.editor.plugins.get(BookmarkEditing);
|
|
173
|
-
const getListItems = () => Array
|
|
174
|
-
.from(bookmarkEditing.getAllBookmarkNames())
|
|
175
|
-
.sort((a, b) => a.localeCompare(b))
|
|
176
|
-
.map((bookmarkId) => ({
|
|
177
|
-
id: bookmarkId,
|
|
178
|
-
href: `#${bookmarkId}`,
|
|
179
|
-
label: bookmarkId,
|
|
180
|
-
icon: IconBookmarkMedium
|
|
181
|
-
}));
|
|
182
|
-
const getItem = (href) => {
|
|
183
|
-
const bookmark = [...bookmarkEditing.getAllBookmarkNames()].find(item => `#${item}` === href);
|
|
184
|
-
if (!bookmark) {
|
|
185
|
-
return null;
|
|
186
|
-
}
|
|
187
|
-
return {
|
|
188
|
-
href,
|
|
189
|
-
label: bookmark,
|
|
190
|
-
icon: IconBookmarkSmall,
|
|
191
|
-
tooltip: t('Scroll to bookmark')
|
|
192
|
-
};
|
|
193
|
-
};
|
|
194
|
-
linksUI.registerLinksListProvider({
|
|
195
|
-
label: t('Bookmarks'),
|
|
196
|
-
emptyListPlaceholder: t('No bookmarks available.'),
|
|
197
|
-
navigate: ({ href }) => this._scrollToBookmark(href),
|
|
198
|
-
getListItems,
|
|
199
|
-
getItem
|
|
200
|
-
});
|
|
201
|
-
}
|
|
202
|
-
/**
|
|
203
|
-
* Scrolls the editor to the bookmark with the given id.
|
|
204
|
-
*/
|
|
205
|
-
_scrollToBookmark(href) {
|
|
206
|
-
const bookmarkEditing = this.editor.plugins.get(BookmarkEditing);
|
|
207
|
-
const bookmarkElement = bookmarkEditing.getElementForBookmarkId(href.slice(1));
|
|
208
|
-
if (!bookmarkElement) {
|
|
209
|
-
return false;
|
|
210
|
-
}
|
|
211
|
-
this.editor.model.change(writer => {
|
|
212
|
-
writer.setSelection(bookmarkElement, 'on');
|
|
162
|
+
// Close the panel on esc key press when the **form has focus**.
|
|
163
|
+
formView.keystrokes.set('Esc', (data, cancel) => {
|
|
164
|
+
this._closeFormView();
|
|
165
|
+
cancel();
|
|
213
166
|
});
|
|
214
|
-
|
|
215
|
-
alignToTop: true,
|
|
216
|
-
forceScroll: true
|
|
217
|
-
});
|
|
218
|
-
return true;
|
|
167
|
+
return formView;
|
|
219
168
|
}
|
|
220
169
|
/**
|
|
221
170
|
* Creates a toolbar Bookmark button. Clicking this button will show
|
|
222
171
|
* a {@link #_balloon} attached to the selection.
|
|
223
172
|
*/
|
|
224
|
-
|
|
173
|
+
_createToolbarBookmarkButton() {
|
|
225
174
|
const editor = this.editor;
|
|
226
175
|
editor.ui.componentFactory.add('bookmark', () => {
|
|
227
|
-
const buttonView = this.
|
|
176
|
+
const buttonView = this._createButton(ButtonView);
|
|
228
177
|
buttonView.set({
|
|
229
178
|
tooltip: true
|
|
230
179
|
});
|
|
231
180
|
return buttonView;
|
|
232
181
|
});
|
|
233
182
|
editor.ui.componentFactory.add('menuBar:bookmark', () => {
|
|
234
|
-
return this.
|
|
235
|
-
});
|
|
236
|
-
// Bookmark toolbar buttons.
|
|
237
|
-
editor.ui.componentFactory.add('bookmarkPreview', locale => {
|
|
238
|
-
const updateBookmarkCommand = editor.commands.get('updateBookmark');
|
|
239
|
-
const label = new LabelView(locale);
|
|
240
|
-
label.extendTemplate({
|
|
241
|
-
attributes: {
|
|
242
|
-
class: ['ck-bookmark-toolbar__preview']
|
|
243
|
-
}
|
|
244
|
-
});
|
|
245
|
-
label.bind('text').to(updateBookmarkCommand, 'value');
|
|
246
|
-
return label;
|
|
247
|
-
});
|
|
248
|
-
editor.ui.componentFactory.add('editBookmark', locale => {
|
|
249
|
-
const updateBookmarkCommand = editor.commands.get('updateBookmark');
|
|
250
|
-
const button = new ButtonView(locale);
|
|
251
|
-
const t = locale.t;
|
|
252
|
-
button.set({
|
|
253
|
-
label: t('Edit bookmark'),
|
|
254
|
-
icon: IconPencil,
|
|
255
|
-
tooltip: true
|
|
256
|
-
});
|
|
257
|
-
button.bind('isEnabled').to(updateBookmarkCommand);
|
|
258
|
-
this.listenTo(button, 'execute', () => {
|
|
259
|
-
this._showFormView();
|
|
260
|
-
});
|
|
261
|
-
return button;
|
|
262
|
-
});
|
|
263
|
-
editor.ui.componentFactory.add('removeBookmark', locale => {
|
|
264
|
-
const deleteCommand = editor.commands.get('delete');
|
|
265
|
-
const button = new ButtonView(locale);
|
|
266
|
-
const t = locale.t;
|
|
267
|
-
button.set({
|
|
268
|
-
label: t('Remove bookmark'),
|
|
269
|
-
icon: IconRemove,
|
|
270
|
-
tooltip: true
|
|
271
|
-
});
|
|
272
|
-
button.bind('isEnabled').to(deleteCommand);
|
|
273
|
-
this.listenTo(button, 'execute', () => {
|
|
274
|
-
editor.execute('delete');
|
|
275
|
-
editor.editing.view.focus();
|
|
276
|
-
});
|
|
277
|
-
return button;
|
|
183
|
+
return this._createButton(MenuBarMenuListItemButtonView);
|
|
278
184
|
});
|
|
279
185
|
}
|
|
280
186
|
/**
|
|
281
187
|
* Creates a button for `bookmark` command to use either in toolbar or in menu bar.
|
|
282
188
|
*/
|
|
283
|
-
|
|
189
|
+
_createButton(ButtonClass) {
|
|
284
190
|
const editor = this.editor;
|
|
285
191
|
const locale = editor.locale;
|
|
286
192
|
const view = new ButtonClass(locale);
|
|
@@ -289,32 +195,85 @@ export default class BookmarkUI extends Plugin {
|
|
|
289
195
|
const t = locale.t;
|
|
290
196
|
view.set({
|
|
291
197
|
label: t('Bookmark'),
|
|
292
|
-
icon:
|
|
198
|
+
icon: icons.bookmark
|
|
293
199
|
});
|
|
294
200
|
// Execute the command.
|
|
295
|
-
this.listenTo(view, 'execute', () => this.
|
|
201
|
+
this.listenTo(view, 'execute', () => this._showUI(true));
|
|
296
202
|
view.bind('isEnabled').toMany([insertCommand, updateCommand], 'isEnabled', (...areEnabled) => areEnabled.some(isEnabled => isEnabled));
|
|
297
203
|
view.bind('isOn').to(updateCommand, 'value', value => !!value);
|
|
298
204
|
return view;
|
|
299
205
|
}
|
|
206
|
+
/**
|
|
207
|
+
* Attaches actions that control whether the balloon panel containing the
|
|
208
|
+
* {@link #formView} should be displayed.
|
|
209
|
+
*/
|
|
210
|
+
_enableBalloonActivators() {
|
|
211
|
+
const editor = this.editor;
|
|
212
|
+
const viewDocument = editor.editing.view.document;
|
|
213
|
+
// Handle click on view document and show panel when selection is placed inside the bookmark element.
|
|
214
|
+
// Keep panel open until selection will be inside the same bookmark element.
|
|
215
|
+
this.listenTo(viewDocument, 'click', () => {
|
|
216
|
+
const bookmark = this._getSelectedBookmarkElement();
|
|
217
|
+
if (bookmark) {
|
|
218
|
+
// Then show panel but keep focus inside editor editable.
|
|
219
|
+
this._showUI();
|
|
220
|
+
}
|
|
221
|
+
});
|
|
222
|
+
}
|
|
300
223
|
/**
|
|
301
224
|
* Attaches actions that control whether the balloon panel containing the
|
|
302
225
|
* {@link #formView} is visible or not.
|
|
303
226
|
*/
|
|
304
227
|
_enableUserBalloonInteractions() {
|
|
228
|
+
// Focus the form if the balloon is visible and the Tab key has been pressed.
|
|
229
|
+
this.editor.keystrokes.set('Tab', (data, cancel) => {
|
|
230
|
+
if (this._areActionsVisible && !this.actionsView.focusTracker.isFocused) {
|
|
231
|
+
this.actionsView.focus();
|
|
232
|
+
cancel();
|
|
233
|
+
}
|
|
234
|
+
}, {
|
|
235
|
+
// Use the high priority because the bookmark UI navigation is more important
|
|
236
|
+
// than other feature's actions, e.g. list indentation.
|
|
237
|
+
priority: 'high'
|
|
238
|
+
});
|
|
305
239
|
// Close the panel on the Esc key press when the editable has focus and the balloon is visible.
|
|
306
240
|
this.editor.keystrokes.set('Esc', (data, cancel) => {
|
|
307
|
-
if (this.
|
|
308
|
-
this.
|
|
241
|
+
if (this._isUIVisible) {
|
|
242
|
+
this._hideUI();
|
|
309
243
|
cancel();
|
|
310
244
|
}
|
|
311
245
|
});
|
|
312
246
|
// Close on click outside of balloon panel element.
|
|
313
247
|
clickOutsideHandler({
|
|
314
248
|
emitter: this.formView,
|
|
315
|
-
activator: () => this.
|
|
249
|
+
activator: () => this._isUIInPanel,
|
|
316
250
|
contextElements: () => [this._balloon.view.element],
|
|
317
|
-
callback: () => this.
|
|
251
|
+
callback: () => this._hideUI()
|
|
252
|
+
});
|
|
253
|
+
}
|
|
254
|
+
/**
|
|
255
|
+
* Updates the button label. If bookmark is selected label is set to 'Update' otherwise
|
|
256
|
+
* it is 'Insert'.
|
|
257
|
+
*/
|
|
258
|
+
_updateFormButtonLabel(isBookmarkSelected) {
|
|
259
|
+
const t = this.editor.locale.t;
|
|
260
|
+
this.formView.buttonView.label = isBookmarkSelected ? t('Update') : t('Insert');
|
|
261
|
+
}
|
|
262
|
+
/**
|
|
263
|
+
* Adds the {@link #actionsView} to the {@link #_balloon}.
|
|
264
|
+
*
|
|
265
|
+
* @internal
|
|
266
|
+
*/
|
|
267
|
+
_addActionsView() {
|
|
268
|
+
if (!this.actionsView) {
|
|
269
|
+
this._createViews();
|
|
270
|
+
}
|
|
271
|
+
if (this._areActionsInPanel) {
|
|
272
|
+
return;
|
|
273
|
+
}
|
|
274
|
+
this._balloon.add({
|
|
275
|
+
view: this.actionsView,
|
|
276
|
+
position: this._getBalloonPositionData()
|
|
318
277
|
});
|
|
319
278
|
}
|
|
320
279
|
/**
|
|
@@ -327,14 +286,14 @@ export default class BookmarkUI extends Plugin {
|
|
|
327
286
|
if (this._isFormInPanel) {
|
|
328
287
|
return;
|
|
329
288
|
}
|
|
330
|
-
const
|
|
289
|
+
const editor = this.editor;
|
|
290
|
+
const updateBookmarkCommand = editor.commands.get('updateBookmark');
|
|
331
291
|
this.formView.disableCssTransitions();
|
|
332
292
|
this.formView.resetFormStatus();
|
|
333
293
|
this._balloon.add({
|
|
334
294
|
view: this.formView,
|
|
335
295
|
position: this._getBalloonPositionData()
|
|
336
296
|
});
|
|
337
|
-
this.formView.backButtonView.isVisible = updateBookmarkCommand.isEnabled;
|
|
338
297
|
this.formView.idInputView.fieldView.value = updateBookmarkCommand.value || '';
|
|
339
298
|
// Select input when form view is currently visible.
|
|
340
299
|
if (this._balloon.visibleView === this.formView) {
|
|
@@ -342,42 +301,78 @@ export default class BookmarkUI extends Plugin {
|
|
|
342
301
|
}
|
|
343
302
|
this.formView.enableCssTransitions();
|
|
344
303
|
}
|
|
304
|
+
/**
|
|
305
|
+
* Closes the form view. Decides whether the balloon should be hidden completely.
|
|
306
|
+
*/
|
|
307
|
+
_closeFormView() {
|
|
308
|
+
const updateBookmarkCommand = this.editor.commands.get('updateBookmark');
|
|
309
|
+
if (updateBookmarkCommand.value !== undefined) {
|
|
310
|
+
this._removeFormView();
|
|
311
|
+
}
|
|
312
|
+
else {
|
|
313
|
+
this._hideUI();
|
|
314
|
+
}
|
|
315
|
+
}
|
|
345
316
|
/**
|
|
346
317
|
* Removes the {@link #formView} from the {@link #_balloon}.
|
|
347
318
|
*/
|
|
348
319
|
_removeFormView() {
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
320
|
+
if (this._isFormInPanel) {
|
|
321
|
+
// Blur the input element before removing it from DOM to prevent issues in some browsers.
|
|
322
|
+
// See https://github.com/ckeditor/ckeditor5/issues/1501.
|
|
323
|
+
this.formView.buttonView.focus();
|
|
324
|
+
// Reset the ID field to update the state of the submit button.
|
|
325
|
+
this.formView.idInputView.fieldView.reset();
|
|
326
|
+
this._balloon.remove(this.formView);
|
|
327
|
+
// Because the form has an input which has focus, the focus must be brought back
|
|
328
|
+
// to the editor. Otherwise, it would be lost.
|
|
329
|
+
this.editor.editing.view.focus();
|
|
330
|
+
this._hideFakeVisualSelection();
|
|
331
|
+
}
|
|
359
332
|
}
|
|
360
333
|
/**
|
|
361
|
-
* Shows the {@link #formView}.
|
|
334
|
+
* Shows the correct UI type. It is either {@link #formView} or {@link #actionsView}.
|
|
362
335
|
*/
|
|
363
|
-
|
|
336
|
+
_showUI(forceVisible = false) {
|
|
364
337
|
if (!this.formView) {
|
|
365
338
|
this._createViews();
|
|
366
339
|
}
|
|
340
|
+
// When there's no bookmark under the selection, go straight to the editing UI.
|
|
367
341
|
if (!this._getSelectedBookmarkElement()) {
|
|
342
|
+
// Show visual selection on a text without a bookmark when the contextual balloon is displayed.
|
|
368
343
|
this._showFakeVisualSelection();
|
|
344
|
+
this._addActionsView();
|
|
345
|
+
// Be sure panel with bookmark is visible.
|
|
346
|
+
if (forceVisible) {
|
|
347
|
+
this._balloon.showStack('main');
|
|
348
|
+
}
|
|
349
|
+
this._addFormView();
|
|
350
|
+
}
|
|
351
|
+
// If there's a bookmark under the selection...
|
|
352
|
+
else {
|
|
353
|
+
// Go to the editing UI if actions are already visible.
|
|
354
|
+
if (this._areActionsVisible) {
|
|
355
|
+
this._addFormView();
|
|
356
|
+
}
|
|
357
|
+
// Otherwise display just the actions UI.
|
|
358
|
+
else {
|
|
359
|
+
this._addActionsView();
|
|
360
|
+
}
|
|
361
|
+
// Be sure panel with bookmark is visible.
|
|
362
|
+
if (forceVisible) {
|
|
363
|
+
this._balloon.showStack('main');
|
|
364
|
+
}
|
|
369
365
|
}
|
|
370
|
-
this._addFormView();
|
|
371
|
-
// Be sure panel with bookmark is visible.
|
|
372
|
-
this._balloon.showStack('main');
|
|
373
366
|
// Begin responding to ui#update once the UI is added.
|
|
374
367
|
this._startUpdatingUI();
|
|
375
368
|
}
|
|
376
369
|
/**
|
|
377
370
|
* Removes the {@link #formView} from the {@link #_balloon}.
|
|
371
|
+
*
|
|
372
|
+
* See {@link #_addFormView}, {@link #_addActionsView}.
|
|
378
373
|
*/
|
|
379
|
-
|
|
380
|
-
if (!this.
|
|
374
|
+
_hideUI() {
|
|
375
|
+
if (!this._isUIInPanel) {
|
|
381
376
|
return;
|
|
382
377
|
}
|
|
383
378
|
const editor = this.editor;
|
|
@@ -388,19 +383,22 @@ export default class BookmarkUI extends Plugin {
|
|
|
388
383
|
editor.editing.view.focus();
|
|
389
384
|
// Remove form first because it's on top of the stack.
|
|
390
385
|
this._removeFormView();
|
|
386
|
+
// Then remove the actions view because it's beneath the form.
|
|
387
|
+
this._balloon.remove(this.actionsView);
|
|
391
388
|
this._hideFakeVisualSelection();
|
|
392
389
|
}
|
|
393
390
|
/**
|
|
394
391
|
* Makes the UI react to the {@link module:ui/editorui/editorui~EditorUI#event:update} event to
|
|
395
392
|
* reposition itself when the editor UI should be refreshed.
|
|
396
393
|
*
|
|
397
|
-
* See: {@link #
|
|
394
|
+
* See: {@link #_hideUI} to learn when the UI stops reacting to the `update` event.
|
|
398
395
|
*/
|
|
399
396
|
_startUpdatingUI() {
|
|
400
397
|
const editor = this.editor;
|
|
401
398
|
const viewDocument = editor.editing.view.document;
|
|
402
399
|
let prevSelectedBookmark = this._getSelectedBookmarkElement();
|
|
403
400
|
let prevSelectionParent = getSelectionParent();
|
|
401
|
+
this._updateFormButtonLabel(!!prevSelectedBookmark);
|
|
404
402
|
const update = () => {
|
|
405
403
|
const selectedBookmark = this._getSelectedBookmarkElement();
|
|
406
404
|
const selectionParent = getSelectionParent();
|
|
@@ -412,20 +410,21 @@ export default class BookmarkUI extends Plugin {
|
|
|
412
410
|
// else modified the document.
|
|
413
411
|
// * the selection has expanded (e.g. displaying bookmark actions then pressing SHIFT+Right arrow).
|
|
414
412
|
//
|
|
415
|
-
if (prevSelectedBookmark && !selectedBookmark ||
|
|
416
|
-
!prevSelectedBookmark && selectionParent !== prevSelectionParent) {
|
|
417
|
-
this.
|
|
413
|
+
if ((prevSelectedBookmark && !selectedBookmark) ||
|
|
414
|
+
(!prevSelectedBookmark && selectionParent !== prevSelectionParent)) {
|
|
415
|
+
this._hideUI();
|
|
418
416
|
}
|
|
419
417
|
// Update the position of the panel when:
|
|
420
418
|
// * bookmark panel is in the visible stack
|
|
421
419
|
// * the selection remains on the original bookmark element,
|
|
422
420
|
// * there was no bookmark element in the first place, i.e. creating a new bookmark
|
|
423
|
-
else if (this.
|
|
421
|
+
else if (this._isUIVisible) {
|
|
424
422
|
// If still in a bookmark element, simply update the position of the balloon.
|
|
425
423
|
// If there was no bookmark (e.g. inserting one), the balloon must be moved
|
|
426
424
|
// to the new position in the editing view (a new native DOM range).
|
|
427
425
|
this._balloon.updatePosition(this._getBalloonPositionData());
|
|
428
426
|
}
|
|
427
|
+
this._updateFormButtonLabel(!!prevSelectedBookmark);
|
|
429
428
|
prevSelectedBookmark = selectedBookmark;
|
|
430
429
|
prevSelectionParent = selectionParent;
|
|
431
430
|
};
|
|
@@ -444,10 +443,31 @@ export default class BookmarkUI extends Plugin {
|
|
|
444
443
|
return !!this.formView && this._balloon.hasView(this.formView);
|
|
445
444
|
}
|
|
446
445
|
/**
|
|
447
|
-
* Returns `true` when {@link #
|
|
446
|
+
* Returns `true` when {@link #actionsView} is in the {@link #_balloon}.
|
|
447
|
+
*/
|
|
448
|
+
get _areActionsInPanel() {
|
|
449
|
+
return !!this.actionsView && this._balloon.hasView(this.actionsView);
|
|
450
|
+
}
|
|
451
|
+
/**
|
|
452
|
+
* Returns `true` when {@link #actionsView} is in the {@link #_balloon} and it is
|
|
453
|
+
* currently visible.
|
|
448
454
|
*/
|
|
449
|
-
get
|
|
450
|
-
return !!this.
|
|
455
|
+
get _areActionsVisible() {
|
|
456
|
+
return !!this.actionsView && this._balloon.visibleView === this.actionsView;
|
|
457
|
+
}
|
|
458
|
+
/**
|
|
459
|
+
* Returns `true` when {@link #actionsView} or {@link #formView} is in the {@link #_balloon}.
|
|
460
|
+
*/
|
|
461
|
+
get _isUIInPanel() {
|
|
462
|
+
return this._isFormInPanel || this._areActionsInPanel;
|
|
463
|
+
}
|
|
464
|
+
/**
|
|
465
|
+
* Returns `true` when {@link #actionsView} or {@link #formView} is in the {@link #_balloon} and it is
|
|
466
|
+
* currently visible.
|
|
467
|
+
*/
|
|
468
|
+
get _isUIVisible() {
|
|
469
|
+
const visibleView = this._balloon.visibleView;
|
|
470
|
+
return !!this.formView && visibleView == this.formView || this._areActionsVisible;
|
|
451
471
|
}
|
|
452
472
|
/**
|
|
453
473
|
* Returns positioning options for the {@link #_balloon}. They control the way the balloon is attached
|
|
@@ -472,12 +492,7 @@ export default class BookmarkUI extends Plugin {
|
|
|
472
492
|
return domConverter.mapViewToDom(viewElement);
|
|
473
493
|
};
|
|
474
494
|
}
|
|
475
|
-
|
|
476
|
-
return;
|
|
477
|
-
}
|
|
478
|
-
return {
|
|
479
|
-
target
|
|
480
|
-
};
|
|
495
|
+
return target && { target };
|
|
481
496
|
}
|
|
482
497
|
/**
|
|
483
498
|
* Returns the bookmark {@link module:engine/view/attributeelement~AttributeElement} under
|
|
@@ -565,13 +580,3 @@ function getFormValidators(editor) {
|
|
|
565
580
|
}
|
|
566
581
|
];
|
|
567
582
|
}
|
|
568
|
-
/**
|
|
569
|
-
* Returns the currently selected bookmark view element.
|
|
570
|
-
*/
|
|
571
|
-
function getSelectedBookmarkWidget(selection) {
|
|
572
|
-
const element = selection.getSelectedElement();
|
|
573
|
-
if (!element || !isWidget(element) || !element.getCustomProperty('bookmark')) {
|
|
574
|
-
return null;
|
|
575
|
-
}
|
|
576
|
-
return element;
|
|
577
|
-
}
|