Skip to content
This repository has been archived by the owner on Jun 26, 2020. It is now read-only.

Fixed integration between alternate text panel and image toolbar #41

Merged
merged 1 commit into from
Jan 27, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 24 additions & 12 deletions src/imagealternatetext/imagealternatetext.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import Plugin from '@ckeditor/ckeditor5-core/src/plugin';
import ButtonView from '@ckeditor/ckeditor5-ui/src/button/buttonview';
import ImageAlternateTextEngine from './imagealternatetextengine';
import escPressHandler from '@ckeditor/ckeditor5-ui/src/bindings/escpresshandler';
import clickOutsideHandler from '@ckeditor/ckeditor5-ui/src/bindings/clickoutsidehandler';
import ImageToolbar from '../imagetoolbar';
import AlternateTextFormView from './ui/alternatetextformview';
import ImageBalloonPanel from '../ui/imageballoonpanelview';
Expand Down Expand Up @@ -99,6 +100,21 @@ export default class ImageAlternateText extends Plugin {
this._hideBalloonPanel();
} );

// If image toolbar is present - hide it when alternate text balloon is visible.
const imageToolbar = editor.plugins.get( ImageToolbar );

if ( imageToolbar ) {
this.listenTo( panel, 'change:isVisible', () => {
if ( panel.isVisible ) {
imageToolbar.hide();
imageToolbar.isEnabled = false;
} else {
imageToolbar.show();
imageToolbar.isEnabled = true;
}
} );
}

this.listenTo( form, 'cancel', () => this._hideBalloonPanel() );

// Close on `ESC` press.
Expand All @@ -108,6 +124,14 @@ export default class ImageAlternateText extends Plugin {
callback: () => this._hideBalloonPanel()
} );

// Close on click outside of balloon panel element.
clickOutsideHandler( {
emitter: panel,
activator: () => panel.isVisible,
contextElement: panel.element,
callback: () => this._hideBalloonPanel()
} );

