8
0

imagetoolbar.js 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  1. /**
  2. * @license Copyright (c) 2003-2018, CKSource - Frederico Knabben. All rights reserved.
  3. * For licensing, see LICENSE.md.
  4. */
  5. /**
  6. * @module image/imagetoolbar
  7. */
  8. import Plugin from '@ckeditor/ckeditor5-core/src/plugin';
  9. import ToolbarView from '@ckeditor/ckeditor5-ui/src/toolbar/toolbarview';
  10. import ContextualBalloon from '@ckeditor/ckeditor5-ui/src/panel/balloon/contextualballoon';
  11. import { isImageWidgetSelected } from './image/utils';
  12. import { repositionContextualBalloon, getBalloonPositionData } from './image/ui/utils';
  13. const balloonClassName = 'ck-toolbar-container';
  14. /**
  15. * The image toolbar class. Creates an image toolbar that shows up when the image widget is selected.
  16. *
  17. * Toolbar components are created using the editor {@link module:ui/componentfactory~ComponentFactory ComponentFactory}
  18. * based on the {@link module:core/editor/editor~Editor#config configuration} stored under `image.toolbar`.
  19. *
  20. * The toolbar uses the {@link module:ui/panel/balloon/contextualballoon~ContextualBalloon}.
  21. *
  22. * For a detailed overview, check the {@glink features/image#image-contextual-toolbar image contextual toolbar} documentation.
  23. *
  24. * @extends module:core/plugin~Plugin
  25. */
  26. export default class ImageToolbar extends Plugin {
  27. /**
  28. * @inheritDoc
  29. */
  30. static get requires() {
  31. return [ ContextualBalloon ];
  32. }
  33. /**
  34. * @inheritDoc
  35. */
  36. static get pluginName() {
  37. return 'ImageToolbar';
  38. }
  39. /**
  40. * @inheritDoc
  41. */
  42. init() {
  43. const editor = this.editor;
  44. const balloonToolbar = editor.plugins.get( 'BalloonToolbar' );
  45. // If the `BalloonToolbar` plugin is loaded, it should be disabled for images
  46. // which have their own toolbar to avoid duplication.
  47. // https://github.com/ckeditor/ckeditor5-image/issues/110
  48. if ( balloonToolbar ) {
  49. this.listenTo( balloonToolbar, 'show', evt => {
  50. if ( isImageWidgetSelected( editor.editing.view.document.selection ) ) {
  51. evt.stop();
  52. }
  53. }, { priority: 'high' } );
  54. }
  55. }
  56. /**
  57. * @inheritDoc
  58. */
  59. afterInit() {
  60. const editor = this.editor;
  61. const toolbarConfig = editor.config.get( 'image.toolbar' );
  62. // Don't add the toolbar if there is no configuration.
  63. if ( !toolbarConfig || !toolbarConfig.length ) {
  64. return;
  65. }
  66. /**
  67. * A contextual balloon plugin instance.
  68. *
  69. * @private
  70. * @member {module:ui/panel/balloon/contextualballoon~ContextualBalloon}
  71. */
  72. this._balloon = this.editor.plugins.get( 'ContextualBalloon' );
  73. /**
  74. * A `ToolbarView` instance used to display the buttons specific for image editing.
  75. *
  76. * @protected
  77. * @type {module:ui/toolbar/toolbarview~ToolbarView}
  78. */
  79. this._toolbar = new ToolbarView();
  80. // Add buttons to the toolbar.
  81. this._toolbar.fillFromConfig( toolbarConfig, editor.ui.componentFactory );
  82. // Show balloon panel each time image widget is selected.
  83. this.listenTo( editor.editing.view, 'render', () => {
  84. this._checkIsVisible();
  85. } );
  86. // There is no render method after focus is back in editor, we need to check if balloon panel should be visible.
  87. this.listenTo( editor.ui.focusTracker, 'change:isFocused', () => {
  88. this._checkIsVisible();
  89. }, { priority: 'low' } );
  90. }
  91. /**
  92. * Checks whether the toolbar should show up or hide depending on the current selection.
  93. *
  94. * @private
  95. */
  96. _checkIsVisible() {
  97. const editor = this.editor;
  98. if ( !editor.ui.focusTracker.isFocused ) {
  99. this._hideToolbar();
  100. } else {
  101. if ( isImageWidgetSelected( editor.editing.view.document.selection ) ) {
  102. this._showToolbar();
  103. } else {
  104. this._hideToolbar();
  105. }
  106. }
  107. }
  108. /**
  109. * Shows the {@link #_toolbar} in the {@link #_balloon}.
  110. *
  111. * @private
  112. */
  113. _showToolbar() {
  114. const editor = this.editor;
  115. if ( this._isVisible ) {
  116. repositionContextualBalloon( editor );
  117. } else {
  118. if ( !this._balloon.hasView( this._toolbar ) ) {
  119. this._balloon.add( {
  120. view: this._toolbar,
  121. position: getBalloonPositionData( editor ),
  122. balloonClassName
  123. } );
  124. }
  125. }
  126. }
  127. /**
  128. * Removes the {@link #_toolbar} from the {@link #_balloon}.
  129. *
  130. * @private
  131. */
  132. _hideToolbar() {
  133. if ( !this._isVisible ) {
  134. return;
  135. }
  136. this._balloon.remove( this._toolbar );
  137. }
  138. /**
  139. * Returns `true` when the {@link #_toolbar} is the visible view in the {@link #_balloon}.
  140. *
  141. * @private
  142. * @type {Boolean}
  143. */
  144. get _isVisible() {
  145. return this._balloon.visibleView == this._toolbar;
  146. }
  147. }
  148. /**
  149. * Items to be placed in the image toolbar.
  150. * This option is used by the {@link module:image/imagetoolbar~ImageToolbar} feature.
  151. *
  152. * Assuming that you use the following features:
  153. *
  154. * * {@link module:image/imagestyle~ImageStyle} (with a default configuration),
  155. * * {@link module:image/imagetextalternative~ImageTextAlternative},
  156. *
  157. * three toolbar items will be available in {@link module:ui/componentfactory~ComponentFactory}:
  158. * `'imageStyle:full'`, `'imageStyle:side'`, and `'imageTextAlternative'` so you can configure the toolbar like this:
  159. *
  160. * const imageConfig = {
  161. * toolbar: [ 'imageStyle:full', 'imageStyle:side', '|', 'imageTextAlternative' ]
  162. * };
  163. *
  164. * Of course, the same buttons can also be used in the
  165. * {@link module:core/editor/editorconfig~EditorConfig#toolbar main editor toolbar}.
  166. *
  167. * Read more about configuring toolbar in {@link module:core/editor/editorconfig~EditorConfig#toolbar}.
  168. *
  169. * @member {Array.<String>} module:image/image~ImageConfig#toolbar
  170. */