@ckeditor/ckeditor5-link
Version:
Link feature for CKEditor 5.
157 lines (156 loc) • 5.09 kB
JavaScript
/**
* @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 link/ui/linkactionsview
*/
import { ButtonView, View, ViewCollection, FocusCycler } from 'ckeditor5/src/ui';
import { FocusTracker, KeystrokeHandler } from 'ckeditor5/src/utils';
import { icons } from 'ckeditor5/src/core';
import { ensureSafeUrl } from '../utils';
// See: #8833.
// eslint-disable-next-line ckeditor5-rules/ckeditor-imports
import '@ckeditor/ckeditor5-ui/theme/components/responsive-form/responsiveform.css';
import '../../theme/linkactions.css';
import unlinkIcon from '../../theme/icons/unlink.svg';
/**
* The link actions view class. This view displays the link preview, allows
* unlinking or editing the link.
*/
export default class LinkActionsView extends View {
/**
* @inheritDoc
*/
constructor(locale) {
super(locale);
/**
* Tracks information about DOM focus in the actions.
*/
this.focusTracker = new FocusTracker();
/**
* An instance of the {@link module:utils/keystrokehandler~KeystrokeHandler}.
*/
this.keystrokes = new KeystrokeHandler();
/**
* A collection of views that can be focused in the view.
*/
this._focusables = new ViewCollection();
const t = locale.t;
this.previewButtonView = this._createPreviewButton();
this.unlinkButtonView = this._createButton(t('Unlink'), unlinkIcon, 'unlink');
this.editButtonView = this._createButton(t('Edit link'), icons.pencil, 'edit');
this.set('href', undefined);
this._focusCycler = new FocusCycler({
focusables: this._focusables,
focusTracker: this.focusTracker,
keystrokeHandler: this.keystrokes,
actions: {
// Navigate fields backwards using the Shift + Tab keystroke.
focusPrevious: 'shift + tab',
// Navigate fields forwards using the Tab key.
focusNext: 'tab'
}
});
this.setTemplate({
tag: 'div',
attributes: {
class: [
'ck',
'ck-link-actions',
'ck-responsive-form'
],
// https://github.com/ckeditor/ckeditor5-link/issues/90
tabindex: '-1'
},
children: [
this.previewButtonView,
this.editButtonView,
this.unlinkButtonView
]
});
}
/**
* @inheritDoc
*/
render() {
super.render();
const childViews = [
this.previewButtonView,
this.editButtonView,
this.unlinkButtonView
];
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 actions.
*/
focus() {
this._focusCycler.focusFirst();
}
/**
* Creates a button view.
*
* @param label The button label.
* @param icon The button icon.
* @param eventName An event name that the `ButtonView#execute` event will be delegated to.
* @returns The button view instance.
*/
_createButton(label, icon, eventName) {
const button = new ButtonView(this.locale);
button.set({
label,
icon,
tooltip: true
});
button.delegate('execute').to(this, eventName);
return button;
}
/**
* Creates a link href preview button.
*
* @returns The button view instance.
*/
_createPreviewButton() {
const button = new ButtonView(this.locale);
const bind = this.bindTemplate;
const t = this.t;
button.set({
withText: true,
tooltip: t('Open link in new tab')
});
button.extendTemplate({
attributes: {
class: [
'ck',
'ck-link-actions__preview'
],
href: bind.to('href', href => href && ensureSafeUrl(href)),
target: '_blank',
rel: 'noopener noreferrer'
}
});
button.bind('label').to(this, 'href', href => {
return href || t('This link has no URL');
});
button.bind('isEnabled').to(this, 'href', href => !!href);
button.template.tag = 'a';
button.template.eventListeners = {};
return button;
}
}