diff --git a/src/image.js b/src/image.js
index 777af10a..a5d15035 100644
--- a/src/image.js
+++ b/src/image.js
@@ -11,6 +11,7 @@ import Plugin from '@ckeditor/ckeditor5-core/src/plugin';
import ImageEngine from './image/imageengine';
import Widget from '@ckeditor/ckeditor5-widget/src/widget';
import ImageTextAlternative from './imagetextalternative';
+import { isImageWidget } from './image/utils';
import '../theme/theme.scss';
@@ -35,4 +36,25 @@ export default class Image extends Plugin {
static get pluginName() {
return 'image/image';
}
+
+ /**
+ * @inheritDoc
+ */
+ init() {
+ const editor = this.editor;
+ const contextualToolbar = editor.plugins.get( 'ui/contextualtoolbar' );
+
+ // If `ContextualToolbar` plugin is loaded, it should be disabled for images
+ // which have their own toolbar to avoid duplication.
+ // https://github.com/ckeditor/ckeditor5-image/issues/110
+ if ( contextualToolbar ) {
+ this.listenTo( contextualToolbar, 'beforeShow', ( evt, stop ) => {
+ const selectedElement = editor.editing.view.selection.getSelectedElement();
+
+ if ( selectedElement && isImageWidget( selectedElement ) ) {
+ stop();
+ }
+ } );
+ }
+ }
}
diff --git a/src/imagetextalternative.js b/src/imagetextalternative.js
index 0773e259..2605efd4 100644
--- a/src/imagetextalternative.js
+++ b/src/imagetextalternative.js
@@ -49,7 +49,7 @@ export default class ImageTextAlternative extends Plugin {
/**
* Balloon panel containing text alternative change form.
*
- * @member {module:image/ui/imageballoonpanel~ImageBalloonPanelView} #baloonPanel
+ * @member {module:image/image/ui/imageballoonpanel~ImageBalloonPanelView} #baloonPanel
*/
this.balloonPanel = panel;
diff --git a/src/imagetextalternative/ui/textalternativeformview.js b/src/imagetextalternative/ui/textalternativeformview.js
index 7def38bc..7e965430 100644
--- a/src/imagetextalternative/ui/textalternativeformview.js
+++ b/src/imagetextalternative/ui/textalternativeformview.js
@@ -4,7 +4,7 @@
*/
/**
- * @module image/imagetextalternative/ui/imagetextalternativeformview
+ * @module image/imagetextalternative/ui/textalternativeformview
*/
import View from '@ckeditor/ckeditor5-ui/src/view';
diff --git a/tests/image.js b/tests/image.js
index ff5f01e5..52eb6ec2 100644
--- a/tests/image.js
+++ b/tests/image.js
@@ -13,12 +13,14 @@ import ImageTextAlternative from '../src/imagetextalternative';
import { setData as setModelData } from '@ckeditor/ckeditor5-engine/src/dev-utils/model';
import { getData as getViewData } from '@ckeditor/ckeditor5-engine/src/dev-utils/view';
import ModelRange from '@ckeditor/ckeditor5-engine/src/model/range';
+import ContextualToolbar from '@ckeditor/ckeditor5-ui/src/toolbar/contextual/contextualtoolbar';
+import Paragraph from '@ckeditor/ckeditor5-paragraph/src/paragraph';
describe( 'Image', () => {
- let editor, document, viewDocument;
+ let editorElement, editor, document, viewDocument;
beforeEach( () => {
- const editorElement = window.document.createElement( 'div' );
+ editorElement = window.document.createElement( 'div' );
window.document.body.appendChild( editorElement );
return ClassicTestEditor.create( editorElement, {
@@ -31,6 +33,12 @@ describe( 'Image', () => {
} );
} );
+ afterEach( () => {
+ editorElement.remove();
+
+ return editor.destroy();
+ } );
+
it( 'should be loaded', () => {
expect( editor.plugins.get( Image ) ).to.instanceOf( Image );
} );
@@ -47,6 +55,41 @@ describe( 'Image', () => {
expect( editor.plugins.get( ImageTextAlternative ) ).to.instanceOf( ImageTextAlternative );
} );
+ it( 'should prevent the ContextualToolbar from being displayed when an image is selected', () => {
+ return ClassicTestEditor.create( editorElement, {
+ plugins: [ Image, ContextualToolbar, Paragraph ]
+ } )
+ .then( newEditor => {
+ const balloon = newEditor.plugins.get( 'ui/contextualballoon' );
+ const contextualToolbar = newEditor.plugins.get( 'ui/contextualtoolbar' );
+
+ newEditor.editing.view.isFocused = true;
+
+ // When image is selected along with text.
+ setModelData( newEditor.document, '
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla finibus consequat placerat. Vestibulum id tellus et mauris sagittis tincidunt quis id mauris. Curabitur consectetur lectus sit amet tellus mattis, non lobortis leo interdum.
+ +Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla finibus consequat placerat. Vestibulum id tellus et mauris sagittis tincidunt quis id mauris. Curabitur consectetur lectus sit amet tellus mattis, non lobortis leo interdum. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla finibus consequat placerat. Vestibulum id tellus et mauris sagittis tincidunt quis id mauris. Curabitur consectetur lectus sit amet tellus mattis, non lobortis leo interdum. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla finibus consequat placerat. Vestibulum id tellus et mauris sagittis tincidunt quis id mauris. Curabitur consectetur lectus sit amet tellus mattis, non lobortis leo interdum. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla finibus consequat placerat. Vestibulum id tellus et mauris sagittis tincidunt quis id mauris. Curabitur consectetur lectus sit amet tellus mattis, non lobortis leo interdum.
+Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla finibus consequat placerat. Vestibulum id tellus et mauris sagittis tincidunt quis id mauris. Curabitur consectetur lectus sit amet tellus mattis, non lobortis leo interdum.
+