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

Commit 835d0ac

Browse files
authored
Merge pull request #226 from ckeditor/t/222
Other: Added the `beforeShow` event to the `ContextualToolbar` plugin. Closes #222.
2 parents 5d91d18 + 827edae commit 835d0ac

File tree

2 files changed

+74
-10
lines changed

2 files changed

+74
-10
lines changed

src/toolbar/contextual/contextualtoolbar.js

Lines changed: 43 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -131,11 +131,14 @@ export default class ContextualToolbar extends Plugin {
131131
/**
132132
* Adds panel view to the {@link: #_balloon} and attaches panel to the selection.
133133
*
134+
* Fires {@link #event:beforeShow} event just before displaying the panel.
135+
*
134136
* @protected
135137
* @return {Promise} A promise resolved when the {@link #toolbarView} {@link module:ui/view~View#init} is done.
136138
*/
137139
_showPanel() {
138140
const editingView = this.editor.editing.view;
141+
let isStopped = false;
139142

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

150-
// Update panel position when selection changes while balloon will be opened (by a collaboration).
151-
this.listenTo( this.editor.editing.view, 'render', () => {
152-
this._balloon.updatePosition( this._getBalloonPositionData() );
153+
const showPromise = new Promise( ( resolve ) => {
154+
// If `beforeShow` event is not stopped by any external code then panel will be displayed.
155+
this.once( 'beforeShow', () => {
156+
if ( isStopped ) {
157+
resolve();
158+
159+
return;
160+
}
161+
162+
// Update panel position when selection changes while balloon will be opened
163+
// (by an external document changes).
164+
this.listenTo( editingView, 'render', () => {
165+
this._balloon.updatePosition( this._getBalloonPositionData() );
166+
} );
167+
168+
resolve(
169+
// Add panel to the common editor contextual balloon.
170+
this._balloon.add( {
171+
view: this.toolbarView,
172+
position: this._getBalloonPositionData(),
173+
balloonClassName: 'ck-toolbar-container'
174+
} )
175+
);
176+
} );
177+
}, { priority: 'lowest' } );
178+
179+
// Fire this event to inform that `ContextualToolbar` is going to be shown.
180+
// Helper function for preventing the panel from being displayed is passed along with the event.
181+
this.fire( 'beforeShow', () => {
182+
isStopped = true;
153183
} );
154184

155-
// Add panel to the common editor contextual balloon.
156-
return this._balloon.add( {
157-
view: this.toolbarView,
158-
position: this._getBalloonPositionData(),
159-
balloonClassName: 'ck-toolbar-container'
160-
} );
185+
return showPromise;
161186
}
162187

163188
/**
@@ -210,6 +235,15 @@ export default class ContextualToolbar extends Plugin {
210235
super.destroy();
211236
}
212237

238+
/**
239+
* This event is fired just before the toolbar shows.
240+
* Using this event, an external code can prevent ContextualToolbar
241+
* from being displayed by calling a `stop` function which is passed along with this event.
242+
*
243+
* @event beforeShow
244+
* @param {Function} stop Calling this function prevents panel from being displayed.
245+
*/
246+
213247
/**
214248
* This is internal plugin event which is fired 200 ms after model selection last change.
215249
* This is to makes easy test debounced action without need to use `setTimeout`.

tests/toolbar/contextual/contextualtoolbar.js

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ describe( 'ContextualToolbar', () => {
4949

5050
afterEach( () => {
5151
sandbox.restore();
52+
editorElement.remove();
5253

5354
return editor.destroy();
5455
} );
@@ -234,7 +235,7 @@ describe( 'ContextualToolbar', () => {
234235
let removeBalloonSpy;
235236

236237
beforeEach( () => {
237-
removeBalloonSpy = sandbox.spy( balloon, 'remove' );
238+
removeBalloonSpy = sandbox.stub( balloon, 'remove', () => {} );
238239
editor.editing.view.isFocused = true;
239240
} );
240241

@@ -388,6 +389,35 @@ describe( 'ContextualToolbar', () => {
388389
} );
389390
} );
390391

392+
describe( 'beforeShow event', () => {
393+
it( 'should fire `beforeShow` event just before panel shows', () => {
394+
const spy = sinon.spy();
395+
396+
contextualToolbar.on( 'beforeShow', spy );
397+
setData( editor.document, '<paragraph>b[a]r</paragraph>' );
398+
399+
const promise = contextualToolbar._showPanel();
400+
401+
sinon.assert.calledOnce( spy );
402+
403+
return promise;
404+
} );
405+
406+
it( 'should not show the panel when `beforeShow` event is stopped', () => {
407+
const balloonAddSpy = sandbox.spy( balloon, 'add' );
408+
409+
setData( editor.document, '<paragraph>b[a]r</paragraph>' );
410+
411+
contextualToolbar.on( 'beforeShow', ( evt, stop ) => {
412+
stop();
413+
} );
414+
415+
return contextualToolbar._showPanel().then( () => {
416+
sinon.assert.notCalled( balloonAddSpy );
417+
} );
418+
} );
419+
} );
420+
391421
function stubSelectionRect( forwardSelectionRect, backwardSelectionRect ) {
392422
const editingView = editor.editing.view;
393423
const originalViewRangeToDom = editingView.domConverter.viewRangeToDom;

0 commit comments

Comments
 (0)