@ckeditor/ckeditor5-link
Version:
Link feature for CKEditor 5.
171 lines (170 loc) • 5.34 kB
JavaScript
/**
* @license Copyright (c) 2003-2025, CKSource Holding sp. z o.o. All rights reserved.
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-licensing-options
*/
/**
* @module link/ui/linkpropertiesview
*/
import { ButtonView, FocusCycler, FormHeaderView, View, ViewCollection, ListView, ListItemView } from 'ckeditor5/src/ui.js';
import { FocusTracker, KeystrokeHandler } from 'ckeditor5/src/utils.js';
import { IconPreviousArrow } from '@ckeditor/ckeditor5-icons';
import '../../theme/linkproperties.css';
/**
* The link properties view controller class.
*
* See {@link module:link/ui/linkpropertiesview~LinkPropertiesView}.
*/
export default class LinkPropertiesView extends View {
/**
* Tracks information about DOM focus in the form.
*/
focusTracker = new FocusTracker();
/**
* An instance of the {@link module:utils/keystrokehandler~KeystrokeHandler}.
*/
keystrokes = new KeystrokeHandler();
/**
* The Back button view displayed in the header.
*/
backButtonView;
/**
* A collection of child views.
*/
children;
/**
* A collection of {@link module:ui/button/switchbuttonview~SwitchButtonView},
* which corresponds to {@link module:link/linkcommand~LinkCommand#manualDecorators manual decorators}
* configured in the editor.
*/
listChildren;
/**
* A collection of views that can be focused in the form.
*/
_focusables = new ViewCollection();
/**
* Helps cycling over {@link #_focusables} in the form.
*/
_focusCycler;
/**
* Creates an instance of the {@link module:link/ui/linkpropertiesview~LinkPropertiesView} class.
*
* Also see {@link #render}.
*
* @param locale The localization services instance.
*/
constructor(locale) {
super(locale);
this.backButtonView = this._createBackButton();
this.listChildren = this.createCollection();
this.children = this.createCollection([
this._createHeaderView(),
this._createListView()
]);
this._focusCycler = new FocusCycler({
focusables: this._focusables,
focusTracker: this.focusTracker,
keystrokeHandler: this.keystrokes,
actions: {
// Navigate form fields backwards using the Shift + Tab keystroke.
focusPrevious: 'shift + tab',
// Navigate form fields forwards using the Tab key.
focusNext: 'tab'
}
});
this.setTemplate({
tag: 'div',
attributes: {
class: [
'ck',
'ck-link-properties'
],
// https://github.com/ckeditor/ckeditor5-link/issues/90
tabindex: '-1'
},
children: this.children
});
// Close the panel on esc key press when the **form has focus**.
this.keystrokes.set('Esc', (data, cancel) => {
this.fire('back');
cancel();
});
}
/**
* @inheritDoc
*/
render() {
super.render();
const childViews = [
...this.listChildren,
this.backButtonView
];
childViews.forEach(v => {
// Register the view as focusable.
this._focusables.add(v);
// Register the view in the focus tracker.
this.focusTracker.add(v.element);
});
// Start listening for the keystrokes coming from #element.
this.keystrokes.listenTo(this.element);
}
/**
* @inheritDoc
*/
destroy() {
super.destroy();
this.focusTracker.destroy();
this.keystrokes.destroy();
}
/**
* Focuses the fist {@link #_focusables} in the form.
*/
focus() {
this._focusCycler.focusFirst();
}
/**
* Creates a back button view.
*/
_createBackButton() {
const t = this.locale.t;
const backButton = new ButtonView(this.locale);
// TODO: maybe we should have a dedicated BackButtonView in the UI library.
backButton.set({
class: 'ck-button-back',
label: t('Back'),
icon: IconPreviousArrow,
tooltip: true
});
backButton.delegate('execute').to(this, 'back');
return backButton;
}
/**
* Creates a header view for the form.
*/
_createHeaderView() {
const t = this.locale.t;
const header = new FormHeaderView(this.locale, {
label: t('Link properties')
});
header.children.add(this.backButtonView, 0);
return header;
}
/**
* Creates a form view that displays the {@link #listChildren} collection.
*/
_createListView() {
const listView = new ListView(this.locale);
listView.extendTemplate({
attributes: {
class: [
'ck-link__list'
]
}
});
listView.items.bindTo(this.listChildren).using(item => {
const listItemView = new ListItemView(this.locale);
listItemView.children.add(item);
return listItemView;
});
return listView;
}
}