Browse Source

BalloonToolbar should listen to ToolbarView#groupedItemsUpdate and re-position itself if the geometry of the toolbar has changed.

Aleksander Nowodzinski 5 years ago
parent
commit
555fd4ab0f

+ 22 - 1
packages/ckeditor5-ui/src/toolbar/balloon/balloontoolbar.js

@@ -165,6 +165,15 @@ export default class BalloonToolbar extends Plugin {
 				} );
 			} );
 		}
+
+		// Listen to the toolbar view and whenever it changes its geometry due to some items being
+		// grouped or ungrouped, update the position of the balloon because a shorter/longer toolbar
+		// means the balloon could be pointing at the wrong place. Once updated, the balloon will point
+		// at the right selection in the content again.
+		// https://github.com/ckeditor/ckeditor5/issues/6444
+		this.listenTo( this.toolbarView, 'groupedItemsUpdate', () => {
+			this._updatePosition();
+		} );
 	}
 
 	/**
@@ -236,7 +245,7 @@ export default class BalloonToolbar extends Plugin {
 
 		// Update the toolbar position when the editor ui should be refreshed.
 		this.listenTo( this.editor.ui, 'update', () => {
-			this._balloon.updatePosition( this._getBalloonPositionData() );
+			this._updatePosition();
 		} );
 
 		// Add the toolbar to the common editor contextual balloon.
@@ -301,6 +310,18 @@ export default class BalloonToolbar extends Plugin {
 	}
 
 	/**
+	 * Updates the position of the {@link #_balloon} to make up for changes:
+	 *
+	 * * in the geometry of the selection it is attached to (e.g. the selection moved in the viewport or expanded or shrunk),
+	 * * or the geometry of the balloon toolbar itself (e.g. the toolbar has grouped or ungrouped some items and it is shorter or longer).
+	 *
+	 * @private
+	 */
+	_updatePosition() {
+		this._balloon.updatePosition( this._getBalloonPositionData() );
+	}
+
+	/**
 	 * @inheritDoc
 	 */
 	destroy() {

+ 12 - 0
packages/ckeditor5-ui/tests/toolbar/balloon/balloontoolbar.js

@@ -361,6 +361,18 @@ describe( 'BalloonToolbar', () => {
 			sinon.assert.calledOnce( spy );
 		} );
 
+		it( 'should update the balloon position whenever #toolbarView fires the #groupedItemsUpdate (it changed its geometry)', () => {
+			setData( model, '<paragraph>b[a]r</paragraph>' );
+
+			const spy = sinon.spy( balloon, 'updatePosition' );
+
+			balloonToolbar.show();
+			sinon.assert.notCalled( spy );
+
+			balloonToolbar.toolbarView.fire( 'groupedItemsUpdate' );
+			sinon.assert.calledOnce( spy );
+		} );
+
 		it( 'should not add #toolbarView to the #_balloon more than once', () => {
 			setData( model, '<paragraph>b[a]r</paragraph>' );