UNPKG

@ckeditor/ckeditor5-link

Version:

Link feature for CKEditor 5.

157 lines (156 loc) 5.09 kB
/** * @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; } }