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

Commit

Permalink
Merge pull request #226 from ckeditor/t/222
Browse files Browse the repository at this point in the history
Other: Added the `beforeShow` event to the `ContextualToolbar` plugin. Closes #222.
  • Loading branch information
oleq committed May 10, 2017
2 parents 5d91d18 + 827edae commit 835d0ac
Show file tree
Hide file tree
Showing 2 changed files with 74 additions and 10 deletions.
52 changes: 43 additions & 9 deletions src/toolbar/contextual/contextualtoolbar.js
Original file line number Diff line number Diff line change
Expand Up @@ -131,11 +131,14 @@ export default class ContextualToolbar extends Plugin {
/**
* Adds panel view to the {@link: #_balloon} and attaches panel to the selection.
*
* Fires {@link #event:beforeShow} event just before displaying the panel.
*
* @protected
* @return {Promise} A promise resolved when the {@link #toolbarView} {@link module:ui/view~View#init} is done.
*/
_showPanel() {
const editingView = this.editor.editing.view;
let isStopped = false;

// Do not add toolbar to the balloon stack twice.
if ( this._balloon.hasView( this.toolbarView ) ) {
Expand All @@ -147,17 +150,39 @@ export default class ContextualToolbar extends Plugin {
return Promise.resolve();
}

// Update panel position when selection changes while balloon will be opened (by a collaboration).
this.listenTo( this.editor.editing.view, 'render', () => {
this._balloon.updatePosition( this._getBalloonPositionData() );
const showPromise = new Promise( ( resolve ) => {
// If `beforeShow` event is not stopped by any external code then panel will be displayed.
this.once( 'beforeShow', () => {
if ( isStopped ) {
resolve();

return;
}

// Update panel position when selection changes while balloon will be opened
// (by an external document changes).
this.listenTo( editingView, 'render', () => {
this._balloon.updatePosition( this._getBalloonPositionData() );
} );

resolve(
// Add panel to the common editor contextual balloon.
this._balloon.add( {
view: this.toolbarView,
position: this._getBalloonPositionData(),
balloonClassName: 'ck-toolbar-container'
} )
);
} );
}, { priority: 'lowest' } );

// Fire this event to inform that `ContextualToolbar` is going to be shown.
// Helper function for preventing the panel from being displayed is passed along with the event.
this.fire( 'beforeShow', () => {
isStopped = true;
} );

// Add panel to the common editor contextual balloon.
return this._balloon.add( {
view: this.toolbarView,
position: this._getBalloonPositionData(),
balloonClassName: 'ck-toolbar-container'
} );
return showPromise;
}

/**
Expand Down Expand Up @@ -210,6 +235,15 @@ export default class ContextualToolbar extends Plugin {
super.destroy();
}

/**
* This event is fired just before the toolbar shows.
* Using this event, an external code can prevent ContextualToolbar
* from being displayed by calling a `stop` function which is passed along with this event.
*
* @event beforeShow
* @param {Function} stop Calling this function prevents panel from being displayed.
*/

/**
* This is internal plugin event which is fired 200 ms after model selection last change.
* This is to makes easy test debounced action without need to use `setTimeout`.
Expand Down
32 changes: 31 additions & 1 deletion tests/toolbar/contextual/contextualtoolbar.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ describe( 'ContextualToolbar', () => {

afterEach( () => {
sandbox.restore();
editorElement.remove();

return editor.destroy();
} );
Expand Down Expand Up @@ -234,7 +235,7 @@ describe( 'ContextualToolbar', () => {
let removeBalloonSpy;

beforeEach( () => {
removeBalloonSpy = sandbox.spy( balloon, 'remove' );
removeBalloonSpy = sandbox.stub( balloon, 'remove', () => {} );
editor.editing.view.isFocused = true;
} );

Expand Down Expand Up @@ -388,6 +389,35 @@ describe( 'ContextualToolbar', () => {
} );
} );

describe( 'beforeShow event', () => {
it( 'should fire `beforeShow` event just before panel shows', () => {
const spy = sinon.spy();

contextualToolbar.on( 'beforeShow', spy );
setData( editor.document, '<paragraph>b[a]r</paragraph>' );

const promise = contextualToolbar._showPanel();

sinon.assert.calledOnce( spy );

return promise;
} );

it( 'should not show the panel when `beforeShow` event is stopped', () => {
const balloonAddSpy = sandbox.spy( balloon, 'add' );

setData( editor.document, '<paragraph>b[a]r</paragraph>' );

contextualToolbar.on( 'beforeShow', ( evt, stop ) => {
stop();
} );

return contextualToolbar._showPanel().then( () => {
sinon.assert.notCalled( balloonAddSpy );
} );
} );
} );

function stubSelectionRect( forwardSelectionRect, backwardSelectionRect ) {
const editingView = editor.editing.view;
const originalViewRangeToDom = editingView.domConverter.viewRangeToDom;
Expand Down

0 comments on commit 835d0ac

Please sign in to comment.