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