UNPKG

6.08 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 image/imageinsert/imageinsertui
7 */
8import { Plugin, icons } from 'ckeditor5/src/core';
9import { SplitButtonView, createDropdown } from 'ckeditor5/src/ui';
10import ImageInsertPanelView from './ui/imageinsertpanelview';
11import { prepareIntegrations } from './utils';
12/**
13 * The image insert dropdown plugin.
14 *
15 * For a detailed overview, check the {@glink features/images/image-upload/image-upload Image upload feature}
16 * and {@glink features/images/images-inserting Insert images via source URL} documentation.
17 *
18 * Adds the `'insertImage'` dropdown to the {@link module:ui/componentfactory~ComponentFactory UI component factory}
19 * and also the `imageInsert` dropdown as an alias for backward compatibility.
20 */
21export default class ImageInsertUI extends Plugin {
22 /**
23 * @inheritDoc
24 */
25 static get pluginName() {
26 return 'ImageInsertUI';
27 }
28 /**
29 * @inheritDoc
30 */
31 init() {
32 const editor = this.editor;
33 const componentCreator = (locale) => {
34 return this._createDropdownView(locale);
35 };
36 // Register `insertImage` dropdown and add `imageInsert` dropdown as an alias for backward compatibility.
37 editor.ui.componentFactory.add('insertImage', componentCreator);
38 editor.ui.componentFactory.add('imageInsert', componentCreator);
39 }
40 /**
41 * Creates the dropdown view.
42 *
43 * @param locale The localization services instance.
44 */
45 _createDropdownView(locale) {
46 const editor = this.editor;
47 const t = locale.t;
48 const uploadImageCommand = editor.commands.get('uploadImage');
49 const insertImageCommand = editor.commands.get('insertImage');
50 this.dropdownView = createDropdown(locale, uploadImageCommand ? SplitButtonView : undefined);
51 const buttonView = this.dropdownView.buttonView;
52 const panelView = this.dropdownView.panelView;
53 buttonView.set({
54 label: t('Insert image'),
55 icon: icons.image,
56 tooltip: true
57 });
58 panelView.extendTemplate({
59 attributes: {
60 class: 'ck-image-insert__panel'
61 }
62 });
63 if (uploadImageCommand) {
64 const splitButtonView = this.dropdownView.buttonView;
65 // We are injecting custom button replacement to readonly field.
66 splitButtonView.actionView = editor.ui.componentFactory.create('uploadImage');
67 // After we replaced action button with `uploadImage` component,
68 // we have lost a proper styling and some minor visual quirks have appeared.
69 // Brining back original split button classes helps fix the button styling
70 // See https://github.com/ckeditor/ckeditor5/issues/7986.
71 splitButtonView.actionView.extendTemplate({
72 attributes: {
73 class: 'ck ck-button ck-splitbutton__action'
74 }
75 });
76 }
77 return this._setUpDropdown(uploadImageCommand || insertImageCommand);
78 }
79 /**
80 * Sets up the dropdown view.
81 *
82 * @param command An uploadImage or insertImage command.
83 */
84 _setUpDropdown(command) {
85 const editor = this.editor;
86 const t = editor.t;
87 const dropdownView = this.dropdownView;
88 const panelView = dropdownView.panelView;
89 const imageUtils = this.editor.plugins.get('ImageUtils');
90 const replaceImageSourceCommand = editor.commands.get('replaceImageSource');
91 let imageInsertView;
92 dropdownView.bind('isEnabled').to(command);
93 dropdownView.once('change:isOpen', () => {
94 imageInsertView = new ImageInsertPanelView(editor.locale, prepareIntegrations(editor));
95 imageInsertView.delegate('submit', 'cancel').to(dropdownView);
96 panelView.children.add(imageInsertView);
97 });
98 dropdownView.on('change:isOpen', () => {
99 const selectedElement = editor.model.document.selection.getSelectedElement();
100 const insertButtonView = imageInsertView.insertButtonView;
101 const insertImageViaUrlForm = imageInsertView.getIntegration('insertImageViaUrl');
102 if (dropdownView.isOpen) {
103 if (imageUtils.isImage(selectedElement)) {
104 imageInsertView.imageURLInputValue = replaceImageSourceCommand.value;
105 insertButtonView.label = t('Update');
106 insertImageViaUrlForm.label = t('Update image URL');
107 }
108 else {
109 imageInsertView.imageURLInputValue = '';
110 insertButtonView.label = t('Insert');
111 insertImageViaUrlForm.label = t('Insert image via URL');
112 }
113 }
114 // Note: Use the low priority to make sure the following listener starts working after the
115 // default action of the drop-down is executed (i.e. the panel showed up). Otherwise, the
116 // invisible form/input cannot be focused/selected.
117 }, { priority: 'low' });
118 this.delegate('cancel').to(dropdownView);
119 dropdownView.on('submit', () => {
120 closePanel();
121 onSubmit();
122 });
123 dropdownView.on('cancel', () => {
124 closePanel();
125 });
126 function onSubmit() {
127 const selectedElement = editor.model.document.selection.getSelectedElement();
128 if (imageUtils.isImage(selectedElement)) {
129 editor.execute('replaceImageSource', { source: imageInsertView.imageURLInputValue });
130 }
131 else {
132 editor.execute('insertImage', { source: imageInsertView.imageURLInputValue });
133 }
134 }
135 function closePanel() {
136 editor.editing.view.focus();
137 dropdownView.isOpen = false;
138 }
139 return dropdownView;
140 }
141}