UNPKG

5.09 kBJavaScriptView Raw
1/**
2 * @license Copyright (c) 2003-2023, 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 link/ui/linkactionsview
7 */
8import { ButtonView, View, ViewCollection, FocusCycler } from 'ckeditor5/src/ui';
9import { FocusTracker, KeystrokeHandler } from 'ckeditor5/src/utils';
10import { icons } from 'ckeditor5/src/core';
11import { ensureSafeUrl } from '../utils';
12// See: #8833.
13// eslint-disable-next-line ckeditor5-rules/ckeditor-imports
14import '@ckeditor/ckeditor5-ui/theme/components/responsive-form/responsiveform.css';
15import '../../theme/linkactions.css';
16import unlinkIcon from '../../theme/icons/unlink.svg';
17/**
18 * The link actions view class. This view displays the link preview, allows
19 * unlinking or editing the link.
20 */
21export default class LinkActionsView extends View {
22 /**
23 * @inheritDoc
24 */
25 constructor(locale) {
26 super(locale);
27 /**
28 * Tracks information about DOM focus in the actions.
29 */
30 this.focusTracker = new FocusTracker();
31 /**
32 * An instance of the {@link module:utils/keystrokehandler~KeystrokeHandler}.
33 */
34 this.keystrokes = new KeystrokeHandler();
35 /**
36 * A collection of views that can be focused in the view.
37 */
38 this._focusables = new ViewCollection();
39 const t = locale.t;
40 this.previewButtonView = this._createPreviewButton();
41 this.unlinkButtonView = this._createButton(t('Unlink'), unlinkIcon, 'unlink');
42 this.editButtonView = this._createButton(t('Edit link'), icons.pencil, 'edit');
43 this.set('href', undefined);
44 this._focusCycler = new FocusCycler({
45 focusables: this._focusables,
46 focusTracker: this.focusTracker,
47 keystrokeHandler: this.keystrokes,
48 actions: {
49 // Navigate fields backwards using the Shift + Tab keystroke.
50 focusPrevious: 'shift + tab',
51 // Navigate fields forwards using the Tab key.
52 focusNext: 'tab'
53 }
54 });
55 this.setTemplate({
56 tag: 'div',
57 attributes: {
58 class: [
59 'ck',
60 'ck-link-actions',
61 'ck-responsive-form'
62 ],
63 // https://github.com/ckeditor/ckeditor5-link/issues/90
64 tabindex: '-1'
65 },
66 children: [
67 this.previewButtonView,
68 this.editButtonView,
69 this.unlinkButtonView
70 ]
71 });
72 }
73 /**
74 * @inheritDoc
75 */
76 render() {
77 super.render();
78 const childViews = [
79 this.previewButtonView,
80 this.editButtonView,
81 this.unlinkButtonView
82 ];
83 childViews.forEach(v => {
84 // Register the view as focusable.
85 this._focusables.add(v);
86 // Register the view in the focus tracker.
87 this.focusTracker.add(v.element);
88 });
89 // Start listening for the keystrokes coming from #element.
90 this.keystrokes.listenTo(this.element);
91 }
92 /**
93 * @inheritDoc
94 */
95 destroy() {
96 super.destroy();
97 this.focusTracker.destroy();
98 this.keystrokes.destroy();
99 }
100 /**
101 * Focuses the fist {@link #_focusables} in the actions.
102 */
103 focus() {
104 this._focusCycler.focusFirst();
105 }
106 /**
107 * Creates a button view.
108 *
109 * @param label The button label.
110 * @param icon The button icon.
111 * @param eventName An event name that the `ButtonView#execute` event will be delegated to.
112 * @returns The button view instance.
113 */
114 _createButton(label, icon, eventName) {
115 const button = new ButtonView(this.locale);
116 button.set({
117 label,
118 icon,
119 tooltip: true
120 });
121 button.delegate('execute').to(this, eventName);
122 return button;
123 }
124 /**
125 * Creates a link href preview button.
126 *
127 * @returns The button view instance.
128 */
129 _createPreviewButton() {
130 const button = new ButtonView(this.locale);
131 const bind = this.bindTemplate;
132 const t = this.t;
133 button.set({
134 withText: true,
135 tooltip: t('Open link in new tab')
136 });
137 button.extendTemplate({
138 attributes: {
139 class: [
140 'ck',
141 'ck-link-actions__preview'
142 ],
143 href: bind.to('href', href => href && ensureSafeUrl(href)),
144 target: '_blank',
145 rel: 'noopener noreferrer'
146 }
147 });
148 button.bind('label').to(this, 'href', href => {
149 return href || t('This link has no URL');
150 });
151 button.bind('isEnabled').to(this, 'href', href => !!href);
152 button.template.tag = 'a';
153 button.template.eventListeners = {};
154 return button;
155 }
156}