1 | /**
|
2 | * @license Copyright (c) 2003-2024, CKSource Holding sp. z o.o. All rights reserved.
|
3 | * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
|
4 | */
|
5 | /**
|
6 | * @module image/imageinsert/ui/imageinsertformview
|
7 | */
|
8 | import { View, ViewCollection, submitHandler, FocusCycler, CollapsibleView } from 'ckeditor5/src/ui.js';
|
9 | import { FocusTracker, KeystrokeHandler } from 'ckeditor5/src/utils.js';
|
10 | import '../../../theme/imageinsert.css';
|
11 | /**
|
12 | * The view displayed in the insert image dropdown.
|
13 | *
|
14 | * See {@link module:image/imageinsert/imageinsertui~ImageInsertUI}.
|
15 | */
|
16 | export default class ImageInsertFormView extends View {
|
17 | /**
|
18 | * Creates a view for the dropdown panel of {@link module:image/imageinsert/imageinsertui~ImageInsertUI}.
|
19 | *
|
20 | * @param locale The localization services instance.
|
21 | * @param integrations An integrations object that contains components (or tokens for components) to be shown in the panel view.
|
22 | */
|
23 | constructor(locale, integrations = []) {
|
24 | super(locale);
|
25 | this.focusTracker = new FocusTracker();
|
26 | this.keystrokes = new KeystrokeHandler();
|
27 | this._focusables = new ViewCollection();
|
28 | this.children = this.createCollection();
|
29 | this._focusCycler = new FocusCycler({
|
30 | focusables: this._focusables,
|
31 | focusTracker: this.focusTracker,
|
32 | keystrokeHandler: this.keystrokes,
|
33 | actions: {
|
34 | // Navigate form fields backwards using the Shift + Tab keystroke.
|
35 | focusPrevious: 'shift + tab',
|
36 | // Navigate form fields forwards using the Tab key.
|
37 | focusNext: 'tab'
|
38 | }
|
39 | });
|
40 | for (const view of integrations) {
|
41 | this.children.add(view);
|
42 | this._focusables.add(view);
|
43 | if (view instanceof CollapsibleView) {
|
44 | this._focusables.addMany(view.children);
|
45 | }
|
46 | }
|
47 | if (this._focusables.length > 1) {
|
48 | for (const view of this._focusables) {
|
49 | if (isViewWithFocusCycler(view)) {
|
50 | view.focusCycler.on('forwardCycle', evt => {
|
51 | this._focusCycler.focusNext();
|
52 | evt.stop();
|
53 | });
|
54 | view.focusCycler.on('backwardCycle', evt => {
|
55 | this._focusCycler.focusPrevious();
|
56 | evt.stop();
|
57 | });
|
58 | }
|
59 | }
|
60 | }
|
61 | this.setTemplate({
|
62 | tag: 'form',
|
63 | attributes: {
|
64 | class: [
|
65 | 'ck',
|
66 | 'ck-image-insert-form'
|
67 | ],
|
68 | tabindex: -1
|
69 | },
|
70 | children: this.children
|
71 | });
|
72 | }
|
73 | /**
|
74 | * @inheritDoc
|
75 | */
|
76 | render() {
|
77 | super.render();
|
78 | submitHandler({
|
79 | view: this
|
80 | });
|
81 | for (const view of this._focusables) {
|
82 | this.focusTracker.add(view.element);
|
83 | }
|
84 | // Start listening for the keystrokes coming from #element.
|
85 | this.keystrokes.listenTo(this.element);
|
86 | const stopPropagation = (data) => data.stopPropagation();
|
87 | // Since the form is in the dropdown panel which is a child of the toolbar, the toolbar's
|
88 | // keystroke handler would take over the key management in the URL input. We need to prevent
|
89 | // this ASAP. Otherwise, the basic caret movement using the arrow keys will be impossible.
|
90 | this.keystrokes.set('arrowright', stopPropagation);
|
91 | this.keystrokes.set('arrowleft', stopPropagation);
|
92 | this.keystrokes.set('arrowup', stopPropagation);
|
93 | this.keystrokes.set('arrowdown', stopPropagation);
|
94 | }
|
95 | /**
|
96 | * @inheritDoc
|
97 | */
|
98 | destroy() {
|
99 | super.destroy();
|
100 | this.focusTracker.destroy();
|
101 | this.keystrokes.destroy();
|
102 | }
|
103 | /**
|
104 | * Focuses the first {@link #_focusables focusable} in the form.
|
105 | */
|
106 | focus() {
|
107 | this._focusCycler.focusFirst();
|
108 | }
|
109 | }
|
110 | function isViewWithFocusCycler(view) {
|
111 | return 'focusCycler' in view;
|
112 | }
|