-
-
Notifications
You must be signed in to change notification settings - Fork 3.7k
/
Copy pathballooneditorui.ts
129 lines (105 loc) · 3.7 KB
/
ballooneditorui.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
/**
* @license Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved.
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
*/
/**
* @module editor-balloon/ballooneditorui
*/
import {
type Editor
} from 'ckeditor5/src/core';
import {
EditorUI,
type EditorUIReadyEvent
} from 'ckeditor5/src/ui';
import { enablePlaceholder } from 'ckeditor5/src/engine';
import type BalloonEditorUIView from './ballooneditoruiview';
/**
* The balloon editor UI class.
*/
export default class BalloonEditorUI extends EditorUI {
/**
* The main (top–most) view of the editor UI.
*/
public readonly view: BalloonEditorUIView;
/**
* Creates an instance of the balloon editor UI class.
*
* @param editor The editor instance.
* @param view The view of the UI.
*/
constructor( editor: Editor, view: BalloonEditorUIView ) {
super( editor );
this.view = view;
}
/**
* @inheritDoc
*/
public override get element(): HTMLElement | null {
return this.view.editable.element;
}
/**
* Initializes the UI.
*/
public init(): void {
const editor = this.editor;
const view = this.view;
const editingView = editor.editing.view;
const editable = view.editable;
const editingRoot = editingView.document.getRoot()!;
// The editable UI and editing root should share the same name. Then name is used
// to recognize the particular editable, for instance in ARIA attributes.
editable.name = editingRoot.rootName;
view.render();
// The editable UI element in DOM is available for sure only after the editor UI view has been rendered.
// But it can be available earlier if a DOM element has been passed to BalloonEditor.create().
const editableElement = editable.element!;
// Register the editable UI view in the editor. A single editor instance can aggregate multiple
// editable areas (roots) but the balloon editor has only one.
this.setEditableElement( editable.name, editableElement );
// Let the editable UI element respond to the changes in the global editor focus
// tracker. It has been added to the same tracker a few lines above but, in reality, there are
// many focusable areas in the editor, like balloons, toolbars or dropdowns and as long
// as they have focus, the editable should act like it is focused too (although technically
// it isn't), e.g. by setting the proper CSS class, visually announcing focus to the user.
// Doing otherwise will result in editable focus styles disappearing, once e.g. the
// toolbar gets focused.
editable.bind( 'isFocused' ).to( this.focusTracker );
// Bind the editable UI element to the editing view, making it an end– and entry–point
// of the editor's engine. This is where the engine meets the UI.
editingView.attachDomRoot( editableElement );
this._initPlaceholder();
this.fire<EditorUIReadyEvent>( 'ready' );
}
/**
* @inheritDoc
*/
public override destroy(): void {
super.destroy();
const view = this.view;
const editingView = this.editor.editing.view;
editingView.detachDomRoot( view.editable.name! );
view.destroy();
}
/**
* Enable the placeholder text on the editing root, if any was configured.
*/
private _initPlaceholder(): void {
const editor = this.editor;
const editingView = editor.editing.view;
const editingRoot = editingView.document.getRoot()!;
const placeholder = editor.config.get( 'placeholder' );
if ( placeholder ) {
const placeholderText = typeof placeholder === 'string' ? placeholder : placeholder[ editingRoot.rootName ];
if ( placeholderText ) {
editingRoot.placeholder = placeholderText;
}
}
enablePlaceholder( {
view: editingView,
element: editingRoot,
isDirectHost: false,
keepOnFocus: true
} );
}
}