imageinsertui.js 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. /**
  2. * @license Copyright (c) 2003-2020, CKSource - Frederico Knabben. 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. */
  8. import Plugin from '@ckeditor/ckeditor5-core/src/plugin';
  9. import ImageInsertPanelView from './ui/imageinsertpanelview';
  10. import { prepareIntegrations } from './utils';
  11. import { isImage } from '../image/utils';
  12. /**
  13. * The image insert dropdown plugin.
  14. *
  15. * For a detailed overview, check the {@glink features/image-upload/image-upload Image upload feature}
  16. * and {@glink features/image#inserting-images-via-source-url Insert images via source URL} documentation.
  17. *
  18. * Adds the `'imageInsert'` dropdown to the {@link module:ui/componentfactory~ComponentFactory UI component factory}.
  19. *
  20. * @extends module:core/plugin~Plugin
  21. */
  22. export default class ImageInsertUI extends Plugin {
  23. /**
  24. * @inheritDoc
  25. */
  26. static get pluginName() {
  27. return 'ImageInsertUI';
  28. }
  29. /**
  30. * @inheritDoc
  31. */
  32. init() {
  33. const editor = this.editor;
  34. editor.ui.componentFactory.add( 'imageInsert', locale => {
  35. return this._createDropdownView( locale );
  36. } );
  37. }
  38. /**
  39. * Creates the dropdown view.
  40. *
  41. * @param {module:utils/locale~Locale} locale The localization services instance.
  42. *
  43. * @private
  44. * @returns {module:ui/dropdown/dropdownview~DropdownView}
  45. */
  46. _createDropdownView( locale ) {
  47. const editor = this.editor;
  48. const imageInsertView = new ImageInsertPanelView( locale, prepareIntegrations( editor ) );
  49. const command = editor.commands.get( 'imageUpload' );
  50. const dropdownView = imageInsertView.dropdownView;
  51. const splitButtonView = dropdownView.buttonView;
  52. splitButtonView.actionView = editor.ui.componentFactory.create( 'imageUpload' );
  53. // After we replaced action button with `imageUpload` component,
  54. // we have lost a proper styling and some minor visual quirks have appeared.
  55. // Brining back original split button classes helps fix the button styling
  56. // See https://github.com/ckeditor/ckeditor5/issues/7986.
  57. splitButtonView.actionView.extendTemplate( {
  58. attributes: {
  59. class: 'ck ck-button ck-splitbutton__action'
  60. }
  61. } );
  62. return this._setUpDropdown( dropdownView, imageInsertView, command );
  63. }
  64. /**
  65. * Sets up the dropdown view.
  66. *
  67. * @param {module:ui/dropdown/dropdownview~DropdownView} dropdownView A dropdownView.
  68. * @param {module:image/imageinsert/ui/imageinsertpanelview~ImageInsertPanelView} imageInsertView An imageInsertView.
  69. * @param {module:core/command~Command} command An imageInsert command
  70. *
  71. * @private
  72. * @returns {module:ui/dropdown/dropdownview~DropdownView}
  73. */
  74. _setUpDropdown( dropdownView, imageInsertView, command ) {
  75. const editor = this.editor;
  76. const t = editor.t;
  77. const insertButtonView = imageInsertView.insertButtonView;
  78. const insertImageViaUrlForm = imageInsertView.getIntegration( 'insertImageViaUrl' );
  79. const panelView = dropdownView.panelView;
  80. dropdownView.bind( 'isEnabled' ).to( command );
  81. // Defer the children injection to improve initial performance.
  82. // See https://github.com/ckeditor/ckeditor5/pull/8019#discussion_r484069652.
  83. dropdownView.buttonView.once( 'open', () => {
  84. panelView.children.add( imageInsertView );
  85. } );
  86. dropdownView.on( 'change:isOpen', () => {
  87. const selectedElement = editor.model.document.selection.getSelectedElement();
  88. if ( dropdownView.isOpen ) {
  89. imageInsertView.focus();
  90. if ( isImage( selectedElement ) ) {
  91. imageInsertView.imageURLInputValue = selectedElement.getAttribute( 'src' );
  92. insertButtonView.label = t( 'Update' );
  93. insertImageViaUrlForm.label = t( 'Update image URL' );
  94. } else {
  95. imageInsertView.imageURLInputValue = '';
  96. insertButtonView.label = t( 'Insert' );
  97. insertImageViaUrlForm.label = t( 'Insert image via URL' );
  98. }
  99. }
  100. } );
  101. imageInsertView.delegate( 'submit', 'cancel' ).to( dropdownView );
  102. this.delegate( 'cancel' ).to( dropdownView );
  103. dropdownView.on( 'submit', () => {
  104. closePanel();
  105. onSubmit();
  106. } );
  107. dropdownView.on( 'cancel', () => {
  108. closePanel();
  109. } );
  110. function onSubmit() {
  111. const selectedElement = editor.model.document.selection.getSelectedElement();
  112. if ( isImage( selectedElement ) ) {
  113. editor.model.change( writer => {
  114. writer.setAttribute( 'src', imageInsertView.imageURLInputValue, selectedElement );
  115. writer.removeAttribute( 'srcset', selectedElement );
  116. writer.removeAttribute( 'sizes', selectedElement );
  117. } );
  118. } else {
  119. editor.execute( 'imageInsert', { source: imageInsertView.imageURLInputValue } );
  120. }
  121. }
  122. function closePanel() {
  123. editor.editing.view.focus();
  124. dropdownView.isOpen = false;
  125. }
  126. return dropdownView;
  127. }
  128. }