@ckeditor/ckeditor5-bookmark 44.3.0 → 45.0.0-alpha.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/be.js +1 -0
- 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 +56 -101
- package/dist/index.css +59 -119
- package/dist/index.css.map +1 -1
- package/dist/index.js +282 -389
- package/dist/index.js.map +1 -1
- package/dist/translations/af.js +1 -1
- package/dist/translations/af.umd.js +1 -1
- package/dist/translations/ar.js +1 -1
- package/dist/translations/ar.umd.js +1 -1
- package/dist/translations/ast.js +1 -1
- package/dist/translations/ast.umd.js +1 -1
- package/dist/translations/az.js +1 -1
- package/dist/translations/az.umd.js +1 -1
- package/dist/translations/be.d.ts +8 -0
- package/dist/translations/be.js +5 -0
- package/dist/translations/be.umd.js +11 -0
- package/dist/translations/bg.js +1 -1
- package/dist/translations/bg.umd.js +1 -1
- package/dist/translations/bn.js +1 -1
- package/dist/translations/bn.umd.js +1 -1
- package/dist/translations/bs.js +1 -1
- package/dist/translations/bs.umd.js +1 -1
- package/dist/translations/ca.js +1 -1
- package/dist/translations/ca.umd.js +1 -1
- package/dist/translations/cs.js +1 -1
- package/dist/translations/cs.umd.js +1 -1
- package/dist/translations/da.js +1 -1
- package/dist/translations/da.umd.js +1 -1
- package/dist/translations/de-ch.js +1 -1
- package/dist/translations/de-ch.umd.js +1 -1
- package/dist/translations/de.js +1 -1
- package/dist/translations/de.umd.js +1 -1
- package/dist/translations/el.js +1 -1
- package/dist/translations/el.umd.js +1 -1
- package/dist/translations/en-au.js +1 -1
- package/dist/translations/en-au.umd.js +1 -1
- package/dist/translations/en-gb.js +1 -1
- package/dist/translations/en-gb.umd.js +1 -1
- package/dist/translations/en.js +1 -1
- package/dist/translations/en.umd.js +1 -1
- package/dist/translations/eo.js +1 -1
- package/dist/translations/eo.umd.js +1 -1
- package/dist/translations/es-co.js +1 -1
- package/dist/translations/es-co.umd.js +1 -1
- package/dist/translations/es.js +1 -1
- package/dist/translations/es.umd.js +1 -1
- package/dist/translations/et.js +1 -1
- package/dist/translations/et.umd.js +1 -1
- package/dist/translations/eu.js +1 -1
- package/dist/translations/eu.umd.js +1 -1
- package/dist/translations/fa.js +1 -1
- package/dist/translations/fa.umd.js +1 -1
- package/dist/translations/fi.js +1 -1
- package/dist/translations/fi.umd.js +1 -1
- package/dist/translations/fr.js +1 -1
- package/dist/translations/fr.umd.js +1 -1
- package/dist/translations/gl.js +1 -1
- package/dist/translations/gl.umd.js +1 -1
- package/dist/translations/gu.js +1 -1
- package/dist/translations/gu.umd.js +1 -1
- package/dist/translations/he.js +1 -1
- package/dist/translations/he.umd.js +1 -1
- package/dist/translations/hi.js +1 -1
- package/dist/translations/hi.umd.js +1 -1
- package/dist/translations/hr.js +1 -1
- package/dist/translations/hr.umd.js +1 -1
- package/dist/translations/hu.js +1 -1
- package/dist/translations/hu.umd.js +1 -1
- package/dist/translations/hy.js +1 -1
- package/dist/translations/hy.umd.js +1 -1
- package/dist/translations/id.js +1 -1
- package/dist/translations/id.umd.js +1 -1
- package/dist/translations/it.js +1 -1
- package/dist/translations/it.umd.js +1 -1
- package/dist/translations/ja.js +1 -1
- package/dist/translations/ja.umd.js +1 -1
- package/dist/translations/jv.js +1 -1
- package/dist/translations/jv.umd.js +1 -1
- package/dist/translations/kk.js +1 -1
- package/dist/translations/kk.umd.js +1 -1
- package/dist/translations/km.js +1 -1
- package/dist/translations/km.umd.js +1 -1
- package/dist/translations/kn.js +1 -1
- package/dist/translations/kn.umd.js +1 -1
- package/dist/translations/ko.js +1 -1
- package/dist/translations/ko.umd.js +1 -1
- package/dist/translations/ku.js +1 -1
- package/dist/translations/ku.umd.js +1 -1
- package/dist/translations/lt.js +1 -1
- package/dist/translations/lt.umd.js +1 -1
- package/dist/translations/lv.js +1 -1
- package/dist/translations/lv.umd.js +1 -1
- package/dist/translations/ms.js +1 -1
- package/dist/translations/ms.umd.js +1 -1
- package/dist/translations/nb.js +1 -1
- package/dist/translations/nb.umd.js +1 -1
- package/dist/translations/ne.js +1 -1
- package/dist/translations/ne.umd.js +1 -1
- package/dist/translations/nl.js +1 -1
- package/dist/translations/nl.umd.js +1 -1
- package/dist/translations/no.js +1 -1
- package/dist/translations/no.umd.js +1 -1
- package/dist/translations/oc.js +1 -1
- package/dist/translations/oc.umd.js +1 -1
- package/dist/translations/pl.js +1 -1
- package/dist/translations/pl.umd.js +1 -1
- package/dist/translations/pt-br.js +1 -1
- package/dist/translations/pt-br.umd.js +1 -1
- package/dist/translations/pt.js +1 -1
- package/dist/translations/pt.umd.js +1 -1
- package/dist/translations/ro.js +1 -1
- package/dist/translations/ro.umd.js +1 -1
- package/dist/translations/ru.js +1 -1
- package/dist/translations/ru.umd.js +1 -1
- package/dist/translations/si.js +1 -1
- package/dist/translations/si.umd.js +1 -1
- package/dist/translations/sk.js +1 -1
- package/dist/translations/sk.umd.js +1 -1
- package/dist/translations/sl.js +1 -1
- package/dist/translations/sl.umd.js +1 -1
- package/dist/translations/sq.js +1 -1
- package/dist/translations/sq.umd.js +1 -1
- package/dist/translations/sr-latn.js +1 -1
- package/dist/translations/sr-latn.umd.js +1 -1
- package/dist/translations/sr.js +1 -1
- package/dist/translations/sr.umd.js +1 -1
- package/dist/translations/sv.js +1 -1
- package/dist/translations/sv.umd.js +1 -1
- package/dist/translations/th.js +1 -1
- package/dist/translations/th.umd.js +1 -1
- package/dist/translations/ti.js +1 -1
- package/dist/translations/ti.umd.js +1 -1
- package/dist/translations/tk.js +1 -1
- package/dist/translations/tk.umd.js +1 -1
- package/dist/translations/tr.js +1 -1
- package/dist/translations/tr.umd.js +1 -1
- package/dist/translations/tt.js +1 -1
- package/dist/translations/tt.umd.js +1 -1
- package/dist/translations/ug.js +1 -1
- package/dist/translations/ug.umd.js +1 -1
- package/dist/translations/uk.js +1 -1
- package/dist/translations/uk.umd.js +1 -1
- package/dist/translations/ur.js +1 -1
- package/dist/translations/ur.umd.js +1 -1
- package/dist/translations/uz.js +1 -1
- package/dist/translations/uz.umd.js +1 -1
- package/dist/translations/vi.js +1 -1
- package/dist/translations/vi.umd.js +1 -1
- package/dist/translations/zh-cn.js +1 -1
- package/dist/translations/zh-cn.umd.js +1 -1
- package/dist/translations/zh.js +1 -1
- package/dist/translations/zh.umd.js +1 -1
- package/lang/contexts.json +5 -3
- package/lang/translations/af.po +16 -8
- package/lang/translations/ar.po +16 -8
- package/lang/translations/ast.po +16 -8
- package/lang/translations/az.po +16 -8
- package/lang/translations/be.po +64 -0
- package/lang/translations/bg.po +16 -8
- package/lang/translations/bn.po +16 -8
- package/lang/translations/bs.po +16 -8
- package/lang/translations/ca.po +16 -8
- package/lang/translations/cs.po +16 -8
- package/lang/translations/da.po +16 -8
- package/lang/translations/de-ch.po +16 -8
- package/lang/translations/de.po +16 -8
- package/lang/translations/el.po +16 -8
- package/lang/translations/en-au.po +16 -8
- package/lang/translations/en-gb.po +16 -8
- package/lang/translations/en.po +16 -8
- package/lang/translations/eo.po +16 -8
- package/lang/translations/es-co.po +16 -8
- package/lang/translations/es.po +16 -8
- package/lang/translations/et.po +16 -8
- package/lang/translations/eu.po +16 -8
- package/lang/translations/fa.po +16 -8
- package/lang/translations/fi.po +16 -8
- package/lang/translations/fr.po +16 -8
- package/lang/translations/gl.po +16 -8
- package/lang/translations/gu.po +16 -8
- package/lang/translations/he.po +16 -8
- package/lang/translations/hi.po +16 -8
- package/lang/translations/hr.po +16 -8
- package/lang/translations/hu.po +16 -8
- package/lang/translations/hy.po +16 -8
- package/lang/translations/id.po +16 -8
- package/lang/translations/it.po +16 -8
- package/lang/translations/ja.po +16 -8
- package/lang/translations/jv.po +16 -8
- package/lang/translations/kk.po +16 -8
- package/lang/translations/km.po +16 -8
- package/lang/translations/kn.po +16 -8
- package/lang/translations/ko.po +16 -8
- package/lang/translations/ku.po +16 -8
- package/lang/translations/lt.po +16 -8
- package/lang/translations/lv.po +16 -8
- package/lang/translations/ms.po +16 -8
- package/lang/translations/nb.po +16 -8
- package/lang/translations/ne.po +16 -8
- package/lang/translations/nl.po +16 -8
- package/lang/translations/no.po +16 -8
- package/lang/translations/oc.po +16 -8
- package/lang/translations/pl.po +16 -8
- package/lang/translations/pt-br.po +16 -8
- package/lang/translations/pt.po +16 -8
- package/lang/translations/ro.po +16 -8
- package/lang/translations/ru.po +16 -8
- package/lang/translations/si.po +16 -8
- package/lang/translations/sk.po +16 -8
- package/lang/translations/sl.po +16 -8
- package/lang/translations/sq.po +16 -8
- package/lang/translations/sr-latn.po +16 -8
- package/lang/translations/sr.po +16 -8
- package/lang/translations/sv.po +16 -8
- package/lang/translations/th.po +16 -8
- package/lang/translations/ti.po +16 -8
- package/lang/translations/tk.po +16 -8
- package/lang/translations/tr.po +16 -8
- package/lang/translations/tt.po +16 -8
- package/lang/translations/ug.po +16 -8
- package/lang/translations/uk.po +16 -8
- package/lang/translations/ur.po +16 -8
- package/lang/translations/uz.po +16 -8
- package/lang/translations/vi.po +16 -8
- package/lang/translations/zh-cn.po +16 -8
- package/lang/translations/zh.po +16 -8
- package/package.json +8 -7
- package/src/bookmarkconfig.d.ts +24 -0
- package/src/bookmarkediting.d.ts +9 -1
- package/src/bookmarkediting.js +23 -9
- package/src/bookmarkui.d.ts +24 -57
- package/src/bookmarkui.js +207 -212
- package/src/ui/bookmarkformview.d.ts +24 -14
- package/src/ui/bookmarkformview.js +103 -62
- package/theme/bookmark.css +0 -46
- package/theme/bookmarkform.css +0 -38
- package/theme/bookmarktoolbar.css +4 -0
- package/src/ui/bookmarkactionsview.d.ts +0 -102
- package/src/ui/bookmarkactionsview.js +0 -154
- package/theme/bookmarkactions.css +0 -44
package/dist/index.js
CHANGED
|
@@ -2,11 +2,12 @@
|
|
|
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
|
-
import {
|
|
6
|
-
import { toWidget, Widget } from '@ckeditor/ckeditor5-widget/dist/index.js';
|
|
7
|
-
import { View, ViewCollection, FocusCycler, submitHandler, FormHeaderView, LabeledFieldView, createLabeledInputText,
|
|
8
|
-
import {
|
|
5
|
+
import { Command, Plugin } from '@ckeditor/ckeditor5-core/dist/index.js';
|
|
6
|
+
import { toWidget, WidgetToolbarRepository, isWidget, Widget } from '@ckeditor/ckeditor5-widget/dist/index.js';
|
|
7
|
+
import { View, ViewCollection, FormRowView, FocusCycler, submitHandler, ButtonView, FormHeaderView, LabeledFieldView, createLabeledInputText, IconView, ContextualBalloon, BalloonPanelView, CssTransitionDisablerMixin, MenuBarMenuListItemButtonView, LabelView, clickOutsideHandler } from '@ckeditor/ckeditor5-ui/dist/index.js';
|
|
8
|
+
import { IconBookmarkInline, IconPencil, IconRemove, IconBookmark, IconBookmarkMedium, IconBookmarkSmall } from '@ckeditor/ckeditor5-icons/dist/index.js';
|
|
9
9
|
import { FocusTracker, KeystrokeHandler, logWarning } from '@ckeditor/ckeditor5-utils/dist/index.js';
|
|
10
|
+
import { IconPreviousArrow } from '@ckeditor/ckeditor5-icons/dist/index.js';
|
|
10
11
|
|
|
11
12
|
/**
|
|
12
13
|
* The bookmark form view controller class.
|
|
@@ -23,8 +24,11 @@ import { FocusTracker, KeystrokeHandler, logWarning } from '@ckeditor/ckeditor5-
|
|
|
23
24
|
* The ID input view.
|
|
24
25
|
*/ idInputView;
|
|
25
26
|
/**
|
|
26
|
-
* The
|
|
27
|
-
*/
|
|
27
|
+
* The Back button view displayed in the header.
|
|
28
|
+
*/ backButtonView;
|
|
29
|
+
/**
|
|
30
|
+
* A button used to submit the form.
|
|
31
|
+
*/ saveButtonView;
|
|
28
32
|
/**
|
|
29
33
|
* A collection of form child views in the form.
|
|
30
34
|
*/ children;
|
|
@@ -46,12 +50,30 @@ import { FocusTracker, KeystrokeHandler, logWarning } from '@ckeditor/ckeditor5-
|
|
|
46
50
|
* @param validators Form validators used by {@link #isValid}.
|
|
47
51
|
*/ constructor(locale, validators){
|
|
48
52
|
super(locale);
|
|
49
|
-
const t = locale.t;
|
|
50
53
|
this._validators = validators;
|
|
54
|
+
// Create buttons.
|
|
55
|
+
this.backButtonView = this._createBackButton();
|
|
56
|
+
this.saveButtonView = this._createSaveButton();
|
|
57
|
+
// Create input fields.
|
|
51
58
|
this.idInputView = this._createIdInput();
|
|
52
|
-
this.
|
|
53
|
-
|
|
54
|
-
|
|
59
|
+
this.children = this.createCollection([
|
|
60
|
+
this._createHeaderView()
|
|
61
|
+
]);
|
|
62
|
+
this.children.add(new FormRowView(locale, {
|
|
63
|
+
children: [
|
|
64
|
+
this.idInputView,
|
|
65
|
+
this.saveButtonView
|
|
66
|
+
],
|
|
67
|
+
class: [
|
|
68
|
+
'ck-form__row_with-submit',
|
|
69
|
+
'ck-form__row_large-top-padding'
|
|
70
|
+
]
|
|
71
|
+
}));
|
|
72
|
+
// Close the panel on esc key press when the **form has focus**.
|
|
73
|
+
this.keystrokes.set('Esc', (data, cancel)=>{
|
|
74
|
+
this.fire('cancel');
|
|
75
|
+
cancel();
|
|
76
|
+
});
|
|
55
77
|
this._focusCycler = new FocusCycler({
|
|
56
78
|
focusables: this._focusables,
|
|
57
79
|
focusTracker: this.focusTracker,
|
|
@@ -63,14 +85,15 @@ import { FocusTracker, KeystrokeHandler, logWarning } from '@ckeditor/ckeditor5-
|
|
|
63
85
|
focusNext: 'tab'
|
|
64
86
|
}
|
|
65
87
|
});
|
|
66
|
-
const classList = [
|
|
67
|
-
'ck',
|
|
68
|
-
'ck-bookmark-view'
|
|
69
|
-
];
|
|
70
88
|
this.setTemplate({
|
|
71
89
|
tag: 'form',
|
|
72
90
|
attributes: {
|
|
73
|
-
class:
|
|
91
|
+
class: [
|
|
92
|
+
'ck',
|
|
93
|
+
'ck-form',
|
|
94
|
+
'ck-bookmark-form',
|
|
95
|
+
'ck-responsive-form'
|
|
96
|
+
],
|
|
74
97
|
// https://github.com/ckeditor/ckeditor5-link/issues/90
|
|
75
98
|
tabindex: '-1'
|
|
76
99
|
},
|
|
@@ -85,8 +108,9 @@ import { FocusTracker, KeystrokeHandler, logWarning } from '@ckeditor/ckeditor5-
|
|
|
85
108
|
view: this
|
|
86
109
|
});
|
|
87
110
|
const childViews = [
|
|
111
|
+
this.backButtonView,
|
|
88
112
|
this.idInputView,
|
|
89
|
-
this.
|
|
113
|
+
this.saveButtonView
|
|
90
114
|
];
|
|
91
115
|
childViews.forEach((v)=>{
|
|
92
116
|
// Register the view as focusable.
|
|
@@ -107,7 +131,7 @@ import { FocusTracker, KeystrokeHandler, logWarning } from '@ckeditor/ckeditor5-
|
|
|
107
131
|
/**
|
|
108
132
|
* Focuses the fist {@link #_focusables} in the form.
|
|
109
133
|
*/ focus() {
|
|
110
|
-
this.
|
|
134
|
+
this.idInputView.focus();
|
|
111
135
|
}
|
|
112
136
|
/**
|
|
113
137
|
* Validates the form and returns `false` when some fields are invalid.
|
|
@@ -133,36 +157,41 @@ import { FocusTracker, KeystrokeHandler, logWarning } from '@ckeditor/ckeditor5-
|
|
|
133
157
|
this.idInputView.errorText = null;
|
|
134
158
|
}
|
|
135
159
|
/**
|
|
136
|
-
* Creates
|
|
137
|
-
*/
|
|
138
|
-
const
|
|
139
|
-
const
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
160
|
+
* Creates a back button view that cancels the form.
|
|
161
|
+
*/ _createBackButton() {
|
|
162
|
+
const t = this.locale.t;
|
|
163
|
+
const backButton = new ButtonView(this.locale);
|
|
164
|
+
backButton.set({
|
|
165
|
+
class: 'ck-button-back',
|
|
166
|
+
label: t('Back'),
|
|
167
|
+
icon: IconPreviousArrow,
|
|
168
|
+
tooltip: true
|
|
169
|
+
});
|
|
170
|
+
backButton.delegate('execute').to(this, 'cancel');
|
|
171
|
+
return backButton;
|
|
145
172
|
}
|
|
146
173
|
/**
|
|
147
|
-
* Creates
|
|
148
|
-
*/
|
|
149
|
-
const
|
|
150
|
-
const
|
|
151
|
-
|
|
152
|
-
'
|
|
153
|
-
|
|
154
|
-
'
|
|
155
|
-
|
|
156
|
-
children.add(this.idInputView);
|
|
157
|
-
children.add(this.buttonView);
|
|
158
|
-
view.setTemplate({
|
|
159
|
-
tag: 'div',
|
|
160
|
-
attributes: {
|
|
161
|
-
class: classList
|
|
162
|
-
},
|
|
163
|
-
children
|
|
174
|
+
* Creates a save button view that saves the bookmark.
|
|
175
|
+
*/ _createSaveButton() {
|
|
176
|
+
const t = this.locale.t;
|
|
177
|
+
const saveButton = new ButtonView(this.locale);
|
|
178
|
+
saveButton.set({
|
|
179
|
+
label: t('Save'),
|
|
180
|
+
withText: true,
|
|
181
|
+
type: 'submit',
|
|
182
|
+
class: 'ck-button-action ck-button-bold'
|
|
164
183
|
});
|
|
165
|
-
return
|
|
184
|
+
return saveButton;
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* Creates a header view for the form.
|
|
188
|
+
*/ _createHeaderView() {
|
|
189
|
+
const t = this.locale.t;
|
|
190
|
+
const header = new FormHeaderView(this.locale, {
|
|
191
|
+
label: t('Bookmark')
|
|
192
|
+
});
|
|
193
|
+
header.children.add(this.backButtonView, 0);
|
|
194
|
+
return header;
|
|
166
195
|
}
|
|
167
196
|
/**
|
|
168
197
|
* Creates a labeled input view.
|
|
@@ -173,27 +202,9 @@ import { FocusTracker, KeystrokeHandler, logWarning } from '@ckeditor/ckeditor5-
|
|
|
173
202
|
const labeledInput = new LabeledFieldView(this.locale, createLabeledInputText);
|
|
174
203
|
labeledInput.label = t('Bookmark name');
|
|
175
204
|
labeledInput.infoText = t('Enter the bookmark name without spaces.');
|
|
205
|
+
labeledInput.class = 'ck-labeled-field-view_full-width';
|
|
176
206
|
return labeledInput;
|
|
177
207
|
}
|
|
178
|
-
/**
|
|
179
|
-
* Creates a button view.
|
|
180
|
-
*
|
|
181
|
-
* @param label The button label.
|
|
182
|
-
* @param className The additional button CSS class name.
|
|
183
|
-
* @returns The button view instance.
|
|
184
|
-
*/ _createButton(label, className) {
|
|
185
|
-
const button = new ButtonView(this.locale);
|
|
186
|
-
button.set({
|
|
187
|
-
label,
|
|
188
|
-
withText: true
|
|
189
|
-
});
|
|
190
|
-
button.extendTemplate({
|
|
191
|
-
attributes: {
|
|
192
|
-
class: className
|
|
193
|
-
}
|
|
194
|
-
});
|
|
195
|
-
return button;
|
|
196
|
-
}
|
|
197
208
|
/**
|
|
198
209
|
* The native DOM `value` of the {@link #idInputView} element.
|
|
199
210
|
*
|
|
@@ -208,149 +219,6 @@ import { FocusTracker, KeystrokeHandler, logWarning } from '@ckeditor/ckeditor5-
|
|
|
208
219
|
}
|
|
209
220
|
}
|
|
210
221
|
|
|
211
|
-
/**
|
|
212
|
-
* The bookmark actions view class. This view displays the bookmark preview, allows
|
|
213
|
-
* removing or editing the bookmark.
|
|
214
|
-
*/ class BookmarkActionsView extends View {
|
|
215
|
-
/**
|
|
216
|
-
* Tracks information about DOM focus in the actions.
|
|
217
|
-
*/ focusTracker = new FocusTracker();
|
|
218
|
-
/**
|
|
219
|
-
* An instance of the {@link module:utils/keystrokehandler~KeystrokeHandler}.
|
|
220
|
-
*/ keystrokes = new KeystrokeHandler();
|
|
221
|
-
/**
|
|
222
|
-
* The bookmark preview view.
|
|
223
|
-
*/ bookmarkPreviewView;
|
|
224
|
-
/**
|
|
225
|
-
* The remove button view.
|
|
226
|
-
*/ removeButtonView;
|
|
227
|
-
/**
|
|
228
|
-
* The edit bookmark button view.
|
|
229
|
-
*/ editButtonView;
|
|
230
|
-
/**
|
|
231
|
-
* A collection of views that can be focused in the view.
|
|
232
|
-
*/ _focusables = new ViewCollection();
|
|
233
|
-
/**
|
|
234
|
-
* Helps cycling over {@link #_focusables} in the view.
|
|
235
|
-
*/ _focusCycler;
|
|
236
|
-
/**
|
|
237
|
-
* @inheritDoc
|
|
238
|
-
*/ constructor(locale){
|
|
239
|
-
super(locale);
|
|
240
|
-
const t = locale.t;
|
|
241
|
-
this.bookmarkPreviewView = this._createBookmarkPreviewView();
|
|
242
|
-
this.removeButtonView = this._createButton(t('Remove bookmark'), icons.remove, 'remove', this.bookmarkPreviewView);
|
|
243
|
-
this.editButtonView = this._createButton(t('Edit bookmark'), icons.pencil, 'edit', this.bookmarkPreviewView);
|
|
244
|
-
this.set('id', undefined);
|
|
245
|
-
this._focusCycler = new FocusCycler({
|
|
246
|
-
focusables: this._focusables,
|
|
247
|
-
focusTracker: this.focusTracker,
|
|
248
|
-
keystrokeHandler: this.keystrokes,
|
|
249
|
-
actions: {
|
|
250
|
-
// Navigate fields backwards using the Shift + Tab keystroke.
|
|
251
|
-
focusPrevious: 'shift + tab',
|
|
252
|
-
// Navigate fields forwards using the Tab key.
|
|
253
|
-
focusNext: 'tab'
|
|
254
|
-
}
|
|
255
|
-
});
|
|
256
|
-
this.setTemplate({
|
|
257
|
-
tag: 'div',
|
|
258
|
-
attributes: {
|
|
259
|
-
class: [
|
|
260
|
-
'ck',
|
|
261
|
-
'ck-bookmark-actions',
|
|
262
|
-
'ck-responsive-form'
|
|
263
|
-
],
|
|
264
|
-
// https://github.com/ckeditor/ckeditor5-link/issues/90
|
|
265
|
-
tabindex: '-1'
|
|
266
|
-
},
|
|
267
|
-
children: [
|
|
268
|
-
this.bookmarkPreviewView,
|
|
269
|
-
this.editButtonView,
|
|
270
|
-
this.removeButtonView
|
|
271
|
-
]
|
|
272
|
-
});
|
|
273
|
-
}
|
|
274
|
-
/**
|
|
275
|
-
* @inheritDoc
|
|
276
|
-
*/ render() {
|
|
277
|
-
super.render();
|
|
278
|
-
const childViews = [
|
|
279
|
-
this.editButtonView,
|
|
280
|
-
this.removeButtonView
|
|
281
|
-
];
|
|
282
|
-
childViews.forEach((v)=>{
|
|
283
|
-
// Register the view as focusable.
|
|
284
|
-
this._focusables.add(v);
|
|
285
|
-
// Register the view in the focus tracker.
|
|
286
|
-
this.focusTracker.add(v.element);
|
|
287
|
-
});
|
|
288
|
-
// Start listening for the keystrokes coming from #element.
|
|
289
|
-
this.keystrokes.listenTo(this.element);
|
|
290
|
-
}
|
|
291
|
-
/**
|
|
292
|
-
* @inheritDoc
|
|
293
|
-
*/ destroy() {
|
|
294
|
-
super.destroy();
|
|
295
|
-
this.focusTracker.destroy();
|
|
296
|
-
this.keystrokes.destroy();
|
|
297
|
-
}
|
|
298
|
-
/**
|
|
299
|
-
* Focuses the fist {@link #_focusables} in the actions.
|
|
300
|
-
*/ focus() {
|
|
301
|
-
this._focusCycler.focusFirst();
|
|
302
|
-
}
|
|
303
|
-
/**
|
|
304
|
-
* Creates a button view.
|
|
305
|
-
*
|
|
306
|
-
* @param label The button label.
|
|
307
|
-
* @param icon The button icon.
|
|
308
|
-
* @param eventName An event name that the `ButtonView#execute` event will be delegated to.
|
|
309
|
-
* @param additionalLabel An additional label outside the button.
|
|
310
|
-
* @returns The button view instance.
|
|
311
|
-
*/ _createButton(label, icon, eventName, additionalLabel) {
|
|
312
|
-
const button = new ButtonView(this.locale);
|
|
313
|
-
button.set({
|
|
314
|
-
label,
|
|
315
|
-
icon,
|
|
316
|
-
tooltip: true
|
|
317
|
-
});
|
|
318
|
-
button.delegate('execute').to(this, eventName);
|
|
319
|
-
// Since button label `id` is bound to the `ariaLabelledBy` property
|
|
320
|
-
// we need to modify this binding to include only the first ID token
|
|
321
|
-
// as this button will be labeled by multiple labels.
|
|
322
|
-
button.labelView.unbind('id');
|
|
323
|
-
button.labelView.bind('id').to(button, 'ariaLabelledBy', (ariaLabelledBy)=>{
|
|
324
|
-
return getFirstToken(ariaLabelledBy);
|
|
325
|
-
});
|
|
326
|
-
button.ariaLabelledBy = `${button.ariaLabelledBy} ${additionalLabel.id}`;
|
|
327
|
-
return button;
|
|
328
|
-
}
|
|
329
|
-
/**
|
|
330
|
-
* Creates a bookmark name preview label.
|
|
331
|
-
*
|
|
332
|
-
* @returns The label view instance.
|
|
333
|
-
*/ _createBookmarkPreviewView() {
|
|
334
|
-
const label = new LabelView(this.locale);
|
|
335
|
-
label.extendTemplate({
|
|
336
|
-
attributes: {
|
|
337
|
-
class: [
|
|
338
|
-
'ck',
|
|
339
|
-
'ck-bookmark-actions__preview'
|
|
340
|
-
]
|
|
341
|
-
}
|
|
342
|
-
});
|
|
343
|
-
// Bind label text with the bookmark ID.
|
|
344
|
-
label.bind('text').to(this, 'id');
|
|
345
|
-
return label;
|
|
346
|
-
}
|
|
347
|
-
}
|
|
348
|
-
/**
|
|
349
|
-
* Returns the first token from space separated token list.
|
|
350
|
-
*/ function getFirstToken(tokenList) {
|
|
351
|
-
return tokenList.split(' ')[0];
|
|
352
|
-
}
|
|
353
|
-
|
|
354
222
|
/**
|
|
355
223
|
* @license Copyright (c) 2003-2025, CKSource Holding sp. z o.o. All rights reserved.
|
|
356
224
|
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-licensing-options
|
|
@@ -548,6 +416,19 @@ import { FocusTracker, KeystrokeHandler, logWarning } from '@ckeditor/ckeditor5-
|
|
|
548
416
|
*/ static get isOfficialPlugin() {
|
|
549
417
|
return true;
|
|
550
418
|
}
|
|
419
|
+
/**
|
|
420
|
+
* @inheritDoc
|
|
421
|
+
*/ constructor(editor){
|
|
422
|
+
super(editor);
|
|
423
|
+
editor.config.define('bookmark', {
|
|
424
|
+
toolbar: [
|
|
425
|
+
'bookmarkPreview',
|
|
426
|
+
'|',
|
|
427
|
+
'editBookmark',
|
|
428
|
+
'removeBookmark'
|
|
429
|
+
]
|
|
430
|
+
});
|
|
431
|
+
}
|
|
551
432
|
/**
|
|
552
433
|
* @inheritDoc
|
|
553
434
|
*/ init() {
|
|
@@ -570,6 +451,11 @@ import { FocusTracker, KeystrokeHandler, logWarning } from '@ckeditor/ckeditor5-
|
|
|
570
451
|
}
|
|
571
452
|
return null;
|
|
572
453
|
}
|
|
454
|
+
/**
|
|
455
|
+
* Returns all unique bookmark names existing in the content.
|
|
456
|
+
*/ getAllBookmarkNames() {
|
|
457
|
+
return new Set(this._bookmarkElements.values());
|
|
458
|
+
}
|
|
573
459
|
/**
|
|
574
460
|
* Defines the schema for the bookmark feature.
|
|
575
461
|
*/ _defineSchema() {
|
|
@@ -622,6 +508,7 @@ import { FocusTracker, KeystrokeHandler, logWarning } from '@ckeditor/ckeditor5-
|
|
|
622
508
|
}, [
|
|
623
509
|
this._createBookmarkUIElement(writer)
|
|
624
510
|
]);
|
|
511
|
+
writer.setCustomProperty('bookmark', true, containerElement);
|
|
625
512
|
this._bookmarkElements.set(modelElement, id);
|
|
626
513
|
// `getFillerOffset` is not needed to set here, because `toWidget` has already covered it.
|
|
627
514
|
const labelCreator = ()=>`${id} ${t('bookmark widget')}`;
|
|
@@ -641,7 +528,7 @@ import { FocusTracker, KeystrokeHandler, logWarning } from '@ckeditor/ckeditor5-
|
|
|
641
528
|
const domElement = this.toDomElement(domDocument);
|
|
642
529
|
const icon = new IconView();
|
|
643
530
|
icon.set({
|
|
644
|
-
content:
|
|
531
|
+
content: IconBookmarkInline,
|
|
645
532
|
isColorInherited: false
|
|
646
533
|
});
|
|
647
534
|
icon.render();
|
|
@@ -751,9 +638,6 @@ const VISUAL_SELECTION_MARKER_NAME = 'bookmark-ui';
|
|
|
751
638
|
* It registers the `'bookmark'` UI button in the editor's {@link module:ui/componentfactory~ComponentFactory component factory}
|
|
752
639
|
* which inserts the `bookmark` element upon selection.
|
|
753
640
|
*/ class BookmarkUI extends Plugin {
|
|
754
|
-
/**
|
|
755
|
-
* The actions view displayed inside of the balloon.
|
|
756
|
-
*/ actionsView = null;
|
|
757
641
|
/**
|
|
758
642
|
* The form view displayed inside the balloon.
|
|
759
643
|
*/ formView = null;
|
|
@@ -765,7 +649,8 @@ const VISUAL_SELECTION_MARKER_NAME = 'bookmark-ui';
|
|
|
765
649
|
*/ static get requires() {
|
|
766
650
|
return [
|
|
767
651
|
BookmarkEditing,
|
|
768
|
-
ContextualBalloon
|
|
652
|
+
ContextualBalloon,
|
|
653
|
+
WidgetToolbarRepository
|
|
769
654
|
];
|
|
770
655
|
}
|
|
771
656
|
/**
|
|
@@ -782,11 +667,13 @@ const VISUAL_SELECTION_MARKER_NAME = 'bookmark-ui';
|
|
|
782
667
|
* @inheritDoc
|
|
783
668
|
*/ init() {
|
|
784
669
|
const editor = this.editor;
|
|
785
|
-
editor.editing.view.addObserver(ClickObserver);
|
|
786
670
|
this._balloon = editor.plugins.get(ContextualBalloon);
|
|
671
|
+
// Register the link provider in link plugin to display the link form.
|
|
672
|
+
if (editor.plugins.has('LinkUI')) {
|
|
673
|
+
this._registerLinkProvider();
|
|
674
|
+
}
|
|
787
675
|
// Create toolbar buttons.
|
|
788
|
-
this.
|
|
789
|
-
this._enableBalloonActivators();
|
|
676
|
+
this._registerComponents();
|
|
790
677
|
// Renders a fake visual selection marker on an expanded selection.
|
|
791
678
|
editor.conversion.for('editingDowncast').markerToHighlight({
|
|
792
679
|
model: VISUAL_SELECTION_MARKER_NAME,
|
|
@@ -812,6 +699,34 @@ const VISUAL_SELECTION_MARKER_NAME = 'bookmark-ui';
|
|
|
812
699
|
}
|
|
813
700
|
});
|
|
814
701
|
}
|
|
702
|
+
/**
|
|
703
|
+
* @inheritDoc
|
|
704
|
+
*/ afterInit() {
|
|
705
|
+
const editor = this.editor;
|
|
706
|
+
const t = editor.locale.t;
|
|
707
|
+
const widgetToolbarRepository = this.editor.plugins.get(WidgetToolbarRepository);
|
|
708
|
+
const defaultPositions = BalloonPanelView.defaultPositions;
|
|
709
|
+
widgetToolbarRepository.register('bookmark', {
|
|
710
|
+
ariaLabel: t('Bookmark toolbar'),
|
|
711
|
+
items: editor.config.get('bookmark.toolbar'),
|
|
712
|
+
getRelatedElement: getSelectedBookmarkWidget,
|
|
713
|
+
// Override positions to the same list as for balloon panel default
|
|
714
|
+
// so widget toolbar will try to use same position as form view.
|
|
715
|
+
positions: [
|
|
716
|
+
defaultPositions.southArrowNorth,
|
|
717
|
+
defaultPositions.southArrowNorthMiddleWest,
|
|
718
|
+
defaultPositions.southArrowNorthMiddleEast,
|
|
719
|
+
defaultPositions.southArrowNorthWest,
|
|
720
|
+
defaultPositions.southArrowNorthEast,
|
|
721
|
+
defaultPositions.northArrowSouth,
|
|
722
|
+
defaultPositions.northArrowSouthMiddleWest,
|
|
723
|
+
defaultPositions.northArrowSouthMiddleEast,
|
|
724
|
+
defaultPositions.northArrowSouthWest,
|
|
725
|
+
defaultPositions.northArrowSouthEast,
|
|
726
|
+
defaultPositions.viewportStickyNorth
|
|
727
|
+
]
|
|
728
|
+
});
|
|
729
|
+
}
|
|
815
730
|
/**
|
|
816
731
|
* @inheritDoc
|
|
817
732
|
*/ destroy() {
|
|
@@ -820,49 +735,20 @@ const VISUAL_SELECTION_MARKER_NAME = 'bookmark-ui';
|
|
|
820
735
|
if (this.formView) {
|
|
821
736
|
this.formView.destroy();
|
|
822
737
|
}
|
|
823
|
-
if (this.actionsView) {
|
|
824
|
-
this.actionsView.destroy();
|
|
825
|
-
}
|
|
826
738
|
}
|
|
827
739
|
/**
|
|
828
740
|
* Creates views.
|
|
829
741
|
*/ _createViews() {
|
|
830
|
-
this.actionsView = this._createActionsView();
|
|
831
742
|
this.formView = this._createFormView();
|
|
832
743
|
// Attach lifecycle actions to the the balloon.
|
|
833
744
|
this._enableUserBalloonInteractions();
|
|
834
745
|
}
|
|
835
|
-
/**
|
|
836
|
-
* Creates the {@link module:bookmark/ui/bookmarkactionsview~BookmarkActionsView} instance.
|
|
837
|
-
*/ _createActionsView() {
|
|
838
|
-
const editor = this.editor;
|
|
839
|
-
const actionsView = new BookmarkActionsView(editor.locale);
|
|
840
|
-
const updateBookmarkCommand = editor.commands.get('updateBookmark');
|
|
841
|
-
const deleteCommand = editor.commands.get('delete');
|
|
842
|
-
actionsView.bind('id').to(updateBookmarkCommand, 'value');
|
|
843
|
-
actionsView.editButtonView.bind('isEnabled').to(updateBookmarkCommand);
|
|
844
|
-
actionsView.removeButtonView.bind('isEnabled').to(deleteCommand);
|
|
845
|
-
// Display edit form view after clicking on the "Edit" button.
|
|
846
|
-
this.listenTo(actionsView, 'edit', ()=>{
|
|
847
|
-
this._addFormView();
|
|
848
|
-
});
|
|
849
|
-
// Execute remove command after clicking on the "Remove" button.
|
|
850
|
-
this.listenTo(actionsView, 'remove', ()=>{
|
|
851
|
-
this._hideUI();
|
|
852
|
-
editor.execute('delete');
|
|
853
|
-
});
|
|
854
|
-
// Close the panel on esc key press when the **actions have focus**.
|
|
855
|
-
actionsView.keystrokes.set('Esc', (data, cancel)=>{
|
|
856
|
-
this._hideUI();
|
|
857
|
-
cancel();
|
|
858
|
-
});
|
|
859
|
-
return actionsView;
|
|
860
|
-
}
|
|
861
746
|
/**
|
|
862
747
|
* Creates the {@link module:bookmark/ui/bookmarkformview~BookmarkFormView} instance.
|
|
863
748
|
*/ _createFormView() {
|
|
864
749
|
const editor = this.editor;
|
|
865
750
|
const locale = editor.locale;
|
|
751
|
+
const t = locale.t;
|
|
866
752
|
const insertBookmarkCommand = editor.commands.get('insertBookmark');
|
|
867
753
|
const updateBookmarkCommand = editor.commands.get('updateBookmark');
|
|
868
754
|
const commands = [
|
|
@@ -871,10 +757,15 @@ const VISUAL_SELECTION_MARKER_NAME = 'bookmark-ui';
|
|
|
871
757
|
];
|
|
872
758
|
const formView = new (CssTransitionDisablerMixin(BookmarkFormView))(locale, getFormValidators(editor));
|
|
873
759
|
formView.idInputView.fieldView.bind('value').to(updateBookmarkCommand, 'value');
|
|
760
|
+
formView.saveButtonView.bind('label').to(updateBookmarkCommand, 'value', (value)=>value ? t('Save') : t('Insert'));
|
|
874
761
|
// Form elements should be read-only when corresponding commands are disabled.
|
|
875
762
|
formView.idInputView.bind('isEnabled').toMany(commands, 'isEnabled', (...areEnabled)=>areEnabled.some((isEnabled)=>isEnabled));
|
|
876
763
|
// Disable the "save" button if the command is disabled.
|
|
877
|
-
formView.
|
|
764
|
+
formView.saveButtonView.bind('isEnabled').toMany(commands, 'isEnabled', (...areEnabled)=>areEnabled.some((isEnabled)=>isEnabled));
|
|
765
|
+
// Close the panel on form after clicking back button.
|
|
766
|
+
this.listenTo(formView, 'cancel', ()=>{
|
|
767
|
+
this._hideFormView();
|
|
768
|
+
});
|
|
878
769
|
// Execute link command after clicking the "Save" button.
|
|
879
770
|
this.listenTo(formView, 'submit', ()=>{
|
|
880
771
|
if (formView.isValid()) {
|
|
@@ -888,39 +779,131 @@ const VISUAL_SELECTION_MARKER_NAME = 'bookmark-ui';
|
|
|
888
779
|
bookmarkId: value
|
|
889
780
|
});
|
|
890
781
|
}
|
|
891
|
-
this.
|
|
782
|
+
this._hideFormView();
|
|
892
783
|
}
|
|
893
784
|
});
|
|
894
785
|
// Update balloon position when form error changes.
|
|
895
786
|
this.listenTo(formView.idInputView, 'change:errorText', ()=>{
|
|
896
787
|
editor.ui.update();
|
|
897
788
|
});
|
|
898
|
-
// Close the panel on esc key press when the **form has focus**.
|
|
899
|
-
formView.keystrokes.set('Esc', (data, cancel)=>{
|
|
900
|
-
this._closeFormView();
|
|
901
|
-
cancel();
|
|
902
|
-
});
|
|
903
789
|
return formView;
|
|
904
790
|
}
|
|
791
|
+
/**
|
|
792
|
+
* Creates link form menu list entry, so it'll be possible to access
|
|
793
|
+
* the list of the bookmarks from the link form.
|
|
794
|
+
*/ _registerLinkProvider() {
|
|
795
|
+
const t = this.editor.locale.t;
|
|
796
|
+
const linksUI = this.editor.plugins.get('LinkUI');
|
|
797
|
+
const bookmarkEditing = this.editor.plugins.get(BookmarkEditing);
|
|
798
|
+
const getListItems = ()=>Array.from(bookmarkEditing.getAllBookmarkNames()).sort((a, b)=>a.localeCompare(b)).map((bookmarkId)=>({
|
|
799
|
+
id: bookmarkId,
|
|
800
|
+
href: `#${bookmarkId}`,
|
|
801
|
+
label: bookmarkId,
|
|
802
|
+
icon: IconBookmarkMedium
|
|
803
|
+
}));
|
|
804
|
+
const getItem = (href)=>{
|
|
805
|
+
const bookmark = [
|
|
806
|
+
...bookmarkEditing.getAllBookmarkNames()
|
|
807
|
+
].find((item)=>`#${item}` === href);
|
|
808
|
+
if (!bookmark) {
|
|
809
|
+
return null;
|
|
810
|
+
}
|
|
811
|
+
return {
|
|
812
|
+
href,
|
|
813
|
+
label: bookmark,
|
|
814
|
+
icon: IconBookmarkSmall,
|
|
815
|
+
tooltip: t('Scroll to bookmark')
|
|
816
|
+
};
|
|
817
|
+
};
|
|
818
|
+
linksUI.registerLinksListProvider({
|
|
819
|
+
label: t('Bookmarks'),
|
|
820
|
+
emptyListPlaceholder: t('No bookmarks available.'),
|
|
821
|
+
navigate: ({ href })=>this._scrollToBookmark(href),
|
|
822
|
+
getListItems,
|
|
823
|
+
getItem
|
|
824
|
+
});
|
|
825
|
+
}
|
|
826
|
+
/**
|
|
827
|
+
* Scrolls the editor to the bookmark with the given id.
|
|
828
|
+
*/ _scrollToBookmark(href) {
|
|
829
|
+
const bookmarkEditing = this.editor.plugins.get(BookmarkEditing);
|
|
830
|
+
const bookmarkElement = bookmarkEditing.getElementForBookmarkId(href.slice(1));
|
|
831
|
+
if (!bookmarkElement) {
|
|
832
|
+
return false;
|
|
833
|
+
}
|
|
834
|
+
this.editor.model.change((writer)=>{
|
|
835
|
+
writer.setSelection(bookmarkElement, 'on');
|
|
836
|
+
});
|
|
837
|
+
this.editor.editing.view.scrollToTheSelection({
|
|
838
|
+
alignToTop: true,
|
|
839
|
+
forceScroll: true
|
|
840
|
+
});
|
|
841
|
+
return true;
|
|
842
|
+
}
|
|
905
843
|
/**
|
|
906
844
|
* Creates a toolbar Bookmark button. Clicking this button will show
|
|
907
845
|
* a {@link #_balloon} attached to the selection.
|
|
908
|
-
*/
|
|
846
|
+
*/ _registerComponents() {
|
|
909
847
|
const editor = this.editor;
|
|
910
848
|
editor.ui.componentFactory.add('bookmark', ()=>{
|
|
911
|
-
const buttonView = this.
|
|
849
|
+
const buttonView = this._createBookmarkButton(ButtonView);
|
|
912
850
|
buttonView.set({
|
|
913
851
|
tooltip: true
|
|
914
852
|
});
|
|
915
853
|
return buttonView;
|
|
916
854
|
});
|
|
917
855
|
editor.ui.componentFactory.add('menuBar:bookmark', ()=>{
|
|
918
|
-
return this.
|
|
856
|
+
return this._createBookmarkButton(MenuBarMenuListItemButtonView);
|
|
857
|
+
});
|
|
858
|
+
// Bookmark toolbar buttons.
|
|
859
|
+
editor.ui.componentFactory.add('bookmarkPreview', (locale)=>{
|
|
860
|
+
const updateBookmarkCommand = editor.commands.get('updateBookmark');
|
|
861
|
+
const label = new LabelView(locale);
|
|
862
|
+
label.extendTemplate({
|
|
863
|
+
attributes: {
|
|
864
|
+
class: [
|
|
865
|
+
'ck-bookmark-toolbar__preview'
|
|
866
|
+
]
|
|
867
|
+
}
|
|
868
|
+
});
|
|
869
|
+
label.bind('text').to(updateBookmarkCommand, 'value');
|
|
870
|
+
return label;
|
|
871
|
+
});
|
|
872
|
+
editor.ui.componentFactory.add('editBookmark', (locale)=>{
|
|
873
|
+
const updateBookmarkCommand = editor.commands.get('updateBookmark');
|
|
874
|
+
const button = new ButtonView(locale);
|
|
875
|
+
const t = locale.t;
|
|
876
|
+
button.set({
|
|
877
|
+
label: t('Edit bookmark'),
|
|
878
|
+
icon: IconPencil,
|
|
879
|
+
tooltip: true
|
|
880
|
+
});
|
|
881
|
+
button.bind('isEnabled').to(updateBookmarkCommand);
|
|
882
|
+
this.listenTo(button, 'execute', ()=>{
|
|
883
|
+
this._showFormView();
|
|
884
|
+
});
|
|
885
|
+
return button;
|
|
886
|
+
});
|
|
887
|
+
editor.ui.componentFactory.add('removeBookmark', (locale)=>{
|
|
888
|
+
const deleteCommand = editor.commands.get('delete');
|
|
889
|
+
const button = new ButtonView(locale);
|
|
890
|
+
const t = locale.t;
|
|
891
|
+
button.set({
|
|
892
|
+
label: t('Remove bookmark'),
|
|
893
|
+
icon: IconRemove,
|
|
894
|
+
tooltip: true
|
|
895
|
+
});
|
|
896
|
+
button.bind('isEnabled').to(deleteCommand);
|
|
897
|
+
this.listenTo(button, 'execute', ()=>{
|
|
898
|
+
editor.execute('delete');
|
|
899
|
+
editor.editing.view.focus();
|
|
900
|
+
});
|
|
901
|
+
return button;
|
|
919
902
|
});
|
|
920
903
|
}
|
|
921
904
|
/**
|
|
922
905
|
* Creates a button for `bookmark` command to use either in toolbar or in menu bar.
|
|
923
|
-
*/
|
|
906
|
+
*/ _createBookmarkButton(ButtonClass) {
|
|
924
907
|
const editor = this.editor;
|
|
925
908
|
const locale = editor.locale;
|
|
926
909
|
const view = new ButtonClass(locale);
|
|
@@ -929,10 +912,10 @@ const VISUAL_SELECTION_MARKER_NAME = 'bookmark-ui';
|
|
|
929
912
|
const t = locale.t;
|
|
930
913
|
view.set({
|
|
931
914
|
label: t('Bookmark'),
|
|
932
|
-
icon:
|
|
915
|
+
icon: IconBookmark
|
|
933
916
|
});
|
|
934
917
|
// Execute the command.
|
|
935
|
-
this.listenTo(view, 'execute', ()=>this.
|
|
918
|
+
this.listenTo(view, 'execute', ()=>this._showFormView());
|
|
936
919
|
view.bind('isEnabled').toMany([
|
|
937
920
|
insertCommand,
|
|
938
921
|
updateCommand
|
|
@@ -940,75 +923,25 @@ const VISUAL_SELECTION_MARKER_NAME = 'bookmark-ui';
|
|
|
940
923
|
view.bind('isOn').to(updateCommand, 'value', (value)=>!!value);
|
|
941
924
|
return view;
|
|
942
925
|
}
|
|
943
|
-
/**
|
|
944
|
-
* Attaches actions that control whether the balloon panel containing the
|
|
945
|
-
* {@link #formView} should be displayed.
|
|
946
|
-
*/ _enableBalloonActivators() {
|
|
947
|
-
const editor = this.editor;
|
|
948
|
-
const viewDocument = editor.editing.view.document;
|
|
949
|
-
// Handle click on view document and show panel when selection is placed inside the bookmark element.
|
|
950
|
-
// Keep panel open until selection will be inside the same bookmark element.
|
|
951
|
-
this.listenTo(viewDocument, 'click', ()=>{
|
|
952
|
-
const bookmark = this._getSelectedBookmarkElement();
|
|
953
|
-
if (bookmark) {
|
|
954
|
-
// Then show panel but keep focus inside editor editable.
|
|
955
|
-
this._showUI();
|
|
956
|
-
}
|
|
957
|
-
});
|
|
958
|
-
}
|
|
959
926
|
/**
|
|
960
927
|
* Attaches actions that control whether the balloon panel containing the
|
|
961
928
|
* {@link #formView} is visible or not.
|
|
962
929
|
*/ _enableUserBalloonInteractions() {
|
|
963
|
-
// Focus the form if the balloon is visible and the Tab key has been pressed.
|
|
964
|
-
this.editor.keystrokes.set('Tab', (data, cancel)=>{
|
|
965
|
-
if (this._areActionsVisible && !this.actionsView.focusTracker.isFocused) {
|
|
966
|
-
this.actionsView.focus();
|
|
967
|
-
cancel();
|
|
968
|
-
}
|
|
969
|
-
}, {
|
|
970
|
-
// Use the high priority because the bookmark UI navigation is more important
|
|
971
|
-
// than other feature's actions, e.g. list indentation.
|
|
972
|
-
priority: 'high'
|
|
973
|
-
});
|
|
974
930
|
// Close the panel on the Esc key press when the editable has focus and the balloon is visible.
|
|
975
931
|
this.editor.keystrokes.set('Esc', (data, cancel)=>{
|
|
976
|
-
if (this.
|
|
977
|
-
this.
|
|
932
|
+
if (this._isFormVisible) {
|
|
933
|
+
this._hideFormView();
|
|
978
934
|
cancel();
|
|
979
935
|
}
|
|
980
936
|
});
|
|
981
937
|
// Close on click outside of balloon panel element.
|
|
982
938
|
clickOutsideHandler({
|
|
983
939
|
emitter: this.formView,
|
|
984
|
-
activator: ()=>this.
|
|
940
|
+
activator: ()=>this._isFormInPanel,
|
|
985
941
|
contextElements: ()=>[
|
|
986
942
|
this._balloon.view.element
|
|
987
943
|
],
|
|
988
|
-
callback: ()=>this.
|
|
989
|
-
});
|
|
990
|
-
}
|
|
991
|
-
/**
|
|
992
|
-
* Updates the button label. If bookmark is selected label is set to 'Update' otherwise
|
|
993
|
-
* it is 'Insert'.
|
|
994
|
-
*/ _updateFormButtonLabel(isBookmarkSelected) {
|
|
995
|
-
const t = this.editor.locale.t;
|
|
996
|
-
this.formView.buttonView.label = isBookmarkSelected ? t('Update') : t('Insert');
|
|
997
|
-
}
|
|
998
|
-
/**
|
|
999
|
-
* Adds the {@link #actionsView} to the {@link #_balloon}.
|
|
1000
|
-
*
|
|
1001
|
-
* @internal
|
|
1002
|
-
*/ _addActionsView() {
|
|
1003
|
-
if (!this.actionsView) {
|
|
1004
|
-
this._createViews();
|
|
1005
|
-
}
|
|
1006
|
-
if (this._areActionsInPanel) {
|
|
1007
|
-
return;
|
|
1008
|
-
}
|
|
1009
|
-
this._balloon.add({
|
|
1010
|
-
view: this.actionsView,
|
|
1011
|
-
position: this._getBalloonPositionData()
|
|
944
|
+
callback: ()=>this._hideFormView()
|
|
1012
945
|
});
|
|
1013
946
|
}
|
|
1014
947
|
/**
|
|
@@ -1020,14 +953,14 @@ const VISUAL_SELECTION_MARKER_NAME = 'bookmark-ui';
|
|
|
1020
953
|
if (this._isFormInPanel) {
|
|
1021
954
|
return;
|
|
1022
955
|
}
|
|
1023
|
-
const
|
|
1024
|
-
const updateBookmarkCommand = editor.commands.get('updateBookmark');
|
|
956
|
+
const updateBookmarkCommand = this.editor.commands.get('updateBookmark');
|
|
1025
957
|
this.formView.disableCssTransitions();
|
|
1026
958
|
this.formView.resetFormStatus();
|
|
1027
959
|
this._balloon.add({
|
|
1028
960
|
view: this.formView,
|
|
1029
961
|
position: this._getBalloonPositionData()
|
|
1030
962
|
});
|
|
963
|
+
this.formView.backButtonView.isVisible = updateBookmarkCommand.isEnabled;
|
|
1031
964
|
this.formView.idInputView.fieldView.value = updateBookmarkCommand.value || '';
|
|
1032
965
|
// Select input when form view is currently visible.
|
|
1033
966
|
if (this._balloon.visibleView === this.formView) {
|
|
@@ -1035,69 +968,39 @@ const VISUAL_SELECTION_MARKER_NAME = 'bookmark-ui';
|
|
|
1035
968
|
}
|
|
1036
969
|
this.formView.enableCssTransitions();
|
|
1037
970
|
}
|
|
1038
|
-
/**
|
|
1039
|
-
* Closes the form view. Decides whether the balloon should be hidden completely.
|
|
1040
|
-
*/ _closeFormView() {
|
|
1041
|
-
const updateBookmarkCommand = this.editor.commands.get('updateBookmark');
|
|
1042
|
-
if (updateBookmarkCommand.value !== undefined) {
|
|
1043
|
-
this._removeFormView();
|
|
1044
|
-
} else {
|
|
1045
|
-
this._hideUI();
|
|
1046
|
-
}
|
|
1047
|
-
}
|
|
1048
971
|
/**
|
|
1049
972
|
* Removes the {@link #formView} from the {@link #_balloon}.
|
|
1050
973
|
*/ _removeFormView() {
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
this._hideFakeVisualSelection();
|
|
1062
|
-
}
|
|
974
|
+
// Blur the input element before removing it from DOM to prevent issues in some browsers.
|
|
975
|
+
// See https://github.com/ckeditor/ckeditor5/issues/1501.
|
|
976
|
+
this.formView.saveButtonView.focus();
|
|
977
|
+
// Reset the ID field to update the state of the submit button.
|
|
978
|
+
this.formView.idInputView.fieldView.reset();
|
|
979
|
+
this._balloon.remove(this.formView);
|
|
980
|
+
// Because the form has an input which has focus, the focus must be brought back
|
|
981
|
+
// to the editor. Otherwise, it would be lost.
|
|
982
|
+
this.editor.editing.view.focus();
|
|
983
|
+
this._hideFakeVisualSelection();
|
|
1063
984
|
}
|
|
1064
985
|
/**
|
|
1065
|
-
* Shows the
|
|
1066
|
-
*/
|
|
986
|
+
* Shows the {@link #formView}.
|
|
987
|
+
*/ _showFormView() {
|
|
1067
988
|
if (!this.formView) {
|
|
1068
989
|
this._createViews();
|
|
1069
990
|
}
|
|
1070
|
-
// When there's no bookmark under the selection, go straight to the editing UI.
|
|
1071
991
|
if (!this._getSelectedBookmarkElement()) {
|
|
1072
|
-
// Show visual selection on a text without a bookmark when the contextual balloon is displayed.
|
|
1073
992
|
this._showFakeVisualSelection();
|
|
1074
|
-
this._addActionsView();
|
|
1075
|
-
// Be sure panel with bookmark is visible.
|
|
1076
|
-
if (forceVisible) {
|
|
1077
|
-
this._balloon.showStack('main');
|
|
1078
|
-
}
|
|
1079
|
-
this._addFormView();
|
|
1080
|
-
} else {
|
|
1081
|
-
// Go to the editing UI if actions are already visible.
|
|
1082
|
-
if (this._areActionsVisible) {
|
|
1083
|
-
this._addFormView();
|
|
1084
|
-
} else {
|
|
1085
|
-
this._addActionsView();
|
|
1086
|
-
}
|
|
1087
|
-
// Be sure panel with bookmark is visible.
|
|
1088
|
-
if (forceVisible) {
|
|
1089
|
-
this._balloon.showStack('main');
|
|
1090
|
-
}
|
|
1091
993
|
}
|
|
994
|
+
this._addFormView();
|
|
995
|
+
// Be sure panel with bookmark is visible.
|
|
996
|
+
this._balloon.showStack('main');
|
|
1092
997
|
// Begin responding to ui#update once the UI is added.
|
|
1093
998
|
this._startUpdatingUI();
|
|
1094
999
|
}
|
|
1095
1000
|
/**
|
|
1096
1001
|
* Removes the {@link #formView} from the {@link #_balloon}.
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
*/ _hideUI() {
|
|
1100
|
-
if (!this._isUIInPanel) {
|
|
1002
|
+
*/ _hideFormView() {
|
|
1003
|
+
if (!this._isFormInPanel) {
|
|
1101
1004
|
return;
|
|
1102
1005
|
}
|
|
1103
1006
|
const editor = this.editor;
|
|
@@ -1108,21 +1011,18 @@ const VISUAL_SELECTION_MARKER_NAME = 'bookmark-ui';
|
|
|
1108
1011
|
editor.editing.view.focus();
|
|
1109
1012
|
// Remove form first because it's on top of the stack.
|
|
1110
1013
|
this._removeFormView();
|
|
1111
|
-
// Then remove the actions view because it's beneath the form.
|
|
1112
|
-
this._balloon.remove(this.actionsView);
|
|
1113
1014
|
this._hideFakeVisualSelection();
|
|
1114
1015
|
}
|
|
1115
1016
|
/**
|
|
1116
1017
|
* Makes the UI react to the {@link module:ui/editorui/editorui~EditorUI#event:update} event to
|
|
1117
1018
|
* reposition itself when the editor UI should be refreshed.
|
|
1118
1019
|
*
|
|
1119
|
-
* See: {@link #
|
|
1020
|
+
* See: {@link #_hideFormView} to learn when the UI stops reacting to the `update` event.
|
|
1120
1021
|
*/ _startUpdatingUI() {
|
|
1121
1022
|
const editor = this.editor;
|
|
1122
1023
|
const viewDocument = editor.editing.view.document;
|
|
1123
1024
|
let prevSelectedBookmark = this._getSelectedBookmarkElement();
|
|
1124
1025
|
let prevSelectionParent = getSelectionParent();
|
|
1125
|
-
this._updateFormButtonLabel(!!prevSelectedBookmark);
|
|
1126
1026
|
const update = ()=>{
|
|
1127
1027
|
const selectedBookmark = this._getSelectedBookmarkElement();
|
|
1128
1028
|
const selectionParent = getSelectionParent();
|
|
@@ -1135,14 +1035,13 @@ const VISUAL_SELECTION_MARKER_NAME = 'bookmark-ui';
|
|
|
1135
1035
|
// * the selection has expanded (e.g. displaying bookmark actions then pressing SHIFT+Right arrow).
|
|
1136
1036
|
//
|
|
1137
1037
|
if (prevSelectedBookmark && !selectedBookmark || !prevSelectedBookmark && selectionParent !== prevSelectionParent) {
|
|
1138
|
-
this.
|
|
1139
|
-
} else if (this.
|
|
1038
|
+
this._hideFormView();
|
|
1039
|
+
} else if (this._isFormVisible) {
|
|
1140
1040
|
// If still in a bookmark element, simply update the position of the balloon.
|
|
1141
1041
|
// If there was no bookmark (e.g. inserting one), the balloon must be moved
|
|
1142
1042
|
// to the new position in the editing view (a new native DOM range).
|
|
1143
1043
|
this._balloon.updatePosition(this._getBalloonPositionData());
|
|
1144
1044
|
}
|
|
1145
|
-
this._updateFormButtonLabel(!!prevSelectedBookmark);
|
|
1146
1045
|
prevSelectedBookmark = selectedBookmark;
|
|
1147
1046
|
prevSelectionParent = selectionParent;
|
|
1148
1047
|
};
|
|
@@ -1158,27 +1057,9 @@ const VISUAL_SELECTION_MARKER_NAME = 'bookmark-ui';
|
|
|
1158
1057
|
return !!this.formView && this._balloon.hasView(this.formView);
|
|
1159
1058
|
}
|
|
1160
1059
|
/**
|
|
1161
|
-
* Returns `true` when {@link #
|
|
1162
|
-
*/ get
|
|
1163
|
-
return !!this.
|
|
1164
|
-
}
|
|
1165
|
-
/**
|
|
1166
|
-
* Returns `true` when {@link #actionsView} is in the {@link #_balloon} and it is
|
|
1167
|
-
* currently visible.
|
|
1168
|
-
*/ get _areActionsVisible() {
|
|
1169
|
-
return !!this.actionsView && this._balloon.visibleView === this.actionsView;
|
|
1170
|
-
}
|
|
1171
|
-
/**
|
|
1172
|
-
* Returns `true` when {@link #actionsView} or {@link #formView} is in the {@link #_balloon}.
|
|
1173
|
-
*/ get _isUIInPanel() {
|
|
1174
|
-
return this._isFormInPanel || this._areActionsInPanel;
|
|
1175
|
-
}
|
|
1176
|
-
/**
|
|
1177
|
-
* Returns `true` when {@link #actionsView} or {@link #formView} is in the {@link #_balloon} and it is
|
|
1178
|
-
* currently visible.
|
|
1179
|
-
*/ get _isUIVisible() {
|
|
1180
|
-
const visibleView = this._balloon.visibleView;
|
|
1181
|
-
return !!this.formView && visibleView == this.formView || this._areActionsVisible;
|
|
1060
|
+
* Returns `true` when {@link #formView} is in the {@link #_balloon} and it is currently visible.
|
|
1061
|
+
*/ get _isFormVisible() {
|
|
1062
|
+
return !!this.formView && this._balloon.visibleView == this.formView;
|
|
1182
1063
|
}
|
|
1183
1064
|
/**
|
|
1184
1065
|
* Returns positioning options for the {@link #_balloon}. They control the way the balloon is attached
|
|
@@ -1201,7 +1082,10 @@ const VISUAL_SELECTION_MARKER_NAME = 'bookmark-ui';
|
|
|
1201
1082
|
return domConverter.mapViewToDom(viewElement);
|
|
1202
1083
|
};
|
|
1203
1084
|
}
|
|
1204
|
-
|
|
1085
|
+
if (!target) {
|
|
1086
|
+
return;
|
|
1087
|
+
}
|
|
1088
|
+
return {
|
|
1205
1089
|
target
|
|
1206
1090
|
};
|
|
1207
1091
|
}
|
|
@@ -1289,6 +1173,15 @@ const VISUAL_SELECTION_MARKER_NAME = 'bookmark-ui';
|
|
|
1289
1173
|
}
|
|
1290
1174
|
];
|
|
1291
1175
|
}
|
|
1176
|
+
/**
|
|
1177
|
+
* Returns the currently selected bookmark view element.
|
|
1178
|
+
*/ function getSelectedBookmarkWidget(selection) {
|
|
1179
|
+
const element = selection.getSelectedElement();
|
|
1180
|
+
if (!element || !isWidget(element) || !element.getCustomProperty('bookmark')) {
|
|
1181
|
+
return null;
|
|
1182
|
+
}
|
|
1183
|
+
return element;
|
|
1184
|
+
}
|
|
1292
1185
|
|
|
1293
1186
|
/**
|
|
1294
1187
|
* The bookmark feature.
|