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

Commit b10b43c

Browse files
authored
Merge pull request #300 from ckeditor/t/297
Feature: Replaced `StickyToolbarView` with a generic `StickyPanelView`. Closes #297. BREAKING CHANGE: The `StickyToolbarView` and corresponding CSS `.ck-sticky-panel` classes are no longer available. `StickyPanelView` + `ToolbarView` combo should be used instead.
2 parents b8b1ccd + df712c0 commit b10b43c

File tree

10 files changed

+145
-121
lines changed

10 files changed

+145
-121
lines changed
Lines changed: 52 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -4,22 +4,20 @@
44
*/
55

66
/**
7-
* @module ui/toolbar/sticky/stickytoolbarview
7+
* @module ui/panel/sticky/stickypanelview
88
*/
99

1010
import global from '@ckeditor/ckeditor5-utils/src/dom/global';
11+
import View from '../../view';
1112
import Template from '../../template';
12-
import ToolbarView from '../toolbarview';
1313
import toUnit from '@ckeditor/ckeditor5-utils/src/dom/tounit';
1414

1515
const toPx = toUnit( 'px' );
1616

1717
/**
18-
* The sticky toolbar view class.
19-
*
20-
* @extends module:ui/toolbar/toolbarview~ToolbarView
18+
* The sticky panel view class.
2119
*/
22-
export default class StickyToolbarView extends ToolbarView {
20+
export default class StickyPanelView extends View {
2321
/**
2422
* @inheritDoc
2523
*/
@@ -29,8 +27,7 @@ export default class StickyToolbarView extends ToolbarView {
2927
const bind = this.bindTemplate;
3028

3129
/**
32-
* Controls whether the sticky toolbar should be active. When any editable
33-
* is focused in the editor, toolbar becomes active.
30+
* Controls whether the sticky panel should be active.
3431
*
3532
* @readonly
3633
* @observable
@@ -39,7 +36,7 @@ export default class StickyToolbarView extends ToolbarView {
3936
this.set( 'isActive', false );
4037

4138
/**
42-
* Controls whether the sticky toolbar is in the "sticky" state.
39+
* Controls whether the sticky panel is in the "sticky" state.
4340
*
4441
* @readonly
4542
* @observable
@@ -48,10 +45,10 @@ export default class StickyToolbarView extends ToolbarView {
4845
this.set( 'isSticky', false );
4946

5047
/**
51-
* The limiter element for the sticky toolbar instance. Its bounding rect limits
52-
* the "stickyness" of the toolbar, i.e. when the toolbar reaches the bottom
48+
* The limiter element for the sticky panel instance. Its bounding rect limits
49+
* the "stickyness" of the panel, i.e. when the panel reaches the bottom
5350
* edge of the limiter, it becomes sticky to that edge and does not float
54-
* off the limiter. It is mandatory for the toolbar to work properly and once
51+
* off the limiter. It is mandatory for the panel to work properly and once
5552
* set, it cannot be changed.
5653
*
5754
* @readonly
@@ -62,7 +59,7 @@ export default class StickyToolbarView extends ToolbarView {
6259

6360
/**
6461
* The offset from the bottom edge of {@link #limiterElement}
65-
* which stops the toolbar from stickying any further to prevent limiter's content
62+
* which stops the panel from stickying any further to prevent limiter's content
6663
* from being completely covered.
6764
*
6865
* @readonly
@@ -74,12 +71,12 @@ export default class StickyToolbarView extends ToolbarView {
7471

7572
/**
7673
* The offset from the top edge of the web browser's viewport which makes the
77-
* toolbar become sticky. The default value is `0`, which means the toolbar becomes
74+
* panel become sticky. The default value is `0`, which means the panel becomes
7875
* sticky when it's upper edge touches the top of the page viewport.
7976
*
8077
* This attribute is useful when the web page has UI elements positioned to the top
8178
* either using `position: fixed` or `position: sticky`, which would cover the
82-
* sticky toolbar or vice–versa (depending on the `z-index` hierarchy).
79+
* sticky panel or vice–versa (depending on the `z-index` hierarchy).
8380
*
8481
* @readonly
8582
* @observable
@@ -89,7 +86,7 @@ export default class StickyToolbarView extends ToolbarView {
8986
this.set( 'viewportTopOffset', 0 );
9087

9188
/**
92-
* Controls the `margin-left` CSS style of the toolbar.
89+
* Controls the `margin-left` CSS style of the panel.
9390
*
9491
* @protected
9592
* @readonly
@@ -99,7 +96,7 @@ export default class StickyToolbarView extends ToolbarView {
9996
this.set( '_marginLeft', null );
10097

10198
/**
102-
* Set `true` if the sticky toolbar reached the bottom edge of the
99+
* Set `true` if the sticky panel reached the bottom edge of the
103100
* {@link #limiterElement}.
104101
*
105102
* @protected
@@ -110,7 +107,7 @@ export default class StickyToolbarView extends ToolbarView {
110107
this.set( '_isStickyToTheLimiter', false );
111108

112109
/**
113-
* Set `true` if the sticky toolbar uses the {@link #viewportTopOffset},
110+
* Set `true` if the sticky panel uses the {@link #viewportTopOffset},
114111
* i.e. not {@link #_isStickyToTheLimiter} and the {@link #viewportTopOffset}
115112
* is not `0`.
116113
*
@@ -122,26 +119,37 @@ export default class StickyToolbarView extends ToolbarView {
122119
this.set( '_hasViewportTopOffset', false );
123120

124121
/**
125-
* The DOM bounding client rect of the {@link module:ui/view~View#element} of the toolbar.
122+
* Collection of the child views which creates balloon panel contents.
123+
*
124+
* @readonly
125+
* @member {module:ui/viewcollection~ViewCollection}
126+
*/
127+
this.content = this.createCollection();
128+
129+
/**
130+
* The DOM bounding client rect of the {@link module:ui/view~View#element} of the panel.
126131
*
127132
* @protected
128-
* @member {Object} #_toolbarRect
133+
* @member {Object} #_panelRect
129134
*/
130135

131136
/**
132137
* The DOM bounding client rect of the {@link #limiterElement}
133-
* of the toolbar.
138+
* of the panel.
134139
*
135140
* @protected
136141
* @member {Object} #_limiterRect
137142
*/
138143

139-
Template.extend( this.template, {
144+
this.template = new Template( {
145+
tag: 'div',
146+
140147
attributes: {
141148
class: [
142-
// Toggle class of the toolbar when "sticky" state changes in the view.
143-
bind.if( 'isSticky', 'ck-toolbar_sticky' ),
144-
bind.if( '_isStickyToTheLimiter', 'ck-toolbar_sticky_bottom-limit' ),
149+
'ck-sticky-panel',
150+
// Toggle class of the panel when "sticky" state changes in the view.
151+
bind.if( 'isSticky', 'ck-sticky-panel_sticky' ),
152+
bind.if( '_isStickyToTheLimiter', 'ck-sticky-panel_sticky_bottom-limit' ),
145153
],
146154
style: {
147155
width: bind.to( 'isSticky', isSticky => {
@@ -158,12 +166,14 @@ export default class StickyToolbarView extends ToolbarView {
158166

159167
marginLeft: bind.to( '_marginLeft' )
160168
}
161-
}
169+
},
170+
171+
children: this.content
162172
} );
163173

164174
/**
165175
* A dummy element which visually fills the space as long as the
166-
* actual toolbar is sticky. It prevents flickering of the UI.
176+
* actual panel is sticky. It prevents flickering of the UI.
167177
*
168178
* @private
169179
* @property {HTMLElement}
@@ -172,12 +182,12 @@ export default class StickyToolbarView extends ToolbarView {
172182
tag: 'div',
173183
attributes: {
174184
class: [
175-
'ck-toolbar__placeholder'
185+
'ck-sticky-panel__placeholder'
176186
],
177187
style: {
178188
display: bind.to( 'isSticky', isSticky => isSticky ? 'block' : 'none' ),
179189
height: bind.to( 'isSticky', isSticky => {
180-
return isSticky ? toPx( this._toolbarRect.height ) : null;
190+
return isSticky ? toPx( this._panelRect.height ) : null;
181191
} )
182192
}
183193
}
@@ -192,57 +202,57 @@ export default class StickyToolbarView extends ToolbarView {
192202

193203
this.element.parentNode.insertBefore( this._elementPlaceholder, this.element );
194204

195-
// Check if the toolbar should go into the sticky state immediately.
205+
// Check if the panel should go into the sticky state immediately.
196206
this._checkIfShouldBeSticky();
197207

198-
// Update sticky state of the toolbar as the window is being scrolled.
208+
// Update sticky state of the panel as the window is being scrolled.
199209
this.listenTo( global.window, 'scroll', () => {
200210
this._checkIfShouldBeSticky();
201211
} );
202212

203-
// Synchronize with `model.isActive` because sticking an inactive toolbar is pointless.
213+
// Synchronize with `model.isActive` because sticking an inactive panel is pointless.
204214
this.listenTo( this, 'change:isActive', () => {
205215
this._checkIfShouldBeSticky();
206216
} );
207217
}
208218

209219
/**
210-
* Destroys the toolbar and removes the {@link #_elementPlaceholder}.
220+
* Destroys the panel and removes the {@link #_elementPlaceholder}.
211221
*/
212222
destroy() {
213223
super.destroy();
214224
this._elementPlaceholder.remove();
215225
}
216226

217227
/**
218-
* Analyzes the environment to decide whether the toolbar should
228+
* Analyzes the environment to decide whether the panel should
219229
* be sticky or not.
220230
*
221231
* @protected
222232
*/
223233
_checkIfShouldBeSticky() {
224234
const limiterRect = this._limiterRect = this.limiterElement.getBoundingClientRect();
225-
const toolbarRect = this._toolbarRect = this.element.getBoundingClientRect();
235+
const panelRect = this._panelRect = this.element.getBoundingClientRect();
226236

227-
// The toolbar must be active to become sticky.
237+
// The panel must be active to become sticky.
228238
this.isSticky = this.isActive &&
229239
// The limiter's top edge must be beyond the upper edge of the visible viewport (+the viewportTopOffset).
230240
limiterRect.top < this.viewportTopOffset &&
231-
// The model#limiterElement's height mustn't be smaller than the toolbar's height and model#limiterBottomOffset.
241+
// The model#limiterElement's height mustn't be smaller than the panel's height and model#limiterBottomOffset.
232242
// There's no point in entering the sticky mode if the model#limiterElement is very, very small, because
233-
// it would immediately set model#_isStickyToTheLimiter true and, given model#limiterBottomOffset, the toolbar
243+
// it would immediately set model#_isStickyToTheLimiter true and, given model#limiterBottomOffset, the panel
234244
// would be positioned before the model#limiterElement.
235-
this._toolbarRect.height + this.limiterBottomOffset < limiterRect.height;
245+
this._panelRect.height + this.limiterBottomOffset < limiterRect.height;
236246

237-
// Stick the toolbar to the top edge of the viewport simulating CSS position:sticky.
247+
// Stick the panel to the top edge of the viewport simulating CSS position:sticky.
238248
// TODO: Possibly replaced by CSS in the future http://caniuse.com/#feat=css-sticky
239249
if ( this.isSticky ) {
240250
this._isStickyToTheLimiter =
241-
limiterRect.bottom < toolbarRect.height + this.limiterBottomOffset + this.viewportTopOffset;
251+
limiterRect.bottom < panelRect.height + this.limiterBottomOffset + this.viewportTopOffset;
242252
this._hasViewportTopOffset = !this._isStickyToTheLimiter && !!this.viewportTopOffset;
243253
this._marginLeft = this._isStickyToTheLimiter ? null : toPx( -global.window.scrollX );
244254
}
245-
// Detach the toolbar from the top edge of the viewport.
255+
// Detach the panel from the top edge of the viewport.
246256
else {
247257
this._isStickyToTheLimiter = false;
248258
this._hasViewportTopOffset = false;

src/view.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
import CKEditorError from '@ckeditor/ckeditor5-utils/src/ckeditorerror';
1111
import ViewCollection from './viewcollection';
1212
import Template from './template';
13-
import DomEmmiterMixin from '@ckeditor/ckeditor5-utils/src/dom/emittermixin';
13+
import DomEmitterMixin from '@ckeditor/ckeditor5-utils/src/dom/emittermixin';
1414
import ObservableMixin from '@ckeditor/ckeditor5-utils/src/observablemixin';
1515
import Collection from '@ckeditor/ckeditor5-utils/src/collection';
1616
import mix from '@ckeditor/ckeditor5-utils/src/mix';
@@ -326,5 +326,5 @@ export default class View {
326326
}
327327
}
328328

329-
mix( View, DomEmmiterMixin );
329+
mix( View, DomEmitterMixin );
330330
mix( View, ObservableMixin );

tests/manual/stickytoolbarview/stickytoolbarview.html renamed to tests/manual/panel/sticky/stickypanelview.html

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ <h2>Sticky to the green box</h2>
3535
<div class="ck-reset_all offset-visualizer"></div>
3636
</div>
3737

38-
<div id="fixed">The toolbar should stick to me instead of the viewport.</div>
38+
<div id="fixed">The panel should stick to me instead of the viewport.</div>
3939
</div>
4040
</div>
4141

@@ -62,13 +62,13 @@ <h2>Sticky to the green box</h2>
6262
position: relative;
6363
}
6464

65-
.ck-toolbar {
65+
.ck-sticky-panel {
6666
background: yellow !important;
6767
padding: 1em;
6868
}
6969

70-
.ck-toolbar:after {
71-
content: "A toolbar mock–up.";
70+
.ck-sticky-panel:after {
71+
content: "A sticky panel mock–up.";
7272
}
7373

7474
.offset-visualizer {
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
/**
2+
* @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3+
* For licensing, see LICENSE.md.
4+
*/
5+
6+
import testUtils from '../../../_utils/utils';
7+
import StickyPanelView from '../../../../src/panel/sticky/stickypanelview';
8+
9+
import '@ckeditor/ckeditor5-theme-lark/theme/theme.scss';
10+
11+
const ui = testUtils.createTestUIView( {
12+
stickyToTheTop: '.ck-sticky_to-the-top .ck-editor__top',
13+
stickyToTheBox: '.ck-sticky_to-the-box .ck-editor__top'
14+
} );
15+
16+
createStickyPanel( ui.stickyToTheTop );
17+
const stickyToTheBoxTPanel = createStickyPanel( ui.stickyToTheBox );
18+
19+
stickyToTheBoxTPanel.viewportTopOffset = 100;
20+
21+
function createStickyPanel( collection ) {
22+
const panel = new StickyPanelView();
23+
24+
panel.limiterElement = collection._parentElement.parentNode;
25+
26+
collection.add( panel );
27+
panel.isActive = true;
28+
29+
return panel;
30+
}

tests/manual/stickytoolbarview/stickytoolbarview.md renamed to tests/manual/panel/sticky/stickypanelview.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,24 +2,24 @@
22

33
### Sticky to the top of the viewport
44

5-
1. When the page is scrolled vertically, the toolbar should
5+
1. When the page is scrolled vertically, the panel should
66
1. stick to the top of the viewport first,
77
1. then disappear beyond the upper edge of the viewport as it touches the red area
88
1. but never cover the red area or go beyond the upper edge of editor mock–up.
99

1010
### Sticky to the green box
1111

12-
1. When the page is scrolled vertically, the toolbar should
12+
1. When the page is scrolled vertically, the panel should
1313
1. stick to the bottom of the green box first,
1414
1. then disappear beyond the bottom edge of the green box as it touches the red area
1515
1. but never cover the red area or go beyond the upper edge of editor mock–up.
1616

1717
## Horizontal scrolling
1818

19-
1. The toolbar should always fit horizontally within the editor mock–up, regardless of the position of the h– and v–scrolls of the web page.
19+
1. The panel should always fit horizontally within the editor mock–up, regardless of the position of the h– and v–scrolls of the web page.
2020

2121
## On–load positioning
2222

23-
1. Scroll the web page vertically and horizontally, so the toolbar is sticky.
23+
1. Scroll the web page vertically and horizontally, so the panel is sticky.
2424
1. Reload the web page.
25-
1. The toolbar should get sticky as the page reloads, if the position of scrollbars and the geometry of the viewport creates such a need.
25+
1. The panel should get sticky as the page reloads, if the position of scrollbars and the geometry of the viewport creates such a need.

tests/manual/stickytoolbarview/stickytoolbarview.js

Lines changed: 0 additions & 30 deletions
This file was deleted.

0 commit comments

Comments
 (0)