/** * @license Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved. * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license */ /** * @module image/imageinsert/imageinsertui */ import Plugin from '@ckeditor/ckeditor5-core/src/plugin'; import ImageInsertPanelView from './ui/imageinsertpanelview'; import { prepareIntegrations } from './utils'; import { isImage } from '../image/utils'; /** * The image insert dropdown plugin. * * For a detailed overview, check the {@glink features/image-upload/image-upload Image upload feature} * and {@glink features/image#inserting-images-via-source-url Insert images via source URL} documentation. * * Adds the `'imageInsert'` dropdown to the {@link module:ui/componentfactory~ComponentFactory UI component factory}. * * @extends module:core/plugin~Plugin */ export default class ImageInsertUI extends Plugin { /** * @inheritDoc */ static get pluginName() { return 'ImageInsertUI'; } /** * @inheritDoc */ init() { const editor = this.editor; editor.ui.componentFactory.add( 'imageInsert', locale => { return this._createDropdownView( locale ); } ); } /** * Creates the dropdown view. * * @param {module:utils/locale~Locale} locale The localization services instance. * * @private * @returns {module:ui/dropdown/dropdownview~DropdownView} */ _createDropdownView( locale ) { const editor = this.editor; const imageInsertView = new ImageInsertPanelView( locale, prepareIntegrations( editor ) ); const command = editor.commands.get( 'imageUpload' ); const dropdownView = imageInsertView.dropdownView; const splitButtonView = dropdownView.buttonView; splitButtonView.actionView = editor.ui.componentFactory.create( 'imageUpload' ); // After we replaced action button with `imageUpload` component, // we have lost a proper styling and some minor visual quirks have appeared. // Brining back original split button classes helps fix the button styling // See https://github.com/ckeditor/ckeditor5/issues/7986. splitButtonView.actionView.extendTemplate( { attributes: { class: 'ck ck-button ck-splitbutton__action' } } ); return this._setUpDropdown( dropdownView, imageInsertView, command ); } /** * Sets up the dropdown view. * * @param {module:ui/dropdown/dropdownview~DropdownView} dropdownView A dropdownView. * @param {module:image/imageinsert/ui/imageinsertpanelview~ImageInsertPanelView} imageInsertView An imageInsertView. * @param {module:core/command~Command} command An imageInsert command * * @private * @returns {module:ui/dropdown/dropdownview~DropdownView} */ _setUpDropdown( dropdownView, imageInsertView, command ) { const editor = this.editor; const t = editor.t; const insertButtonView = imageInsertView.insertButtonView; const insertImageViaUrlForm = imageInsertView.getIntegration( 'insertImageViaUrl' ); const panelView = dropdownView.panelView; dropdownView.bind( 'isEnabled' ).to( command ); // Defer the children injection to improve initial performance. // See https://github.com/ckeditor/ckeditor5/pull/8019#discussion_r484069652. dropdownView.buttonView.once( 'open', () => { panelView.children.add( imageInsertView ); } ); dropdownView.on( 'change:isOpen', () => { const selectedElement = editor.model.document.selection.getSelectedElement(); if ( dropdownView.isOpen ) { imageInsertView.focus(); if ( isImage( selectedElement ) ) { imageInsertView.imageURLInputValue = selectedElement.getAttribute( 'src' ); insertButtonView.label = t( 'Update' ); insertImageViaUrlForm.label = t( 'Update image URL' ); } else { imageInsertView.imageURLInputValue = ''; insertButtonView.label = t( 'Insert' ); insertImageViaUrlForm.label = t( 'Insert image via URL' ); } } // Note: Use the low priority to make sure the following listener starts working after the // default action of the drop-down is executed (i.e. the panel showed up). Otherwise, the // invisible form/input cannot be focused/selected. }, { priority: 'low' } ); imageInsertView.delegate( 'submit', 'cancel' ).to( dropdownView ); this.delegate( 'cancel' ).to( dropdownView ); dropdownView.on( 'submit', () => { closePanel(); onSubmit(); } ); dropdownView.on( 'cancel', () => { closePanel(); } ); function onSubmit() { const selectedElement = editor.model.document.selection.getSelectedElement(); if ( isImage( selectedElement ) ) { editor.model.change( writer => { writer.setAttribute( 'src', imageInsertView.imageURLInputValue, selectedElement ); writer.removeAttribute( 'srcset', selectedElement ); writer.removeAttribute( 'sizes', selectedElement ); } ); } else { editor.execute( 'imageInsert', { source: imageInsertView.imageURLInputValue } ); } } function closePanel() { editor.focus(); dropdownView.isOpen = false; } return dropdownView; } }