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

Commit 66a30b1

Browse files
authored
Merge pull request #188 from ckeditor/t/182
Feature: Introduced `ContextualToolbar` plugin. Closes #182. Closes #187. Introduced several new positions in `BalloonPanelView#defaultPositions`. Added `className` attribute to the `BalloonPanelView` interface. BREAKING CHANGE: Default positions of the `BalloonPanelView` have been renamed. BREAKING CHANGE: Class names controlling the arrow of the panel have been renamed.
2 parents a7e7c94 + 94f6a15 commit 66a30b1

File tree

10 files changed

+986
-228
lines changed

10 files changed

+986
-228
lines changed

src/panel/balloon/balloonpanelview.js

Lines changed: 118 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ export default class BalloonPanelView extends View {
5252

5353
/**
5454
* Balloon panel's current position. The position name is reflected in the CSS class set
55-
* to the balloon, i.e. `.ck-balloon-panel_arrow_se` for "arrow_se" position. The class
55+
* to the balloon, i.e. `.ck-balloon-panel_arrow_ne` for "arrow_ne" position. The class
5656
* controls the minor aspects of the balloon's visual appearance like placement
5757
* of the "arrow". To support a new position, an additional CSS must be created.
5858
*
@@ -64,10 +64,10 @@ export default class BalloonPanelView extends View {
6464
* See {@link #withArrow}.
6565
*
6666
* @observable
67-
* @default 'arrow_se'
68-
* @member {'arrow_se'|'arrow_sw'|'arrow_ne'|'arrow_nw'} #position
67+
* @default 'arrow_ne'
68+
* @member {'arrow_ne'|'arrow_nw'|'arrow_se'|'arrow_sw'} #position
6969
*/
70-
this.set( 'position', 'arrow_se' );
70+
this.set( 'position', 'arrow_ne' );
7171

7272
/**
7373
* Controls whether the balloon panel is visible or not.
@@ -88,6 +88,14 @@ export default class BalloonPanelView extends View {
8888
*/
8989
this.set( 'withArrow', true );
9090

91+
/**
92+
* Additional css class added to the {#element}.
93+
*
94+
* @observable
95+
* @member {String} #className
96+
*/
97+
this.set( 'className' );
98+
9199
/**
92100
* Max width of the balloon panel, as in CSS.
93101
*
@@ -118,7 +126,8 @@ export default class BalloonPanelView extends View {
118126
'ck-balloon-panel',
119127
bind.to( 'position', ( value ) => `ck-balloon-panel_${ value }` ),
120128
bind.if( 'isVisible', 'ck-balloon-panel_visible' ),
121-
bind.if( 'withArrow', 'ck-balloon-panel_with-arrow' )
129+
bind.if( 'withArrow', 'ck-balloon-panel_with-arrow' ),
130+
bind.to( 'className' )
122131
],
123132

124133
style: {
@@ -171,10 +180,10 @@ export default class BalloonPanelView extends View {
171180
const positionOptions = Object.assign( {}, {
172181
element: this.element,
173182
positions: [
174-
defaultPositions.se,
175-
defaultPositions.sw,
176-
defaultPositions.ne,
177-
defaultPositions.nw
183+
defaultPositions.southEastArrowNorthEast,
184+
defaultPositions.southWestArrowNorthEast,
185+
defaultPositions.northEastArrowSouthWest,
186+
defaultPositions.northWestArrowSouthEast
178187
],
179188
limiter: defaultLimiterElement,
180189
fitInViewport: true
@@ -324,7 +333,7 @@ BalloonPanelView.arrowVerticalOffset = 15;
324333
*
325334
* The available positioning functions are as follows:
326335
*
327-
* * South east:
336+
* * South east (arrow north west):
328337
*
329338
* [ Target ]
330339
* ^
@@ -333,7 +342,7 @@ BalloonPanelView.arrowVerticalOffset = 15;
333342
* +-----------------+
334343
*
335344
*
336-
* * South west:
345+
* * South west (arrow north east):
337346
*
338347
* [ Target ]
339348
* ^
@@ -342,7 +351,7 @@ BalloonPanelView.arrowVerticalOffset = 15;
342351
* +-----------------+
343352
*
344353
*
345-
* * North east:
354+
* * North east (arrow south west):
346355
*
347356
* +-----------------+
348357
* | Balloon |
@@ -351,14 +360,66 @@ BalloonPanelView.arrowVerticalOffset = 15;
351360
* [ Target ]
352361
*
353362
*
354-
* * North west:
363+
* * North west (arrow south east):
355364
*
356365
* +-----------------+
357366
* | Balloon |
358367
* +-----------------+
359368
* V
360369
* [ Target ]
361370
*
371+
*
372+
* * South east (arrow north):
373+
*
374+
* [ Target ]
375+
* ^
376+
* +-----------------+
377+
* | Balloon |
378+
* +-----------------+
379+
*
380+
*
381+
* * North east (arrow south):
382+
*
383+
* +-----------------+
384+
* | Balloon |
385+
* +-----------------+
386+
* V
387+
* [ Target ]
388+
*
389+
*
390+
* * North west (arrow south):
391+
*
392+
* +-----------------+
393+
* | Balloon |
394+
* +-----------------+
395+
* V
396+
* [ Target ]
397+
*
398+
*
399+
* * South west (arrow north):
400+
*
401+
* [ Target ]
402+
* ^
403+
* +-----------------+
404+
* | Balloon |
405+
* +-----------------+
406+
*
407+
* * South (arrow north):
408+
*
409+
* [ Target ]
410+
* ^
411+
* +-----------------+
412+
* | Balloon |
413+
* +-----------------+
414+
*
415+
* * North (arrow south):
416+
*
417+
* +-----------------+
418+
* | Balloon |
419+
* +-----------------+
420+
* V
421+
* [ Target ]
422+
*
362423
* See {@link module:ui/panel/balloon/balloonpanelview~BalloonPanelView#attachTo}.
363424
*
364425
* Positioning functions must be compatible with {@link module:utils/dom/position~Position}.
@@ -369,27 +430,63 @@ BalloonPanelView.arrowVerticalOffset = 15;
369430
* @member {Object} module:ui/panel/balloon/balloonpanelview~BalloonPanelView.defaultPositions
370431
*/
371432
BalloonPanelView.defaultPositions = {
372-
se: ( targetRect ) => ( {
433+
southEastArrowNorthEast: ( targetRect ) => ( {
373434
top: targetRect.bottom + BalloonPanelView.arrowVerticalOffset,
374435
left: targetRect.left + targetRect.width / 2 - BalloonPanelView.arrowHorizontalOffset,
375-
name: 'arrow_se'
436+
name: 'arrow_ne'
376437
} ),
377438

378-
sw: ( targetRect, balloonRect ) => ( {
439+
southWestArrowNorthEast: ( targetRect, balloonRect ) => ( {
379440
top: targetRect.bottom + BalloonPanelView.arrowVerticalOffset,
380441
left: targetRect.left + targetRect.width / 2 - balloonRect.width + BalloonPanelView.arrowHorizontalOffset,
381-
name: 'arrow_sw'
442+
name: 'arrow_nw'
382443
} ),
383444

384-
ne: ( targetRect, balloonRect ) => ( {
445+
northEastArrowSouthWest: ( targetRect, balloonRect ) => ( {
385446
top: targetRect.top - balloonRect.height - BalloonPanelView.arrowVerticalOffset,
386447
left: targetRect.left + targetRect.width / 2 - BalloonPanelView.arrowHorizontalOffset,
387-
name: 'arrow_ne'
448+
name: 'arrow_se'
388449
} ),
389450

390-
nw: ( targetRect, balloonRect ) => ( {
451+
northWestArrowSouthEast: ( targetRect, balloonRect ) => ( {
391452
top: targetRect.top - balloonRect.height - BalloonPanelView.arrowVerticalOffset,
392453
left: targetRect.left + targetRect.width / 2 - balloonRect.width + BalloonPanelView.arrowHorizontalOffset,
393-
name: 'arrow_nw'
454+
name: 'arrow_sw'
455+
} ),
456+
457+
southEastArrowNorth: ( targetRect, balloonRect ) => ( {
458+
top: targetRect.bottom + BalloonPanelView.arrowVerticalOffset,
459+
left: targetRect.right - balloonRect.width / 2,
460+
name: 'arrow_n'
461+
} ),
462+
463+
northEastArrowSouth: ( targetRect, balloonRect ) => ( {
464+
top: targetRect.top - balloonRect.height - BalloonPanelView.arrowVerticalOffset,
465+
left: targetRect.right - balloonRect.width / 2,
466+
name: 'arrow_s'
467+
} ),
468+
469+
northWestArrowSouth: ( targetRect, balloonRect ) => ( {
470+
top: targetRect.top - balloonRect.height - BalloonPanelView.arrowVerticalOffset,
471+
left: targetRect.left - balloonRect.width / 2,
472+
name: 'arrow_s'
473+
} ),
474+
475+
southWestArrowNorth: ( targetRect, balloonRect ) => ( {
476+
top: targetRect.bottom + BalloonPanelView.arrowVerticalOffset,
477+
left: targetRect.left - balloonRect.width / 2,
478+
name: 'arrow_n'
479+
} ),
480+
481+
southArrowNorth: ( targetRect, balloonRect ) => ( {
482+
top: targetRect.bottom + BalloonPanelView.arrowVerticalOffset,
483+
left: targetRect.left + targetRect.width / 2 - balloonRect.width / 2,
484+
name: 'arrow_n'
485+
} ),
486+
487+
northArrowSouth: ( targetRect, balloonRect ) => ( {
488+
top: targetRect.top - balloonRect.height - BalloonPanelView.arrowVerticalOffset,
489+
left: targetRect.left + targetRect.width / 2 - balloonRect.width / 2,
490+
name: 'arrow_s'
394491
} )
395492
};

src/panel/balloon/contextualballoon.js

Lines changed: 26 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,13 @@ import CKEditorError from '@ckeditor/ckeditor5-utils/src/ckeditorerror';
2828
* @extends module:core/plugin~Plugin
2929
*/
3030
export default class ContextualBalloon extends Plugin {
31+
/**
32+
* @inheritDoc
33+
*/
34+
static get pluginName() {
35+
return 'ui/contextualballoon';
36+
}
37+
3138
/**
3239
* @inheritDoc
3340
*/
@@ -56,10 +63,6 @@ export default class ContextualBalloon extends Plugin {
5663
return this.editor.ui.view.body.add( this.view );
5764
}
5865

59-
static get pluginName() {
60-
return 'contextualballoon';
61-
}
62-
6366
/**
6467
* Returns the currently visible view or `null` when there are no
6568
* views in the stack.
@@ -88,6 +91,7 @@ export default class ContextualBalloon extends Plugin {
8891
* @param {Object} data Configuration of the view.
8992
* @param {module:ui/view~View} [data.view] Content of the balloon.
9093
* @param {module:utils/dom/position~Options} [data.position] Positioning options.
94+
* @param {String} [data.balloonClassName] Additional css class for {@link #view} added when given view is visible.
9195
* @returns {Promise} A Promise resolved when the child {@link module:ui/view~View#init} is done.
9296
*/
9397
add( data ) {
@@ -109,7 +113,7 @@ export default class ContextualBalloon extends Plugin {
109113
// Add new view to the stack.
110114
this._stack.set( data.view, data );
111115
// And display it.
112-
return this._show( data.view );
116+
return this._show( data );
113117
}
114118

115119
/**
@@ -147,7 +151,7 @@ export default class ContextualBalloon extends Plugin {
147151
// If it is some other view.
148152
if ( last ) {
149153
// Just show it.
150-
promise = this._show( last.view );
154+
promise = this._show( last );
151155
} else {
152156
// Hide the balloon panel.
153157
this.view.hide();
@@ -161,10 +165,16 @@ export default class ContextualBalloon extends Plugin {
161165
}
162166

163167
/**
164-
* Updates the position of the balloon panel according to position data
165-
* of the first view in the stack.
168+
* Updates the position of the balloon panel according to the given position data
169+
* or position data of the first view in the stack.
170+
*
171+
* @param {module:utils/dom/position~Options} [position] position options.
166172
*/
167-
updatePosition() {
173+
updatePosition( position ) {
174+
if ( position ) {
175+
this._stack.values().next().value.position = position;
176+
}
177+
168178
this.view.attachTo( this._getBalloonPosition() );
169179
}
170180

@@ -173,10 +183,13 @@ export default class ContextualBalloon extends Plugin {
173183
* options of the first view.
174184
*
175185
* @private
176-
* @param {module:ui/view~View} view View to show in the balloon.
177-
* @returns {Promise} A Promise resolved when the child {@link module:ui/view~View#init} is done.
186+
* @param {Object} data Configuration.
187+
* @param {module:ui/view~View} [data.view] View to show in the balloon.
188+
* @param {String} [data.balloonClassName=''] Additional class name which will added to the {#_balloon} view.
178189
*/
179-
_show( view ) {
190+
_show( { view, balloonClassName = '' } ) {
191+
this.view.className = balloonClassName;
192+
180193
return this.view.content.add( view ).then( () => {
181194
this.view.pin( this._getBalloonPosition() );
182195
} );
@@ -190,7 +203,7 @@ export default class ContextualBalloon extends Plugin {
190203
* @returns {module:utils/dom/position~Options}
191204
*/
192205
_getBalloonPosition() {
193-
return Array.from( this._stack.values() )[ 0 ].position;
206+
return this._stack.values().next().value.position;
194207
}
195208

196209
/**

0 commit comments

Comments
 (0)