return Promise.all( [
panel.content.add( form ),
editor.ui.view.body.add( panel )
Expand All @@ -122,12 +146,6 @@ export default class ImageAlternateText extends Plugin {
_showBalloonPanel() {
const editor = this.editor;
const command = editor.commands.get( 'imageAlternateText' );
const imageToolbar = editor.plugins.get( ImageToolbar );

if ( imageToolbar ) {
imageToolbar.hide();
}

this.form.lebeledInput.value = command.value || '';
this.balloonPanel.attach();
this.form.lebeledInput.select();
Expand All @@ -142,11 +160,5 @@ export default class ImageAlternateText extends Plugin {
const editor = this.editor;
this.balloonPanel.detach();
editor.editing.view.focus();

const imageToolbar = editor.plugins.get( ImageToolbar );

if ( imageToolbar ) {
imageToolbar.show();
}
}
}
14 changes: 12 additions & 2 deletions src/imagetoolbar.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,14 @@ export default class ImageToolbar extends Plugin {
super( editor );

editor.config.set( 'image.defaultToolbar', [] );

/**
* When set to `true`, toolbar will be repositioned and showed on each render event and focus change.
* Set to `false` to temporary disable the image toolbar.
*
* @member {Boolean}
*/
this.isEnabled = true;
}

/**
Expand Down Expand Up @@ -70,12 +78,14 @@ export default class ImageToolbar extends Plugin {

// Show balloon panel each time image widget is selected.
this.listenTo( this.editor.editing.view, 'render', () => {
this.show();
if ( this.isEnabled ) {
this.show();
}
}, { priority: 'low' } );

// There is no render method after focus is back in editor, we need to check if balloon panel should be visible.
this.listenTo( editor.ui.focusTracker, 'change:isFocused', ( evt, name, is, was ) => {
if ( !was && is ) {
if ( !was && is && this.isEnabled ) {
this.show();
}
} );
Expand Down
94 changes: 69 additions & 25 deletions tests/imagealternatetext/imagealternatetext.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ import global from '@ckeditor/ckeditor5-utils/src/dom/global';
import { setData } from '@ckeditor/ckeditor5-engine/src/dev-utils/model';
import { keyCodes } from '@ckeditor/ckeditor5-utils/src/keyboard';

/* global Event */

describe( 'ImageAlternateText', () => {
let editor, plugin, command, balloonPanel, form;

Expand Down Expand Up @@ -72,31 +74,6 @@ describe( 'ImageAlternateText', () => {
sinon.assert.calledOnce( spy );
} );

it( 'should hide ImageToolbar on execute', () => {
const editorElement = global.document.createElement( 'div' );
global.document.body.appendChild( editorElement );

return ClassicTestEditor.create( editorElement, {
plugins: [ ImageAlternateText, Image, ImageToolbar ],
image: {
toolbar: [ 'imageAlternateText' ]
}
} )
.then( newEditor => {
newEditor.editing.view.attachDomRoot( editorElement );
const button = newEditor.ui.componentFactory.create( 'imageAlternateText' );
const toolbarPlugin = newEditor.plugins.get( ImageToolbar );

const spy = sinon.spy( toolbarPlugin, 'hide' );
setData( newEditor.document, '[<image src="" alt="foo bar"></image>]' );
button.fire( 'execute' );

sinon.assert.calledOnce( spy );

newEditor.destroy();
} );
} );

it( 'should set alt attribute value to textarea and select it', () => {
const spy = sinon.spy( form.lebeledInput, 'select' );
setData( editor.document, '[<image src="" alt="foo bar"></image>]' );
Expand Down Expand Up @@ -175,6 +152,73 @@ describe( 'ImageAlternateText', () => {
sinon.assert.called( hidePanelSpy );
} );
} );

describe( 'mouse', () => {
it( 'should close and not focus editable on click outside the panel', () => {
balloonPanel.isVisible = true;
global.document.body.dispatchEvent( new Event( 'mouseup', { bubbles: true } ) );

sinon.assert.called( hidePanelSpy );
} );

it( 'should not close on click inside the panel', () => {
balloonPanel.isVisible = true;
balloonPanel.element.dispatchEvent( new Event( 'mouseup', { bubbles: true } ) );

sinon.assert.notCalled( hidePanelSpy );
} );
} );
} );
} );

describe( 'working with ImageToolbar', () => {
let editor, button, imageToolbarPlugin, plugin;

beforeEach( () => {
const editorElement = global.document.createElement( 'div' );
global.document.body.appendChild( editorElement );

return ClassicTestEditor.create( editorElement, {
plugins: [ ImageAlternateText, Image, ImageToolbar ],
image: {
toolbar: [ 'imageAlternateText' ]
}
} )
.then( newEditor => {
editor = newEditor;
editor.editing.view.attachDomRoot( editorElement );
button = newEditor.ui.componentFactory.create( 'imageAlternateText' );
imageToolbarPlugin = newEditor.plugins.get( ImageToolbar );
plugin = editor.plugins.get( ImageAlternateText );
} );
} );

afterEach( () => editor.destroy() );

it( 'should hide ImageToolbar when visible', () => {
setData( editor.document, '[<image src="" alt="foo bar"></image>]' );
const spy = sinon.spy( imageToolbarPlugin, 'hide' );
button.fire( 'execute' );

sinon.assert.calledOnce( spy );
} );

it( 'ImageToolbar should not show when alternate text panel is visible', () => {
setData( editor.document, '[<image src="" alt="foo bar"></image>]' );
button.fire( 'execute' );
const spy = sinon.spy( imageToolbarPlugin, 'show' );
editor.editing.view.render();

sinon.assert.notCalled( spy );
} );

it( 'ImageToolbar should show when alternate text panel is not visible', () => {
setData( editor.document, '[<image src="" alt="foo bar"></image>]' );
button.fire( 'execute' );
const spy = sinon.spy( imageToolbarPlugin, 'show' );
plugin.balloonPanel.isVisible = false;

sinon.assert.called( spy );
} );
} );
} );
11 changes: 11 additions & 0 deletions tests/imagetoolbar.js
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,17 @@ describe( 'ImageToolbar', () => {
sinon.assert.calledOnce( spy );
} );

it( 'should not show the panel automatically when it is disabled', () => {
plugin.isEnabled = false;
setData( doc, '[<image src=""></image>]' );
editor.ui.focusTracker.isFocused = true;
const spy = sinon.spy( plugin, 'show' );

editingView.render();

sinon.assert.notCalled( spy );
} );

it( 'should not show the panel when editor looses focus', () => {
editor.ui.focusTracker.isFocused = true;
const spy = sinon.spy( plugin, 'show' );
Expand Down