8
0

imageuploadui.js 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  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/imageupload/imageuploadui
  7. */
  8. import Plugin from '@ckeditor/ckeditor5-core/src/plugin';
  9. import ImageUploadPanelView from './ui/imageuploadpanelview';
  10. import FileDialogButtonView from '@ckeditor/ckeditor5-upload/src/ui/filedialogbuttonview';
  11. import { createImageTypeRegExp, prepareIntegrations } from './utils';
  12. import imageIcon from '@ckeditor/ckeditor5-core/theme/icons/image.svg';
  13. import { isImage } from '../image/utils';
  14. /**
  15. * The image upload button plugin.
  16. *
  17. * For a detailed overview, check the {@glink features/image-upload/image-upload Image upload feature} documentation.
  18. *
  19. * Adds the `'imageUpload'` dropdown to the {@link module:ui/componentfactory~ComponentFactory UI component factory}.
  20. *
  21. * @extends module:core/plugin~Plugin
  22. */
  23. export default class ImageUploadUI extends Plugin {
  24. /**
  25. * @inheritDoc
  26. */
  27. static get pluginName() {
  28. return 'ImageUploadUI';
  29. }
  30. /**
  31. * @inheritDoc
  32. */
  33. init() {
  34. const editor = this.editor;
  35. const isImageUploadPanelViewEnabled = !!editor.config.get( 'image.upload.panel.items' );
  36. editor.ui.componentFactory.add( 'imageUpload', locale => {
  37. if ( isImageUploadPanelViewEnabled ) {
  38. return this._createDropdownView( locale );
  39. } else {
  40. return this._createFileDialogButtonView( locale );
  41. }
  42. } );
  43. }
  44. /**
  45. * Sets up the dropdown view.
  46. *
  47. * @param {module:ui/dropdown/dropdownview~DropdownView} dropdownView A dropdownView.
  48. * @param {module:image/imageupload/ui/imageuploadpanelview~ImageUploadPanelView} imageUploadView An imageUploadView.
  49. * @param {module:core/command~Command} command An imageUpload command
  50. *
  51. * @private
  52. * @returns {module:ui/dropdown/dropdownview~DropdownView}
  53. */
  54. _setUpDropdown( dropdownView, imageUploadView, command ) {
  55. const editor = this.editor;
  56. const t = editor.t;
  57. const insertButtonView = imageUploadView.insertButtonView;
  58. dropdownView.bind( 'isEnabled' ).to( command );
  59. dropdownView.on( 'change:isOpen', () => {
  60. const selectedElement = editor.model.document.selection.getSelectedElement();
  61. if ( dropdownView.isOpen ) {
  62. imageUploadView.focus();
  63. if ( isImage( selectedElement ) ) {
  64. imageUploadView.imageURLInputValue = selectedElement.getAttribute( 'src' );
  65. insertButtonView.label = t( 'Update' );
  66. } else {
  67. imageUploadView.imageURLInputValue = '';
  68. insertButtonView.label = t( 'Insert' );
  69. }
  70. }
  71. } );
  72. imageUploadView.delegate( 'submit', 'cancel' ).to( dropdownView );
  73. this.delegate( 'cancel' ).to( dropdownView );
  74. dropdownView.on( 'submit', () => {
  75. closePanel();
  76. onSubmit();
  77. } );
  78. dropdownView.on( 'cancel', () => {
  79. closePanel();
  80. } );
  81. function onSubmit() {
  82. const selectedElement = editor.model.document.selection.getSelectedElement();
  83. if ( isImage( selectedElement ) ) {
  84. editor.model.change( writer => {
  85. writer.setAttribute( 'src', imageUploadView.imageURLInputValue, selectedElement );
  86. writer.removeAttribute( 'srcset', selectedElement );
  87. writer.removeAttribute( 'sizes', selectedElement );
  88. } );
  89. } else {
  90. editor.execute( 'imageInsert', { source: imageUploadView.imageURLInputValue } );
  91. }
  92. }
  93. function closePanel() {
  94. editor.editing.view.focus();
  95. dropdownView.isOpen = false;
  96. }
  97. return dropdownView;
  98. }
  99. /**
  100. * Creates the dropdown view.
  101. *
  102. * @param {module:utils/locale~Locale} locale The localization services instance.
  103. *
  104. * @private
  105. * @returns {module:ui/dropdown/dropdownview~DropdownView}
  106. */
  107. _createDropdownView( locale ) {
  108. const editor = this.editor;
  109. const imageUploadView = new ImageUploadPanelView( locale, prepareIntegrations( editor ) );
  110. const command = editor.commands.get( 'imageUpload' );
  111. const dropdownView = imageUploadView.dropdownView;
  112. const panelView = dropdownView.panelView;
  113. const splitButtonView = dropdownView.buttonView;
  114. splitButtonView.actionView = this._createFileDialogButtonView( locale );
  115. panelView.children.add( imageUploadView );
  116. return this._setUpDropdown( dropdownView, imageUploadView, command );
  117. }
  118. /**
  119. * Creates and sets up the file dialog button view.
  120. *
  121. * @param {module:utils/locale~Locale} locale The localization services instance.
  122. *
  123. * @private
  124. * @returns {module:upload/ui/filedialogbuttonview~FileDialogButtonView}
  125. */
  126. _createFileDialogButtonView( locale ) {
  127. const editor = this.editor;
  128. const t = locale.t;
  129. const imageTypes = editor.config.get( 'image.upload.types' );
  130. const fileDialogButtonView = new FileDialogButtonView( locale );
  131. const imageTypesRegExp = createImageTypeRegExp( imageTypes );
  132. const command = editor.commands.get( 'imageUpload' );
  133. fileDialogButtonView.set( {
  134. acceptedType: imageTypes.map( type => `image/${ type }` ).join( ',' ),
  135. allowMultipleFiles: true
  136. } );
  137. fileDialogButtonView.buttonView.set( {
  138. label: t( 'Insert image' ),
  139. icon: imageIcon,
  140. tooltip: true
  141. } );
  142. fileDialogButtonView.buttonView.bind( 'isEnabled' ).to( command );
  143. fileDialogButtonView.on( 'done', ( evt, files ) => {
  144. const imagesToUpload = Array.from( files ).filter( file => imageTypesRegExp.test( file.type ) );
  145. if ( imagesToUpload.length ) {
  146. editor.execute( 'imageUpload', { file: imagesToUpload } );
  147. }
  148. } );
  149. return fileDialogButtonView;
  150. }
  151. }