@ckeditor/ckeditor5-ui 40.0.0 → 40.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +26 -26
- package/LICENSE.md +3 -3
- package/lang/translations/gl.po +4 -4
- package/lang/translations/pt-br.po +1 -1
- package/lang/translations/sr-latn.po +6 -6
- package/lang/translations/ug.po +26 -26
- package/package.json +3 -3
- package/src/arialiveannouncer.d.ts +94 -0
- package/src/arialiveannouncer.js +113 -0
- package/src/augmentation.d.ts +86 -86
- package/src/augmentation.js +5 -5
- package/src/autocomplete/autocompleteview.d.ts +81 -81
- package/src/autocomplete/autocompleteview.js +153 -146
- package/src/bindings/addkeyboardhandlingforgrid.d.ts +27 -27
- package/src/bindings/addkeyboardhandlingforgrid.js +107 -107
- package/src/bindings/clickoutsidehandler.d.ts +28 -28
- package/src/bindings/clickoutsidehandler.js +36 -36
- package/src/bindings/csstransitiondisablermixin.d.ts +40 -40
- package/src/bindings/csstransitiondisablermixin.js +55 -55
- package/src/bindings/injectcsstransitiondisabler.d.ts +59 -59
- package/src/bindings/injectcsstransitiondisabler.js +71 -71
- package/src/bindings/preventdefault.d.ts +33 -33
- package/src/bindings/preventdefault.js +34 -34
- package/src/bindings/submithandler.d.ts +57 -57
- package/src/bindings/submithandler.js +47 -47
- package/src/button/button.d.ts +172 -178
- package/src/button/button.js +5 -5
- package/src/button/buttonlabel.d.ts +34 -34
- package/src/button/buttonlabel.js +5 -5
- package/src/button/buttonlabelview.d.ts +31 -31
- package/src/button/buttonlabelview.js +42 -42
- package/src/button/buttonview.d.ts +181 -185
- package/src/button/buttonview.js +217 -219
- package/src/button/switchbuttonview.d.ts +45 -45
- package/src/button/switchbuttonview.js +75 -75
- package/src/collapsible/collapsibleview.d.ts +69 -0
- package/src/collapsible/collapsibleview.js +95 -0
- package/src/colorgrid/colorgridview.d.ts +132 -132
- package/src/colorgrid/colorgridview.js +124 -124
- package/src/colorgrid/colortileview.d.ts +28 -28
- package/src/colorgrid/colortileview.js +40 -40
- package/src/colorgrid/utils.d.ts +47 -47
- package/src/colorgrid/utils.js +84 -84
- package/src/colorpicker/colorpickerview.d.ts +137 -137
- package/src/colorpicker/colorpickerview.js +270 -270
- package/src/colorpicker/utils.d.ts +43 -43
- package/src/colorpicker/utils.js +99 -99
- package/src/colorselector/colorgridsfragmentview.d.ts +194 -194
- package/src/colorselector/colorgridsfragmentview.js +289 -289
- package/src/colorselector/colorpickerfragmentview.d.ts +128 -128
- package/src/colorselector/colorpickerfragmentview.js +205 -205
- package/src/colorselector/colorselectorview.d.ts +242 -242
- package/src/colorselector/colorselectorview.js +256 -256
- package/src/colorselector/documentcolorcollection.d.ts +70 -70
- package/src/colorselector/documentcolorcollection.js +42 -42
- package/src/componentfactory.d.ts +81 -81
- package/src/componentfactory.js +104 -104
- package/src/dropdown/button/dropdownbutton.d.ts +25 -25
- package/src/dropdown/button/dropdownbutton.js +5 -5
- package/src/dropdown/button/dropdownbuttonview.d.ts +48 -48
- package/src/dropdown/button/dropdownbuttonview.js +66 -66
- package/src/dropdown/button/splitbuttonview.d.ts +162 -161
- package/src/dropdown/button/splitbuttonview.js +154 -152
- package/src/dropdown/dropdownpanelfocusable.d.ts +21 -21
- package/src/dropdown/dropdownpanelfocusable.js +5 -5
- package/src/dropdown/dropdownpanelview.d.ts +62 -62
- package/src/dropdown/dropdownpanelview.js +97 -97
- package/src/dropdown/dropdownview.d.ts +315 -315
- package/src/dropdown/dropdownview.js +379 -379
- package/src/dropdown/utils.d.ts +235 -235
- package/src/dropdown/utils.js +463 -458
- package/src/editableui/editableuiview.d.ts +72 -72
- package/src/editableui/editableuiview.js +112 -112
- package/src/editableui/inline/inlineeditableuiview.d.ts +40 -40
- package/src/editableui/inline/inlineeditableuiview.js +48 -48
- package/src/editorui/bodycollection.d.ts +55 -55
- package/src/editorui/bodycollection.js +84 -84
- package/src/editorui/boxed/boxededitoruiview.d.ts +40 -40
- package/src/editorui/boxed/boxededitoruiview.js +81 -81
- package/src/editorui/editorui.d.ts +288 -282
- package/src/editorui/editorui.js +412 -410
- package/src/editorui/editoruiview.d.ts +39 -39
- package/src/editorui/editoruiview.js +38 -38
- package/src/editorui/poweredby.d.ts +71 -71
- package/src/editorui/poweredby.js +276 -276
- package/src/focuscycler.d.ts +226 -226
- package/src/focuscycler.js +245 -245
- package/src/formheader/formheaderview.d.ts +59 -59
- package/src/formheader/formheaderview.js +69 -69
- package/src/highlightedtext/highlightedtextview.d.ts +38 -38
- package/src/highlightedtext/highlightedtextview.js +102 -102
- package/src/icon/iconview.d.ts +85 -85
- package/src/icon/iconview.js +114 -114
- package/src/iframe/iframeview.d.ts +50 -50
- package/src/iframe/iframeview.js +63 -63
- package/src/index.d.ts +74 -73
- package/src/index.js +71 -70
- package/src/input/inputbase.d.ts +107 -107
- package/src/input/inputbase.js +110 -110
- package/src/input/inputview.d.ts +36 -36
- package/src/input/inputview.js +24 -24
- package/src/inputnumber/inputnumberview.d.ts +49 -49
- package/src/inputnumber/inputnumberview.js +40 -40
- package/src/inputtext/inputtextview.d.ts +18 -18
- package/src/inputtext/inputtextview.js +27 -27
- package/src/label/labelview.d.ts +36 -36
- package/src/label/labelview.js +41 -41
- package/src/labeledfield/labeledfieldview.d.ts +187 -187
- package/src/labeledfield/labeledfieldview.js +157 -157
- package/src/labeledfield/utils.d.ts +123 -123
- package/src/labeledfield/utils.js +176 -176
- package/src/labeledinput/labeledinputview.d.ts +125 -125
- package/src/labeledinput/labeledinputview.js +125 -125
- package/src/list/listitemgroupview.d.ts +59 -51
- package/src/list/listitemgroupview.js +67 -75
- package/src/list/listitemview.d.ts +36 -36
- package/src/list/listitemview.js +42 -42
- package/src/list/listseparatorview.d.ts +18 -18
- package/src/list/listseparatorview.js +28 -28
- package/src/list/listview.d.ts +123 -122
- package/src/list/listview.js +188 -187
- package/src/model.d.ts +22 -22
- package/src/model.js +31 -31
- package/src/notification/notification.d.ts +211 -211
- package/src/notification/notification.js +187 -187
- package/src/panel/balloon/balloonpanelview.d.ts +685 -685
- package/src/panel/balloon/balloonpanelview.js +1010 -1010
- package/src/panel/balloon/contextualballoon.d.ts +299 -299
- package/src/panel/balloon/contextualballoon.js +572 -572
- package/src/panel/sticky/stickypanelview.d.ts +156 -156
- package/src/panel/sticky/stickypanelview.js +234 -234
- package/src/search/filteredview.d.ts +31 -31
- package/src/search/filteredview.js +5 -5
- package/src/search/searchinfoview.d.ts +45 -45
- package/src/search/searchinfoview.js +59 -59
- package/src/search/searchresultsview.d.ts +54 -54
- package/src/search/searchresultsview.js +65 -65
- package/src/search/text/searchtextqueryview.d.ts +76 -76
- package/src/search/text/searchtextqueryview.js +75 -75
- package/src/search/text/searchtextview.d.ts +219 -219
- package/src/search/text/searchtextview.js +201 -201
- package/src/spinner/spinnerview.d.ts +25 -25
- package/src/spinner/spinnerview.js +38 -38
- package/src/template.d.ts +942 -942
- package/src/template.js +1294 -1294
- package/src/textarea/textareaview.d.ts +88 -88
- package/src/textarea/textareaview.js +142 -140
- package/src/toolbar/balloon/balloontoolbar.d.ts +122 -122
- package/src/toolbar/balloon/balloontoolbar.js +300 -300
- package/src/toolbar/block/blockbuttonview.d.ts +35 -35
- package/src/toolbar/block/blockbuttonview.js +41 -41
- package/src/toolbar/block/blocktoolbar.d.ts +161 -161
- package/src/toolbar/block/blocktoolbar.js +395 -395
- package/src/toolbar/normalizetoolbarconfig.d.ts +40 -40
- package/src/toolbar/normalizetoolbarconfig.js +52 -51
- package/src/toolbar/toolbarlinebreakview.d.ts +18 -18
- package/src/toolbar/toolbarlinebreakview.js +28 -28
- package/src/toolbar/toolbarseparatorview.d.ts +18 -18
- package/src/toolbar/toolbarseparatorview.js +28 -28
- package/src/toolbar/toolbarview.d.ts +266 -266
- package/src/toolbar/toolbarview.js +719 -719
- package/src/tooltipmanager.d.ts +180 -180
- package/src/tooltipmanager.js +353 -353
- package/src/view.d.ts +422 -422
- package/src/view.js +396 -396
- package/src/viewcollection.d.ts +139 -139
- package/src/viewcollection.js +206 -206
- package/theme/components/arialiveannouncer/arialiveannouncer.css +10 -0
- package/theme/components/button/button.css +9 -1
- package/theme/components/collapsible/collapsible.css +10 -0
- package/theme/components/formheader/formheader.css +0 -4
|
@@ -1,1010 +1,1010 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @license Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved.
|
|
3
|
-
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
|
|
4
|
-
*/
|
|
5
|
-
/**
|
|
6
|
-
* @module ui/panel/balloon/balloonpanelview
|
|
7
|
-
*/
|
|
8
|
-
import View from '../../view';
|
|
9
|
-
import { getOptimalPosition, global, isRange, toUnit } from '@ckeditor/ckeditor5-utils';
|
|
10
|
-
import { isElement } from 'lodash-es';
|
|
11
|
-
import '../../../theme/components/panel/balloonpanel.css';
|
|
12
|
-
const toPx = toUnit('px');
|
|
13
|
-
const defaultLimiterElement = global.document.body;
|
|
14
|
-
// A static balloon panel positioning function that moves the balloon far off the viewport.
|
|
15
|
-
// It is used as a fallback when there is no way to position the balloon using provided
|
|
16
|
-
// positioning functions (see: `getOptimalPosition()`), for instance, when the target the
|
|
17
|
-
// balloon should be attached to gets obscured by scrollable containers or the viewport.
|
|
18
|
-
//
|
|
19
|
-
// It prevents the balloon from being attached to the void and possible degradation of the UX.
|
|
20
|
-
// At the same time, it keeps the balloon physically visible in the DOM so the focus remains
|
|
21
|
-
// uninterrupted.
|
|
22
|
-
const POSITION_OFF_SCREEN = {
|
|
23
|
-
top: -99999,
|
|
24
|
-
left: -99999,
|
|
25
|
-
name: 'arrowless',
|
|
26
|
-
config: {
|
|
27
|
-
withArrow: false
|
|
28
|
-
}
|
|
29
|
-
};
|
|
30
|
-
/**
|
|
31
|
-
* The balloon panel view class.
|
|
32
|
-
*
|
|
33
|
-
* A floating container which can
|
|
34
|
-
* {@link module:ui/panel/balloon/balloonpanelview~BalloonPanelView#pin pin} to any
|
|
35
|
-
* {@link module:utils/dom/position~Options#target target} in the DOM and remain in that position
|
|
36
|
-
* e.g. when the web page is scrolled.
|
|
37
|
-
*
|
|
38
|
-
* The balloon panel can be used to display contextual, non-blocking UI like forms, toolbars and
|
|
39
|
-
* the like in its {@link module:ui/panel/balloon/balloonpanelview~BalloonPanelView#content} view
|
|
40
|
-
* collection.
|
|
41
|
-
*
|
|
42
|
-
* There is a number of {@link module:ui/panel/balloon/balloonpanelview~BalloonPanelView.defaultPositions}
|
|
43
|
-
* that the balloon can use, automatically switching from one to another when the viewport space becomes
|
|
44
|
-
* scarce to keep the balloon visible to the user as long as it is possible. The balloon will also
|
|
45
|
-
* accept any custom position set provided by the user compatible with the
|
|
46
|
-
* {@link module:utils/dom/position~Options options}.
|
|
47
|
-
*
|
|
48
|
-
* ```ts
|
|
49
|
-
* const panel = new BalloonPanelView( locale );
|
|
50
|
-
* const childView = new ChildView();
|
|
51
|
-
* const positions = BalloonPanelView.defaultPositions;
|
|
52
|
-
*
|
|
53
|
-
* panel.render();
|
|
54
|
-
*
|
|
55
|
-
* // Add a child view to the panel's content collection.
|
|
56
|
-
* panel.content.add( childView );
|
|
57
|
-
*
|
|
58
|
-
* // Start pinning the panel to an element with the "target" id DOM.
|
|
59
|
-
* // The balloon will remain pinned until unpin() is called.
|
|
60
|
-
* panel.pin( {
|
|
61
|
-
* target: document.querySelector( '#target' ),
|
|
62
|
-
* positions: [
|
|
63
|
-
* positions.northArrowSouth,
|
|
64
|
-
* positions.southArrowNorth
|
|
65
|
-
* ]
|
|
66
|
-
* } );
|
|
67
|
-
* ```
|
|
68
|
-
*/
|
|
69
|
-
export default class BalloonPanelView extends View {
|
|
70
|
-
/**
|
|
71
|
-
* @inheritDoc
|
|
72
|
-
*/
|
|
73
|
-
constructor(locale) {
|
|
74
|
-
super(locale);
|
|
75
|
-
const bind = this.bindTemplate;
|
|
76
|
-
this.set('top', 0);
|
|
77
|
-
this.set('left', 0);
|
|
78
|
-
this.set('position', 'arrow_nw');
|
|
79
|
-
this.set('isVisible', false);
|
|
80
|
-
this.set('withArrow', true);
|
|
81
|
-
this.set('class', undefined);
|
|
82
|
-
this._pinWhenIsVisibleCallback = null;
|
|
83
|
-
this.content = this.createCollection();
|
|
84
|
-
this.setTemplate({
|
|
85
|
-
tag: 'div',
|
|
86
|
-
attributes: {
|
|
87
|
-
class: [
|
|
88
|
-
'ck',
|
|
89
|
-
'ck-balloon-panel',
|
|
90
|
-
bind.to('position', value => `ck-balloon-panel_${value}`),
|
|
91
|
-
bind.if('isVisible', 'ck-balloon-panel_visible'),
|
|
92
|
-
bind.if('withArrow', 'ck-balloon-panel_with-arrow'),
|
|
93
|
-
bind.to('class')
|
|
94
|
-
],
|
|
95
|
-
style: {
|
|
96
|
-
top: bind.to('top', toPx),
|
|
97
|
-
left: bind.to('left', toPx)
|
|
98
|
-
}
|
|
99
|
-
},
|
|
100
|
-
children: this.content
|
|
101
|
-
});
|
|
102
|
-
}
|
|
103
|
-
/**
|
|
104
|
-
* Shows the panel.
|
|
105
|
-
*
|
|
106
|
-
* See {@link #isVisible}.
|
|
107
|
-
*/
|
|
108
|
-
show() {
|
|
109
|
-
this.isVisible = true;
|
|
110
|
-
}
|
|
111
|
-
/**
|
|
112
|
-
* Hides the panel.
|
|
113
|
-
*
|
|
114
|
-
* See {@link #isVisible}.
|
|
115
|
-
*/
|
|
116
|
-
hide() {
|
|
117
|
-
this.isVisible = false;
|
|
118
|
-
}
|
|
119
|
-
/**
|
|
120
|
-
* Attaches the panel to a specified {@link module:utils/dom/position~Options#target} with a
|
|
121
|
-
* smart positioning heuristics that chooses from available positions to make sure the panel
|
|
122
|
-
* is visible to the user i.e. within the limits of the viewport.
|
|
123
|
-
*
|
|
124
|
-
* This method accepts configuration {@link module:utils/dom/position~Options options}
|
|
125
|
-
* to set the `target`, optional `limiter` and `positions` the balloon should choose from.
|
|
126
|
-
*
|
|
127
|
-
* ```ts
|
|
128
|
-
* const panel = new BalloonPanelView( locale );
|
|
129
|
-
* const positions = BalloonPanelView.defaultPositions;
|
|
130
|
-
*
|
|
131
|
-
* panel.render();
|
|
132
|
-
*
|
|
133
|
-
* // Attach the panel to an element with the "target" id DOM.
|
|
134
|
-
* panel.attachTo( {
|
|
135
|
-
* target: document.querySelector( '#target' ),
|
|
136
|
-
* positions: [
|
|
137
|
-
* positions.northArrowSouth,
|
|
138
|
-
* positions.southArrowNorth
|
|
139
|
-
* ]
|
|
140
|
-
* } );
|
|
141
|
-
* ```
|
|
142
|
-
*
|
|
143
|
-
* **Note**: Attaching the panel will also automatically {@link #show} it.
|
|
144
|
-
*
|
|
145
|
-
* **Note**: An attached panel will not follow its target when the window is scrolled or resized.
|
|
146
|
-
* See the {@link #pin} method for a more permanent positioning strategy.
|
|
147
|
-
*
|
|
148
|
-
* @param options Positioning options compatible with {@link module:utils/dom/position~getOptimalPosition}.
|
|
149
|
-
* Default `positions` array is {@link module:ui/panel/balloon/balloonpanelview~BalloonPanelView.defaultPositions}.
|
|
150
|
-
*/
|
|
151
|
-
attachTo(options) {
|
|
152
|
-
this.show();
|
|
153
|
-
const defaultPositions = BalloonPanelView.defaultPositions;
|
|
154
|
-
const positionOptions = Object.assign({}, {
|
|
155
|
-
element: this.element,
|
|
156
|
-
positions: [
|
|
157
|
-
defaultPositions.southArrowNorth,
|
|
158
|
-
defaultPositions.southArrowNorthMiddleWest,
|
|
159
|
-
defaultPositions.southArrowNorthMiddleEast,
|
|
160
|
-
defaultPositions.southArrowNorthWest,
|
|
161
|
-
defaultPositions.southArrowNorthEast,
|
|
162
|
-
defaultPositions.northArrowSouth,
|
|
163
|
-
defaultPositions.northArrowSouthMiddleWest,
|
|
164
|
-
defaultPositions.northArrowSouthMiddleEast,
|
|
165
|
-
defaultPositions.northArrowSouthWest,
|
|
166
|
-
defaultPositions.northArrowSouthEast,
|
|
167
|
-
defaultPositions.viewportStickyNorth
|
|
168
|
-
],
|
|
169
|
-
limiter: defaultLimiterElement,
|
|
170
|
-
fitInViewport: true
|
|
171
|
-
}, options);
|
|
172
|
-
const optimalPosition = BalloonPanelView._getOptimalPosition(positionOptions) || POSITION_OFF_SCREEN;
|
|
173
|
-
// Usually browsers make some problems with super accurate values like 104.345px
|
|
174
|
-
// so it is better to use int values.
|
|
175
|
-
const left = parseInt(optimalPosition.left);
|
|
176
|
-
const top = parseInt(optimalPosition.top);
|
|
177
|
-
const position = optimalPosition.name;
|
|
178
|
-
const config = optimalPosition.config || {};
|
|
179
|
-
const { withArrow = true } = config;
|
|
180
|
-
this.top = top;
|
|
181
|
-
this.left = left;
|
|
182
|
-
this.position = position;
|
|
183
|
-
this.withArrow = withArrow;
|
|
184
|
-
}
|
|
185
|
-
/**
|
|
186
|
-
* Works the same way as the {@link #attachTo} method except that the position of the panel is
|
|
187
|
-
* continuously updated when:
|
|
188
|
-
*
|
|
189
|
-
* * any ancestor of the {@link module:utils/dom/position~Options#target}
|
|
190
|
-
* or {@link module:utils/dom/position~Options#limiter} is scrolled,
|
|
191
|
-
* * the browser window gets resized or scrolled.
|
|
192
|
-
*
|
|
193
|
-
* Thanks to that, the panel always sticks to the {@link module:utils/dom/position~Options#target}
|
|
194
|
-
* and is immune to the changing environment.
|
|
195
|
-
*
|
|
196
|
-
* ```ts
|
|
197
|
-
* const panel = new BalloonPanelView( locale );
|
|
198
|
-
* const positions = BalloonPanelView.defaultPositions;
|
|
199
|
-
*
|
|
200
|
-
* panel.render();
|
|
201
|
-
*
|
|
202
|
-
* // Pin the panel to an element with the "target" id DOM.
|
|
203
|
-
* panel.pin( {
|
|
204
|
-
* target: document.querySelector( '#target' ),
|
|
205
|
-
* positions: [
|
|
206
|
-
* positions.northArrowSouth,
|
|
207
|
-
* positions.southArrowNorth
|
|
208
|
-
* ]
|
|
209
|
-
* } );
|
|
210
|
-
* ```
|
|
211
|
-
*
|
|
212
|
-
* To leave the pinned state, use the {@link #unpin} method.
|
|
213
|
-
*
|
|
214
|
-
* **Note**: Pinning the panel will also automatically {@link #show} it.
|
|
215
|
-
*
|
|
216
|
-
* @param options Positioning options compatible with {@link module:utils/dom/position~getOptimalPosition}.
|
|
217
|
-
* Default `positions` array is {@link module:ui/panel/balloon/balloonpanelview~BalloonPanelView.defaultPositions}.
|
|
218
|
-
*/
|
|
219
|
-
pin(options) {
|
|
220
|
-
this.unpin();
|
|
221
|
-
this._pinWhenIsVisibleCallback = () => {
|
|
222
|
-
if (this.isVisible) {
|
|
223
|
-
this._startPinning(options);
|
|
224
|
-
}
|
|
225
|
-
else {
|
|
226
|
-
this._stopPinning();
|
|
227
|
-
}
|
|
228
|
-
};
|
|
229
|
-
this._startPinning(options);
|
|
230
|
-
// Control the state of the listeners depending on whether the panel is visible
|
|
231
|
-
// or not.
|
|
232
|
-
// TODO: Use on() (https://github.com/ckeditor/ckeditor5-utils/issues/144).
|
|
233
|
-
this.listenTo(this, 'change:isVisible', this._pinWhenIsVisibleCallback);
|
|
234
|
-
}
|
|
235
|
-
/**
|
|
236
|
-
* Stops pinning the panel, as set up by {@link #pin}.
|
|
237
|
-
*/
|
|
238
|
-
unpin() {
|
|
239
|
-
if (this._pinWhenIsVisibleCallback) {
|
|
240
|
-
// Deactivate listeners attached by pin().
|
|
241
|
-
this._stopPinning();
|
|
242
|
-
// Deactivate the panel pin() control logic.
|
|
243
|
-
// TODO: Use off() (https://github.com/ckeditor/ckeditor5-utils/issues/144).
|
|
244
|
-
this.stopListening(this, 'change:isVisible', this._pinWhenIsVisibleCallback);
|
|
245
|
-
this._pinWhenIsVisibleCallback = null;
|
|
246
|
-
this.hide();
|
|
247
|
-
}
|
|
248
|
-
}
|
|
249
|
-
/**
|
|
250
|
-
* Starts managing the pinned state of the panel. See {@link #pin}.
|
|
251
|
-
*
|
|
252
|
-
* @param options Positioning options compatible with {@link module:utils/dom/position~getOptimalPosition}.
|
|
253
|
-
*/
|
|
254
|
-
_startPinning(options) {
|
|
255
|
-
this.attachTo(options);
|
|
256
|
-
const targetElement = getDomElement(options.target);
|
|
257
|
-
const limiterElement = options.limiter ? getDomElement(options.limiter) : defaultLimiterElement;
|
|
258
|
-
// Then we need to listen on scroll event of eny element in the document.
|
|
259
|
-
this.listenTo(global.document, 'scroll', (evt, domEvt) => {
|
|
260
|
-
const scrollTarget = domEvt.target;
|
|
261
|
-
// The position needs to be updated if the positioning target is within the scrolled element.
|
|
262
|
-
const isWithinScrollTarget = targetElement && scrollTarget.contains(targetElement);
|
|
263
|
-
// The position needs to be updated if the positioning limiter is within the scrolled element.
|
|
264
|
-
const isLimiterWithinScrollTarget = limiterElement && scrollTarget.contains(limiterElement);
|
|
265
|
-
// The positioning target and/or limiter can be a Rect, object etc..
|
|
266
|
-
// There's no way to optimize the listener then.
|
|
267
|
-
if (isWithinScrollTarget || isLimiterWithinScrollTarget || !targetElement || !limiterElement) {
|
|
268
|
-
this.attachTo(options);
|
|
269
|
-
}
|
|
270
|
-
}, { useCapture: true });
|
|
271
|
-
// We need to listen on window resize event and update position.
|
|
272
|
-
this.listenTo(global.window, 'resize', () => {
|
|
273
|
-
this.attachTo(options);
|
|
274
|
-
});
|
|
275
|
-
}
|
|
276
|
-
/**
|
|
277
|
-
* Stops managing the pinned state of the panel. See {@link #pin}.
|
|
278
|
-
*/
|
|
279
|
-
_stopPinning() {
|
|
280
|
-
this.stopListening(global.document, 'scroll');
|
|
281
|
-
this.stopListening(global.window, 'resize');
|
|
282
|
-
}
|
|
283
|
-
}
|
|
284
|
-
/**
|
|
285
|
-
* A side offset of the arrow tip from the edge of the balloon. Controlled by CSS.
|
|
286
|
-
*
|
|
287
|
-
* ```
|
|
288
|
-
* ┌───────────────────────┐
|
|
289
|
-
* │ │
|
|
290
|
-
* │ Balloon │
|
|
291
|
-
* │ Content │
|
|
292
|
-
* │ │
|
|
293
|
-
* └──+ +───────────────┘
|
|
294
|
-
* | \ /
|
|
295
|
-
* | \/
|
|
296
|
-
* >┼─────┼< ─────────────────────── side offset
|
|
297
|
-
*
|
|
298
|
-
* ```
|
|
299
|
-
*
|
|
300
|
-
* @default 25
|
|
301
|
-
*/
|
|
302
|
-
BalloonPanelView.arrowSideOffset = 25;
|
|
303
|
-
/**
|
|
304
|
-
* A height offset of the arrow from the edge of the balloon. Controlled by CSS.
|
|
305
|
-
*
|
|
306
|
-
* ```
|
|
307
|
-
* ┌───────────────────────┐
|
|
308
|
-
* │ │
|
|
309
|
-
* │ Balloon │
|
|
310
|
-
* │ Content │ ╱-- arrow height offset
|
|
311
|
-
* │ │ V
|
|
312
|
-
* └──+ +───────────────┘ --- ─┼───────
|
|
313
|
-
* \ / │
|
|
314
|
-
* \/ │
|
|
315
|
-
* ────────────────────────────────┼───────
|
|
316
|
-
* ^
|
|
317
|
-
*
|
|
318
|
-
*
|
|
319
|
-
* >┼────┼< arrow height offset
|
|
320
|
-
* │ │
|
|
321
|
-
* │ ┌────────────────────────┐
|
|
322
|
-
* │ │ │
|
|
323
|
-
* │ ╱ │
|
|
324
|
-
* │ ╱ Balloon │
|
|
325
|
-
* │ ╲ Content │
|
|
326
|
-
* │ ╲ │
|
|
327
|
-
* │ │ │
|
|
328
|
-
* │ └────────────────────────┘
|
|
329
|
-
* ```
|
|
330
|
-
*
|
|
331
|
-
* @default 10
|
|
332
|
-
*/
|
|
333
|
-
BalloonPanelView.arrowHeightOffset = 10;
|
|
334
|
-
/**
|
|
335
|
-
* A vertical offset of the balloon panel from the edge of the viewport if sticky.
|
|
336
|
-
* It helps in accessing toolbar buttons underneath the balloon panel.
|
|
337
|
-
*
|
|
338
|
-
* ```
|
|
339
|
-
* ┌───────────────────────────────────────────────────┐
|
|
340
|
-
* │ Target │
|
|
341
|
-
* │ │
|
|
342
|
-
* │ /── vertical offset │
|
|
343
|
-
* ┌─────────────────────────────V─────────────────────────┐
|
|
344
|
-
* │ Toolbar ┌─────────────┐ │
|
|
345
|
-
* ├────────────────────│ Balloon │────────────────────┤
|
|
346
|
-
* │ │ └─────────────┘ │ │
|
|
347
|
-
* │ │ │ │
|
|
348
|
-
* │ │ │ │
|
|
349
|
-
* │ │ │ │
|
|
350
|
-
* │ └───────────────────────────────────────────────────┘ │
|
|
351
|
-
* │ Viewport │
|
|
352
|
-
* └───────────────────────────────────────────────────────┘
|
|
353
|
-
* ```
|
|
354
|
-
*
|
|
355
|
-
* @default 20
|
|
356
|
-
*/
|
|
357
|
-
BalloonPanelView.stickyVerticalOffset = 20;
|
|
358
|
-
/**
|
|
359
|
-
* Function used to calculate the optimal position for the balloon.
|
|
360
|
-
*/
|
|
361
|
-
BalloonPanelView._getOptimalPosition = getOptimalPosition;
|
|
362
|
-
/**
|
|
363
|
-
* A default set of positioning functions used by the balloon panel view
|
|
364
|
-
* when attaching using the {@link module:ui/panel/balloon/balloonpanelview~BalloonPanelView#attachTo} method.
|
|
365
|
-
*
|
|
366
|
-
* The available positioning functions are as follows:
|
|
367
|
-
*
|
|
368
|
-
* **North west**
|
|
369
|
-
*
|
|
370
|
-
* * `northWestArrowSouthWest`
|
|
371
|
-
*
|
|
372
|
-
* ```
|
|
373
|
-
* +-----------------+
|
|
374
|
-
* | Balloon |
|
|
375
|
-
* +-----------------+
|
|
376
|
-
* V
|
|
377
|
-
* [ Target ]
|
|
378
|
-
* ```
|
|
379
|
-
*
|
|
380
|
-
* * `northWestArrowSouthMiddleWest`
|
|
381
|
-
*
|
|
382
|
-
* ```
|
|
383
|
-
* +-----------------+
|
|
384
|
-
* | Balloon |
|
|
385
|
-
* +-----------------+
|
|
386
|
-
* V
|
|
387
|
-
* [ Target ]
|
|
388
|
-
* ```
|
|
389
|
-
*
|
|
390
|
-
* * `northWestArrowSouth`
|
|
391
|
-
*
|
|
392
|
-
* ```
|
|
393
|
-
* +-----------------+
|
|
394
|
-
* | Balloon |
|
|
395
|
-
* +-----------------+
|
|
396
|
-
* V
|
|
397
|
-
* [ Target ]
|
|
398
|
-
* ```
|
|
399
|
-
*
|
|
400
|
-
* * `northWestArrowSouthMiddleEast`
|
|
401
|
-
*
|
|
402
|
-
* ```
|
|
403
|
-
* +-----------------+
|
|
404
|
-
* | Balloon |
|
|
405
|
-
* +-----------------+
|
|
406
|
-
* V
|
|
407
|
-
* [ Target ]
|
|
408
|
-
* ```
|
|
409
|
-
*
|
|
410
|
-
* * `northWestArrowSouthEast`
|
|
411
|
-
*
|
|
412
|
-
* ```
|
|
413
|
-
* +-----------------+
|
|
414
|
-
* | Balloon |
|
|
415
|
-
* +-----------------+
|
|
416
|
-
* V
|
|
417
|
-
* [ Target ]
|
|
418
|
-
* ```
|
|
419
|
-
*
|
|
420
|
-
* **North**
|
|
421
|
-
*
|
|
422
|
-
* * `northArrowSouthWest`
|
|
423
|
-
*
|
|
424
|
-
* ```
|
|
425
|
-
* +-----------------+
|
|
426
|
-
* | Balloon |
|
|
427
|
-
* +-----------------+
|
|
428
|
-
* V
|
|
429
|
-
* [ Target ]
|
|
430
|
-
* ```
|
|
431
|
-
*
|
|
432
|
-
* * `northArrowSouthMiddleWest`
|
|
433
|
-
*
|
|
434
|
-
* ```
|
|
435
|
-
* +-----------------+
|
|
436
|
-
* | Balloon |
|
|
437
|
-
* +-----------------+
|
|
438
|
-
* V
|
|
439
|
-
* [ Target ]
|
|
440
|
-
* ```
|
|
441
|
-
* * `northArrowSouth`
|
|
442
|
-
*
|
|
443
|
-
* ```
|
|
444
|
-
* +-----------------+
|
|
445
|
-
* | Balloon |
|
|
446
|
-
* +-----------------+
|
|
447
|
-
* V
|
|
448
|
-
* [ Target ]
|
|
449
|
-
* ```
|
|
450
|
-
*
|
|
451
|
-
* * `northArrowSouthMiddleEast`
|
|
452
|
-
*
|
|
453
|
-
* ```
|
|
454
|
-
* +-----------------+
|
|
455
|
-
* | Balloon |
|
|
456
|
-
* +-----------------+
|
|
457
|
-
* V
|
|
458
|
-
* [ Target ]
|
|
459
|
-
* ```
|
|
460
|
-
*
|
|
461
|
-
* * `northArrowSouthEast`
|
|
462
|
-
*
|
|
463
|
-
* ```
|
|
464
|
-
* +-----------------+
|
|
465
|
-
* | Balloon |
|
|
466
|
-
* +-----------------+
|
|
467
|
-
* V
|
|
468
|
-
* [ Target ]
|
|
469
|
-
* ```
|
|
470
|
-
*
|
|
471
|
-
* **North east**
|
|
472
|
-
*
|
|
473
|
-
* * `northEastArrowSouthWest`
|
|
474
|
-
*
|
|
475
|
-
* ```
|
|
476
|
-
* +-----------------+
|
|
477
|
-
* | Balloon |
|
|
478
|
-
* +-----------------+
|
|
479
|
-
* V
|
|
480
|
-
* [ Target ]
|
|
481
|
-
* ```
|
|
482
|
-
*
|
|
483
|
-
* * `northEastArrowSouthMiddleWest`
|
|
484
|
-
*
|
|
485
|
-
* ```
|
|
486
|
-
* +-----------------+
|
|
487
|
-
* | Balloon |
|
|
488
|
-
* +-----------------+
|
|
489
|
-
* V
|
|
490
|
-
* [ Target ]
|
|
491
|
-
* ```
|
|
492
|
-
*
|
|
493
|
-
* * `northEastArrowSouth`
|
|
494
|
-
*
|
|
495
|
-
* ```
|
|
496
|
-
* +-----------------+
|
|
497
|
-
* | Balloon |
|
|
498
|
-
* +-----------------+
|
|
499
|
-
* V
|
|
500
|
-
* [ Target ]
|
|
501
|
-
* ```
|
|
502
|
-
*
|
|
503
|
-
* * `northEastArrowSouthMiddleEast`
|
|
504
|
-
*
|
|
505
|
-
* ```
|
|
506
|
-
* +-----------------+
|
|
507
|
-
* | Balloon |
|
|
508
|
-
* +-----------------+
|
|
509
|
-
* V
|
|
510
|
-
* [ Target ]
|
|
511
|
-
* ```
|
|
512
|
-
*
|
|
513
|
-
* * `northEastArrowSouthEast`
|
|
514
|
-
*
|
|
515
|
-
* ```
|
|
516
|
-
* +-----------------+
|
|
517
|
-
* | Balloon |
|
|
518
|
-
* +-----------------+
|
|
519
|
-
* V
|
|
520
|
-
* [ Target ]
|
|
521
|
-
* ```
|
|
522
|
-
*
|
|
523
|
-
* **South**
|
|
524
|
-
*
|
|
525
|
-
* * `southArrowNorthWest`
|
|
526
|
-
*
|
|
527
|
-
* ```
|
|
528
|
-
* [ Target ]
|
|
529
|
-
* ^
|
|
530
|
-
* +-----------------+
|
|
531
|
-
* | Balloon |
|
|
532
|
-
* +-----------------+
|
|
533
|
-
* ```
|
|
534
|
-
*
|
|
535
|
-
* * `southArrowNorthMiddleWest`
|
|
536
|
-
*
|
|
537
|
-
* ```
|
|
538
|
-
* [ Target ]
|
|
539
|
-
* ^
|
|
540
|
-
* +-----------------+
|
|
541
|
-
* | Balloon |
|
|
542
|
-
* +-----------------+
|
|
543
|
-
* ```
|
|
544
|
-
*
|
|
545
|
-
* * `southArrowNorth`
|
|
546
|
-
*
|
|
547
|
-
* ```
|
|
548
|
-
* [ Target ]
|
|
549
|
-
* ^
|
|
550
|
-
* +-----------------+
|
|
551
|
-
* | Balloon |
|
|
552
|
-
* +-----------------+
|
|
553
|
-
* ```
|
|
554
|
-
*
|
|
555
|
-
* * `southArrowNorthMiddleEast`
|
|
556
|
-
*
|
|
557
|
-
* ```
|
|
558
|
-
* [ Target ]
|
|
559
|
-
* ^
|
|
560
|
-
* +-----------------+
|
|
561
|
-
* | Balloon |
|
|
562
|
-
* +-----------------+
|
|
563
|
-
* ```
|
|
564
|
-
*
|
|
565
|
-
* * `southArrowNorthEast`
|
|
566
|
-
*
|
|
567
|
-
* ```
|
|
568
|
-
* [ Target ]
|
|
569
|
-
* ^
|
|
570
|
-
* +-----------------+
|
|
571
|
-
* | Balloon |
|
|
572
|
-
* +-----------------+
|
|
573
|
-
* ```
|
|
574
|
-
*
|
|
575
|
-
* **South west**
|
|
576
|
-
*
|
|
577
|
-
* * `southWestArrowNorthWest`
|
|
578
|
-
*
|
|
579
|
-
*
|
|
580
|
-
* ```
|
|
581
|
-
* [ Target ]
|
|
582
|
-
* ^
|
|
583
|
-
* +-----------------+
|
|
584
|
-
* | Balloon |
|
|
585
|
-
* +-----------------+
|
|
586
|
-
* ```
|
|
587
|
-
*
|
|
588
|
-
* * `southWestArrowNorthMiddleWest`
|
|
589
|
-
*
|
|
590
|
-
* ```
|
|
591
|
-
* [ Target ]
|
|
592
|
-
* ^
|
|
593
|
-
* +-----------------+
|
|
594
|
-
* | Balloon |
|
|
595
|
-
* +-----------------+
|
|
596
|
-
* ```
|
|
597
|
-
*
|
|
598
|
-
* * `southWestArrowNorth`
|
|
599
|
-
*
|
|
600
|
-
* ```
|
|
601
|
-
* [ Target ]
|
|
602
|
-
* ^
|
|
603
|
-
* +-----------------+
|
|
604
|
-
* | Balloon |
|
|
605
|
-
* +-----------------+
|
|
606
|
-
* ```
|
|
607
|
-
*
|
|
608
|
-
* * `southWestArrowNorthMiddleEast`
|
|
609
|
-
*
|
|
610
|
-
* ```
|
|
611
|
-
* [ Target ]
|
|
612
|
-
* ^
|
|
613
|
-
* +-----------------+
|
|
614
|
-
* | Balloon |
|
|
615
|
-
* +-----------------+
|
|
616
|
-
* ```
|
|
617
|
-
*
|
|
618
|
-
* * `southWestArrowNorthEast`
|
|
619
|
-
*
|
|
620
|
-
* ```
|
|
621
|
-
* [ Target ]
|
|
622
|
-
* ^
|
|
623
|
-
* +-----------------+
|
|
624
|
-
* | Balloon |
|
|
625
|
-
* +-----------------+
|
|
626
|
-
* ```
|
|
627
|
-
*
|
|
628
|
-
* **South east**
|
|
629
|
-
*
|
|
630
|
-
* * `southEastArrowNorthWest`
|
|
631
|
-
*
|
|
632
|
-
* ```
|
|
633
|
-
* [ Target ]
|
|
634
|
-
* ^
|
|
635
|
-
* +-----------------+
|
|
636
|
-
* | Balloon |
|
|
637
|
-
* +-----------------+
|
|
638
|
-
* ```
|
|
639
|
-
*
|
|
640
|
-
* * `southEastArrowNorthMiddleWest`
|
|
641
|
-
*
|
|
642
|
-
* ```
|
|
643
|
-
* [ Target ]
|
|
644
|
-
* ^
|
|
645
|
-
* +-----------------+
|
|
646
|
-
* | Balloon |
|
|
647
|
-
* +-----------------+
|
|
648
|
-
* ```
|
|
649
|
-
*
|
|
650
|
-
* * `southEastArrowNorth`
|
|
651
|
-
*
|
|
652
|
-
* ```
|
|
653
|
-
* [ Target ]
|
|
654
|
-
* ^
|
|
655
|
-
* +-----------------+
|
|
656
|
-
* | Balloon |
|
|
657
|
-
* +-----------------+
|
|
658
|
-
* ```
|
|
659
|
-
*
|
|
660
|
-
* * `southEastArrowNorthMiddleEast`
|
|
661
|
-
*
|
|
662
|
-
* ```
|
|
663
|
-
* [ Target ]
|
|
664
|
-
* ^
|
|
665
|
-
* +-----------------+
|
|
666
|
-
* | Balloon |
|
|
667
|
-
* +-----------------+
|
|
668
|
-
* ```
|
|
669
|
-
*
|
|
670
|
-
* * `southEastArrowNorthEast`
|
|
671
|
-
*
|
|
672
|
-
* ```
|
|
673
|
-
* [ Target ]
|
|
674
|
-
* ^
|
|
675
|
-
* +-----------------+
|
|
676
|
-
* | Balloon |
|
|
677
|
-
* +-----------------+
|
|
678
|
-
* ```
|
|
679
|
-
*
|
|
680
|
-
* **West**
|
|
681
|
-
*
|
|
682
|
-
* * `westArrowEast`
|
|
683
|
-
*
|
|
684
|
-
* ```
|
|
685
|
-
* +-----------------+
|
|
686
|
-
* | Balloon |>[ Target ]
|
|
687
|
-
* +-----------------+
|
|
688
|
-
* ```
|
|
689
|
-
*
|
|
690
|
-
* **East**
|
|
691
|
-
*
|
|
692
|
-
* * `eastArrowWest`
|
|
693
|
-
*
|
|
694
|
-
* ```
|
|
695
|
-
* +-----------------+
|
|
696
|
-
* [ Target ]<| Balloon |
|
|
697
|
-
* +-----------------+
|
|
698
|
-
* ```
|
|
699
|
-
*
|
|
700
|
-
* **Sticky**
|
|
701
|
-
*
|
|
702
|
-
* * `viewportStickyNorth`
|
|
703
|
-
*
|
|
704
|
-
* ```
|
|
705
|
-
* +---------------------------+
|
|
706
|
-
* | [ Target ] |
|
|
707
|
-
* | |
|
|
708
|
-
* +-----------------------------------+
|
|
709
|
-
* | | +-----------------+ | |
|
|
710
|
-
* | | | Balloon | | |
|
|
711
|
-
* | | +-----------------+ | |
|
|
712
|
-
* | | | |
|
|
713
|
-
* | | | |
|
|
714
|
-
* | | | |
|
|
715
|
-
* | | | |
|
|
716
|
-
* | +---------------------------+ |
|
|
717
|
-
* | Viewport |
|
|
718
|
-
* +-----------------------------------+
|
|
719
|
-
* ```
|
|
720
|
-
*
|
|
721
|
-
* See {@link module:ui/panel/balloon/balloonpanelview~BalloonPanelView#attachTo}.
|
|
722
|
-
*
|
|
723
|
-
* Positioning functions must be compatible with {@link module:utils/dom/position~Position}.
|
|
724
|
-
*
|
|
725
|
-
* Default positioning functions with customized offsets can be generated using
|
|
726
|
-
* {@link module:ui/panel/balloon/balloonpanelview~generatePositions}.
|
|
727
|
-
*
|
|
728
|
-
* The name that the position function returns will be reflected in the balloon panel's class that
|
|
729
|
-
* controls the placement of the "arrow". See {@link #position} to learn more.
|
|
730
|
-
*/
|
|
731
|
-
BalloonPanelView.defaultPositions = generatePositions();
|
|
732
|
-
/**
|
|
733
|
-
* Returns the DOM element for given object or null, if there is none,
|
|
734
|
-
* e.g. when the passed object is a Rect instance or so.
|
|
735
|
-
*/
|
|
736
|
-
function getDomElement(object) {
|
|
737
|
-
if (isElement(object)) {
|
|
738
|
-
return object;
|
|
739
|
-
}
|
|
740
|
-
if (isRange(object)) {
|
|
741
|
-
return object.commonAncestorContainer;
|
|
742
|
-
}
|
|
743
|
-
if (typeof object == 'function') {
|
|
744
|
-
return getDomElement(object());
|
|
745
|
-
}
|
|
746
|
-
return null;
|
|
747
|
-
}
|
|
748
|
-
/**
|
|
749
|
-
* Returns available {@link module:ui/panel/balloon/balloonpanelview~BalloonPanelView}
|
|
750
|
-
* {@link module:utils/dom/position~PositioningFunction positioning functions} adjusted by the specific offsets.
|
|
751
|
-
*
|
|
752
|
-
* @internal
|
|
753
|
-
* @param options Options to generate positions. If not specified, this helper will simply return
|
|
754
|
-
* {@link module:ui/panel/balloon/balloonpanelview~BalloonPanelView.defaultPositions}.
|
|
755
|
-
* @param options.sideOffset A custom side offset (in pixels) of each position. If
|
|
756
|
-
* not specified, {@link module:ui/panel/balloon/balloonpanelview~BalloonPanelView.arrowSideOffset the default value}
|
|
757
|
-
* will be used.
|
|
758
|
-
* @param options.heightOffset A custom height offset (in pixels) of each position. If
|
|
759
|
-
* not specified, {@link module:ui/panel/balloon/balloonpanelview~BalloonPanelView.arrowHeightOffset the default value}
|
|
760
|
-
* will be used.
|
|
761
|
-
* @param options.stickyVerticalOffset A custom offset (in pixels) of the `viewportStickyNorth` positioning function.
|
|
762
|
-
* If not specified, {@link module:ui/panel/balloon/balloonpanelview~BalloonPanelView.stickyVerticalOffset the default value}
|
|
763
|
-
* will be used.
|
|
764
|
-
* @param options.config Additional configuration of the balloon balloon panel view.
|
|
765
|
-
* Currently only {@link module:ui/panel/balloon/balloonpanelview~BalloonPanelView#withArrow} is supported. Learn more
|
|
766
|
-
* about {@link module:utils/dom/position~PositioningFunction positioning functions}.
|
|
767
|
-
*/
|
|
768
|
-
export function generatePositions(options = {}) {
|
|
769
|
-
const { sideOffset = BalloonPanelView.arrowSideOffset, heightOffset = BalloonPanelView.arrowHeightOffset, stickyVerticalOffset = BalloonPanelView.stickyVerticalOffset, config } = options;
|
|
770
|
-
return {
|
|
771
|
-
// ------- North west
|
|
772
|
-
northWestArrowSouthWest: (targetRect, balloonRect) => ({
|
|
773
|
-
top: getNorthTop(targetRect, balloonRect),
|
|
774
|
-
left: targetRect.left - sideOffset,
|
|
775
|
-
name: 'arrow_sw',
|
|
776
|
-
...(config && { config })
|
|
777
|
-
}),
|
|
778
|
-
northWestArrowSouthMiddleWest: (targetRect, balloonRect) => ({
|
|
779
|
-
top: getNorthTop(targetRect, balloonRect),
|
|
780
|
-
left: targetRect.left - (balloonRect.width * .25) - sideOffset,
|
|
781
|
-
name: 'arrow_smw',
|
|
782
|
-
...(config && { config })
|
|
783
|
-
}),
|
|
784
|
-
northWestArrowSouth: (targetRect, balloonRect) => ({
|
|
785
|
-
top: getNorthTop(targetRect, balloonRect),
|
|
786
|
-
left: targetRect.left - balloonRect.width / 2,
|
|
787
|
-
name: 'arrow_s',
|
|
788
|
-
...(config && { config })
|
|
789
|
-
}),
|
|
790
|
-
northWestArrowSouthMiddleEast: (targetRect, balloonRect) => ({
|
|
791
|
-
top: getNorthTop(targetRect, balloonRect),
|
|
792
|
-
left: targetRect.left - (balloonRect.width * .75) + sideOffset,
|
|
793
|
-
name: 'arrow_sme',
|
|
794
|
-
...(config && { config })
|
|
795
|
-
}),
|
|
796
|
-
northWestArrowSouthEast: (targetRect, balloonRect) => ({
|
|
797
|
-
top: getNorthTop(targetRect, balloonRect),
|
|
798
|
-
left: targetRect.left - balloonRect.width + sideOffset,
|
|
799
|
-
name: 'arrow_se',
|
|
800
|
-
...(config && { config })
|
|
801
|
-
}),
|
|
802
|
-
// ------- North
|
|
803
|
-
northArrowSouthWest: (targetRect, balloonRect) => ({
|
|
804
|
-
top: getNorthTop(targetRect, balloonRect),
|
|
805
|
-
left: targetRect.left + targetRect.width / 2 - sideOffset,
|
|
806
|
-
name: 'arrow_sw',
|
|
807
|
-
...(config && { config })
|
|
808
|
-
}),
|
|
809
|
-
northArrowSouthMiddleWest: (targetRect, balloonRect) => ({
|
|
810
|
-
top: getNorthTop(targetRect, balloonRect),
|
|
811
|
-
left: targetRect.left + targetRect.width / 2 - (balloonRect.width * .25) - sideOffset,
|
|
812
|
-
name: 'arrow_smw',
|
|
813
|
-
...(config && { config })
|
|
814
|
-
}),
|
|
815
|
-
northArrowSouth: (targetRect, balloonRect) => ({
|
|
816
|
-
top: getNorthTop(targetRect, balloonRect),
|
|
817
|
-
left: targetRect.left + targetRect.width / 2 - balloonRect.width / 2,
|
|
818
|
-
name: 'arrow_s',
|
|
819
|
-
...(config && { config })
|
|
820
|
-
}),
|
|
821
|
-
northArrowSouthMiddleEast: (targetRect, balloonRect) => ({
|
|
822
|
-
top: getNorthTop(targetRect, balloonRect),
|
|
823
|
-
left: targetRect.left + targetRect.width / 2 - (balloonRect.width * .75) + sideOffset,
|
|
824
|
-
name: 'arrow_sme',
|
|
825
|
-
...(config && { config })
|
|
826
|
-
}),
|
|
827
|
-
northArrowSouthEast: (targetRect, balloonRect) => ({
|
|
828
|
-
top: getNorthTop(targetRect, balloonRect),
|
|
829
|
-
left: targetRect.left + targetRect.width / 2 - balloonRect.width + sideOffset,
|
|
830
|
-
name: 'arrow_se',
|
|
831
|
-
...(config && { config })
|
|
832
|
-
}),
|
|
833
|
-
// ------- North east
|
|
834
|
-
northEastArrowSouthWest: (targetRect, balloonRect) => ({
|
|
835
|
-
top: getNorthTop(targetRect, balloonRect),
|
|
836
|
-
left: targetRect.right - sideOffset,
|
|
837
|
-
name: 'arrow_sw',
|
|
838
|
-
...(config && { config })
|
|
839
|
-
}),
|
|
840
|
-
northEastArrowSouthMiddleWest: (targetRect, balloonRect) => ({
|
|
841
|
-
top: getNorthTop(targetRect, balloonRect),
|
|
842
|
-
left: targetRect.right - (balloonRect.width * .25) - sideOffset,
|
|
843
|
-
name: 'arrow_smw',
|
|
844
|
-
...(config && { config })
|
|
845
|
-
}),
|
|
846
|
-
northEastArrowSouth: (targetRect, balloonRect) => ({
|
|
847
|
-
top: getNorthTop(targetRect, balloonRect),
|
|
848
|
-
left: targetRect.right - balloonRect.width / 2,
|
|
849
|
-
name: 'arrow_s',
|
|
850
|
-
...(config && { config })
|
|
851
|
-
}),
|
|
852
|
-
northEastArrowSouthMiddleEast: (targetRect, balloonRect) => ({
|
|
853
|
-
top: getNorthTop(targetRect, balloonRect),
|
|
854
|
-
left: targetRect.right - (balloonRect.width * .75) + sideOffset,
|
|
855
|
-
name: 'arrow_sme',
|
|
856
|
-
...(config && { config })
|
|
857
|
-
}),
|
|
858
|
-
northEastArrowSouthEast: (targetRect, balloonRect) => ({
|
|
859
|
-
top: getNorthTop(targetRect, balloonRect),
|
|
860
|
-
left: targetRect.right - balloonRect.width + sideOffset,
|
|
861
|
-
name: 'arrow_se',
|
|
862
|
-
...(config && { config })
|
|
863
|
-
}),
|
|
864
|
-
// ------- South west
|
|
865
|
-
southWestArrowNorthWest: targetRect => ({
|
|
866
|
-
top: getSouthTop(targetRect),
|
|
867
|
-
left: targetRect.left - sideOffset,
|
|
868
|
-
name: 'arrow_nw',
|
|
869
|
-
...(config && { config })
|
|
870
|
-
}),
|
|
871
|
-
southWestArrowNorthMiddleWest: (targetRect, balloonRect) => ({
|
|
872
|
-
top: getSouthTop(targetRect),
|
|
873
|
-
left: targetRect.left - (balloonRect.width * .25) - sideOffset,
|
|
874
|
-
name: 'arrow_nmw',
|
|
875
|
-
...(config && { config })
|
|
876
|
-
}),
|
|
877
|
-
southWestArrowNorth: (targetRect, balloonRect) => ({
|
|
878
|
-
top: getSouthTop(targetRect),
|
|
879
|
-
left: targetRect.left - balloonRect.width / 2,
|
|
880
|
-
name: 'arrow_n',
|
|
881
|
-
...(config && { config })
|
|
882
|
-
}),
|
|
883
|
-
southWestArrowNorthMiddleEast: (targetRect, balloonRect) => ({
|
|
884
|
-
top: getSouthTop(targetRect),
|
|
885
|
-
left: targetRect.left - (balloonRect.width * .75) + sideOffset,
|
|
886
|
-
name: 'arrow_nme',
|
|
887
|
-
...(config && { config })
|
|
888
|
-
}),
|
|
889
|
-
southWestArrowNorthEast: (targetRect, balloonRect) => ({
|
|
890
|
-
top: getSouthTop(targetRect),
|
|
891
|
-
left: targetRect.left - balloonRect.width + sideOffset,
|
|
892
|
-
name: 'arrow_ne',
|
|
893
|
-
...(config && { config })
|
|
894
|
-
}),
|
|
895
|
-
// ------- South
|
|
896
|
-
southArrowNorthWest: targetRect => ({
|
|
897
|
-
top: getSouthTop(targetRect),
|
|
898
|
-
left: targetRect.left + targetRect.width / 2 - sideOffset,
|
|
899
|
-
name: 'arrow_nw',
|
|
900
|
-
...(config && { config })
|
|
901
|
-
}),
|
|
902
|
-
southArrowNorthMiddleWest: (targetRect, balloonRect) => ({
|
|
903
|
-
top: getSouthTop(targetRect),
|
|
904
|
-
left: targetRect.left + targetRect.width / 2 - (balloonRect.width * 0.25) - sideOffset,
|
|
905
|
-
name: 'arrow_nmw',
|
|
906
|
-
...(config && { config })
|
|
907
|
-
}),
|
|
908
|
-
southArrowNorth: (targetRect, balloonRect) => ({
|
|
909
|
-
top: getSouthTop(targetRect),
|
|
910
|
-
left: targetRect.left + targetRect.width / 2 - balloonRect.width / 2,
|
|
911
|
-
name: 'arrow_n',
|
|
912
|
-
...(config && { config })
|
|
913
|
-
}),
|
|
914
|
-
southArrowNorthMiddleEast: (targetRect, balloonRect) => ({
|
|
915
|
-
top: getSouthTop(targetRect),
|
|
916
|
-
left: targetRect.left + targetRect.width / 2 - (balloonRect.width * 0.75) + sideOffset,
|
|
917
|
-
name: 'arrow_nme',
|
|
918
|
-
...(config && { config })
|
|
919
|
-
}),
|
|
920
|
-
southArrowNorthEast: (targetRect, balloonRect) => ({
|
|
921
|
-
top: getSouthTop(targetRect),
|
|
922
|
-
left: targetRect.left + targetRect.width / 2 - balloonRect.width + sideOffset,
|
|
923
|
-
name: 'arrow_ne',
|
|
924
|
-
...(config && { config })
|
|
925
|
-
}),
|
|
926
|
-
// ------- South east
|
|
927
|
-
southEastArrowNorthWest: targetRect => ({
|
|
928
|
-
top: getSouthTop(targetRect),
|
|
929
|
-
left: targetRect.right - sideOffset,
|
|
930
|
-
name: 'arrow_nw',
|
|
931
|
-
...(config && { config })
|
|
932
|
-
}),
|
|
933
|
-
southEastArrowNorthMiddleWest: (targetRect, balloonRect) => ({
|
|
934
|
-
top: getSouthTop(targetRect),
|
|
935
|
-
left: targetRect.right - (balloonRect.width * .25) - sideOffset,
|
|
936
|
-
name: 'arrow_nmw',
|
|
937
|
-
...(config && { config })
|
|
938
|
-
}),
|
|
939
|
-
southEastArrowNorth: (targetRect, balloonRect) => ({
|
|
940
|
-
top: getSouthTop(targetRect),
|
|
941
|
-
left: targetRect.right - balloonRect.width / 2,
|
|
942
|
-
name: 'arrow_n',
|
|
943
|
-
...(config && { config })
|
|
944
|
-
}),
|
|
945
|
-
southEastArrowNorthMiddleEast: (targetRect, balloonRect) => ({
|
|
946
|
-
top: getSouthTop(targetRect),
|
|
947
|
-
left: targetRect.right - (balloonRect.width * .75) + sideOffset,
|
|
948
|
-
name: 'arrow_nme',
|
|
949
|
-
...(config && { config })
|
|
950
|
-
}),
|
|
951
|
-
southEastArrowNorthEast: (targetRect, balloonRect) => ({
|
|
952
|
-
top: getSouthTop(targetRect),
|
|
953
|
-
left: targetRect.right - balloonRect.width + sideOffset,
|
|
954
|
-
name: 'arrow_ne',
|
|
955
|
-
...(config && { config })
|
|
956
|
-
}),
|
|
957
|
-
// ------- West
|
|
958
|
-
westArrowEast: (targetRect, balloonRect) => ({
|
|
959
|
-
top: targetRect.top + targetRect.height / 2 - balloonRect.height / 2,
|
|
960
|
-
left: targetRect.left - balloonRect.width - heightOffset,
|
|
961
|
-
name: 'arrow_e',
|
|
962
|
-
...(config && { config })
|
|
963
|
-
}),
|
|
964
|
-
// ------- East
|
|
965
|
-
eastArrowWest: (targetRect, balloonRect) => ({
|
|
966
|
-
top: targetRect.top + targetRect.height / 2 - balloonRect.height / 2,
|
|
967
|
-
left: targetRect.right + heightOffset,
|
|
968
|
-
name: 'arrow_w',
|
|
969
|
-
...(config && { config })
|
|
970
|
-
}),
|
|
971
|
-
// ------- Sticky
|
|
972
|
-
viewportStickyNorth: (targetRect, balloonRect, viewportRect, limiterRect) => {
|
|
973
|
-
const boundaryRect = limiterRect || viewportRect;
|
|
974
|
-
if (!targetRect.getIntersection(boundaryRect)) {
|
|
975
|
-
return null;
|
|
976
|
-
}
|
|
977
|
-
// Engage when the target top and bottom edges are close or off the boundary.
|
|
978
|
-
// By close, it means there's not enough space for the balloon arrow (offset).
|
|
979
|
-
if (boundaryRect.height - targetRect.height > stickyVerticalOffset) {
|
|
980
|
-
return null;
|
|
981
|
-
}
|
|
982
|
-
return {
|
|
983
|
-
top: boundaryRect.top + stickyVerticalOffset,
|
|
984
|
-
left: targetRect.left + targetRect.width / 2 - balloonRect.width / 2,
|
|
985
|
-
name: 'arrowless',
|
|
986
|
-
config: {
|
|
987
|
-
withArrow: false,
|
|
988
|
-
...config
|
|
989
|
-
}
|
|
990
|
-
};
|
|
991
|
-
}
|
|
992
|
-
};
|
|
993
|
-
/**
|
|
994
|
-
* Returns the top coordinate for positions starting with `north*`.
|
|
995
|
-
*
|
|
996
|
-
* @param targetRect A rect of the target.
|
|
997
|
-
* @param balloonRect A rect of the balloon.
|
|
998
|
-
*/
|
|
999
|
-
function getNorthTop(targetRect, balloonRect) {
|
|
1000
|
-
return targetRect.top - balloonRect.height - heightOffset;
|
|
1001
|
-
}
|
|
1002
|
-
/**
|
|
1003
|
-
* Returns the top coordinate for positions starting with `south*`.
|
|
1004
|
-
*
|
|
1005
|
-
* @param targetRect A rect of the target.
|
|
1006
|
-
*/
|
|
1007
|
-
function getSouthTop(targetRect) {
|
|
1008
|
-
return targetRect.bottom + heightOffset;
|
|
1009
|
-
}
|
|
1010
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* @license Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved.
|
|
3
|
+
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* @module ui/panel/balloon/balloonpanelview
|
|
7
|
+
*/
|
|
8
|
+
import View from '../../view';
|
|
9
|
+
import { getOptimalPosition, global, isRange, toUnit } from '@ckeditor/ckeditor5-utils';
|
|
10
|
+
import { isElement } from 'lodash-es';
|
|
11
|
+
import '../../../theme/components/panel/balloonpanel.css';
|
|
12
|
+
const toPx = toUnit('px');
|
|
13
|
+
const defaultLimiterElement = global.document.body;
|
|
14
|
+
// A static balloon panel positioning function that moves the balloon far off the viewport.
|
|
15
|
+
// It is used as a fallback when there is no way to position the balloon using provided
|
|
16
|
+
// positioning functions (see: `getOptimalPosition()`), for instance, when the target the
|
|
17
|
+
// balloon should be attached to gets obscured by scrollable containers or the viewport.
|
|
18
|
+
//
|
|
19
|
+
// It prevents the balloon from being attached to the void and possible degradation of the UX.
|
|
20
|
+
// At the same time, it keeps the balloon physically visible in the DOM so the focus remains
|
|
21
|
+
// uninterrupted.
|
|
22
|
+
const POSITION_OFF_SCREEN = {
|
|
23
|
+
top: -99999,
|
|
24
|
+
left: -99999,
|
|
25
|
+
name: 'arrowless',
|
|
26
|
+
config: {
|
|
27
|
+
withArrow: false
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
/**
|
|
31
|
+
* The balloon panel view class.
|
|
32
|
+
*
|
|
33
|
+
* A floating container which can
|
|
34
|
+
* {@link module:ui/panel/balloon/balloonpanelview~BalloonPanelView#pin pin} to any
|
|
35
|
+
* {@link module:utils/dom/position~Options#target target} in the DOM and remain in that position
|
|
36
|
+
* e.g. when the web page is scrolled.
|
|
37
|
+
*
|
|
38
|
+
* The balloon panel can be used to display contextual, non-blocking UI like forms, toolbars and
|
|
39
|
+
* the like in its {@link module:ui/panel/balloon/balloonpanelview~BalloonPanelView#content} view
|
|
40
|
+
* collection.
|
|
41
|
+
*
|
|
42
|
+
* There is a number of {@link module:ui/panel/balloon/balloonpanelview~BalloonPanelView.defaultPositions}
|
|
43
|
+
* that the balloon can use, automatically switching from one to another when the viewport space becomes
|
|
44
|
+
* scarce to keep the balloon visible to the user as long as it is possible. The balloon will also
|
|
45
|
+
* accept any custom position set provided by the user compatible with the
|
|
46
|
+
* {@link module:utils/dom/position~Options options}.
|
|
47
|
+
*
|
|
48
|
+
* ```ts
|
|
49
|
+
* const panel = new BalloonPanelView( locale );
|
|
50
|
+
* const childView = new ChildView();
|
|
51
|
+
* const positions = BalloonPanelView.defaultPositions;
|
|
52
|
+
*
|
|
53
|
+
* panel.render();
|
|
54
|
+
*
|
|
55
|
+
* // Add a child view to the panel's content collection.
|
|
56
|
+
* panel.content.add( childView );
|
|
57
|
+
*
|
|
58
|
+
* // Start pinning the panel to an element with the "target" id DOM.
|
|
59
|
+
* // The balloon will remain pinned until unpin() is called.
|
|
60
|
+
* panel.pin( {
|
|
61
|
+
* target: document.querySelector( '#target' ),
|
|
62
|
+
* positions: [
|
|
63
|
+
* positions.northArrowSouth,
|
|
64
|
+
* positions.southArrowNorth
|
|
65
|
+
* ]
|
|
66
|
+
* } );
|
|
67
|
+
* ```
|
|
68
|
+
*/
|
|
69
|
+
export default class BalloonPanelView extends View {
|
|
70
|
+
/**
|
|
71
|
+
* @inheritDoc
|
|
72
|
+
*/
|
|
73
|
+
constructor(locale) {
|
|
74
|
+
super(locale);
|
|
75
|
+
const bind = this.bindTemplate;
|
|
76
|
+
this.set('top', 0);
|
|
77
|
+
this.set('left', 0);
|
|
78
|
+
this.set('position', 'arrow_nw');
|
|
79
|
+
this.set('isVisible', false);
|
|
80
|
+
this.set('withArrow', true);
|
|
81
|
+
this.set('class', undefined);
|
|
82
|
+
this._pinWhenIsVisibleCallback = null;
|
|
83
|
+
this.content = this.createCollection();
|
|
84
|
+
this.setTemplate({
|
|
85
|
+
tag: 'div',
|
|
86
|
+
attributes: {
|
|
87
|
+
class: [
|
|
88
|
+
'ck',
|
|
89
|
+
'ck-balloon-panel',
|
|
90
|
+
bind.to('position', value => `ck-balloon-panel_${value}`),
|
|
91
|
+
bind.if('isVisible', 'ck-balloon-panel_visible'),
|
|
92
|
+
bind.if('withArrow', 'ck-balloon-panel_with-arrow'),
|
|
93
|
+
bind.to('class')
|
|
94
|
+
],
|
|
95
|
+
style: {
|
|
96
|
+
top: bind.to('top', toPx),
|
|
97
|
+
left: bind.to('left', toPx)
|
|
98
|
+
}
|
|
99
|
+
},
|
|
100
|
+
children: this.content
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Shows the panel.
|
|
105
|
+
*
|
|
106
|
+
* See {@link #isVisible}.
|
|
107
|
+
*/
|
|
108
|
+
show() {
|
|
109
|
+
this.isVisible = true;
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Hides the panel.
|
|
113
|
+
*
|
|
114
|
+
* See {@link #isVisible}.
|
|
115
|
+
*/
|
|
116
|
+
hide() {
|
|
117
|
+
this.isVisible = false;
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Attaches the panel to a specified {@link module:utils/dom/position~Options#target} with a
|
|
121
|
+
* smart positioning heuristics that chooses from available positions to make sure the panel
|
|
122
|
+
* is visible to the user i.e. within the limits of the viewport.
|
|
123
|
+
*
|
|
124
|
+
* This method accepts configuration {@link module:utils/dom/position~Options options}
|
|
125
|
+
* to set the `target`, optional `limiter` and `positions` the balloon should choose from.
|
|
126
|
+
*
|
|
127
|
+
* ```ts
|
|
128
|
+
* const panel = new BalloonPanelView( locale );
|
|
129
|
+
* const positions = BalloonPanelView.defaultPositions;
|
|
130
|
+
*
|
|
131
|
+
* panel.render();
|
|
132
|
+
*
|
|
133
|
+
* // Attach the panel to an element with the "target" id DOM.
|
|
134
|
+
* panel.attachTo( {
|
|
135
|
+
* target: document.querySelector( '#target' ),
|
|
136
|
+
* positions: [
|
|
137
|
+
* positions.northArrowSouth,
|
|
138
|
+
* positions.southArrowNorth
|
|
139
|
+
* ]
|
|
140
|
+
* } );
|
|
141
|
+
* ```
|
|
142
|
+
*
|
|
143
|
+
* **Note**: Attaching the panel will also automatically {@link #show} it.
|
|
144
|
+
*
|
|
145
|
+
* **Note**: An attached panel will not follow its target when the window is scrolled or resized.
|
|
146
|
+
* See the {@link #pin} method for a more permanent positioning strategy.
|
|
147
|
+
*
|
|
148
|
+
* @param options Positioning options compatible with {@link module:utils/dom/position~getOptimalPosition}.
|
|
149
|
+
* Default `positions` array is {@link module:ui/panel/balloon/balloonpanelview~BalloonPanelView.defaultPositions}.
|
|
150
|
+
*/
|
|
151
|
+
attachTo(options) {
|
|
152
|
+
this.show();
|
|
153
|
+
const defaultPositions = BalloonPanelView.defaultPositions;
|
|
154
|
+
const positionOptions = Object.assign({}, {
|
|
155
|
+
element: this.element,
|
|
156
|
+
positions: [
|
|
157
|
+
defaultPositions.southArrowNorth,
|
|
158
|
+
defaultPositions.southArrowNorthMiddleWest,
|
|
159
|
+
defaultPositions.southArrowNorthMiddleEast,
|
|
160
|
+
defaultPositions.southArrowNorthWest,
|
|
161
|
+
defaultPositions.southArrowNorthEast,
|
|
162
|
+
defaultPositions.northArrowSouth,
|
|
163
|
+
defaultPositions.northArrowSouthMiddleWest,
|
|
164
|
+
defaultPositions.northArrowSouthMiddleEast,
|
|
165
|
+
defaultPositions.northArrowSouthWest,
|
|
166
|
+
defaultPositions.northArrowSouthEast,
|
|
167
|
+
defaultPositions.viewportStickyNorth
|
|
168
|
+
],
|
|
169
|
+
limiter: defaultLimiterElement,
|
|
170
|
+
fitInViewport: true
|
|
171
|
+
}, options);
|
|
172
|
+
const optimalPosition = BalloonPanelView._getOptimalPosition(positionOptions) || POSITION_OFF_SCREEN;
|
|
173
|
+
// Usually browsers make some problems with super accurate values like 104.345px
|
|
174
|
+
// so it is better to use int values.
|
|
175
|
+
const left = parseInt(optimalPosition.left);
|
|
176
|
+
const top = parseInt(optimalPosition.top);
|
|
177
|
+
const position = optimalPosition.name;
|
|
178
|
+
const config = optimalPosition.config || {};
|
|
179
|
+
const { withArrow = true } = config;
|
|
180
|
+
this.top = top;
|
|
181
|
+
this.left = left;
|
|
182
|
+
this.position = position;
|
|
183
|
+
this.withArrow = withArrow;
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* Works the same way as the {@link #attachTo} method except that the position of the panel is
|
|
187
|
+
* continuously updated when:
|
|
188
|
+
*
|
|
189
|
+
* * any ancestor of the {@link module:utils/dom/position~Options#target}
|
|
190
|
+
* or {@link module:utils/dom/position~Options#limiter} is scrolled,
|
|
191
|
+
* * the browser window gets resized or scrolled.
|
|
192
|
+
*
|
|
193
|
+
* Thanks to that, the panel always sticks to the {@link module:utils/dom/position~Options#target}
|
|
194
|
+
* and is immune to the changing environment.
|
|
195
|
+
*
|
|
196
|
+
* ```ts
|
|
197
|
+
* const panel = new BalloonPanelView( locale );
|
|
198
|
+
* const positions = BalloonPanelView.defaultPositions;
|
|
199
|
+
*
|
|
200
|
+
* panel.render();
|
|
201
|
+
*
|
|
202
|
+
* // Pin the panel to an element with the "target" id DOM.
|
|
203
|
+
* panel.pin( {
|
|
204
|
+
* target: document.querySelector( '#target' ),
|
|
205
|
+
* positions: [
|
|
206
|
+
* positions.northArrowSouth,
|
|
207
|
+
* positions.southArrowNorth
|
|
208
|
+
* ]
|
|
209
|
+
* } );
|
|
210
|
+
* ```
|
|
211
|
+
*
|
|
212
|
+
* To leave the pinned state, use the {@link #unpin} method.
|
|
213
|
+
*
|
|
214
|
+
* **Note**: Pinning the panel will also automatically {@link #show} it.
|
|
215
|
+
*
|
|
216
|
+
* @param options Positioning options compatible with {@link module:utils/dom/position~getOptimalPosition}.
|
|
217
|
+
* Default `positions` array is {@link module:ui/panel/balloon/balloonpanelview~BalloonPanelView.defaultPositions}.
|
|
218
|
+
*/
|
|
219
|
+
pin(options) {
|
|
220
|
+
this.unpin();
|
|
221
|
+
this._pinWhenIsVisibleCallback = () => {
|
|
222
|
+
if (this.isVisible) {
|
|
223
|
+
this._startPinning(options);
|
|
224
|
+
}
|
|
225
|
+
else {
|
|
226
|
+
this._stopPinning();
|
|
227
|
+
}
|
|
228
|
+
};
|
|
229
|
+
this._startPinning(options);
|
|
230
|
+
// Control the state of the listeners depending on whether the panel is visible
|
|
231
|
+
// or not.
|
|
232
|
+
// TODO: Use on() (https://github.com/ckeditor/ckeditor5-utils/issues/144).
|
|
233
|
+
this.listenTo(this, 'change:isVisible', this._pinWhenIsVisibleCallback);
|
|
234
|
+
}
|
|
235
|
+
/**
|
|
236
|
+
* Stops pinning the panel, as set up by {@link #pin}.
|
|
237
|
+
*/
|
|
238
|
+
unpin() {
|
|
239
|
+
if (this._pinWhenIsVisibleCallback) {
|
|
240
|
+
// Deactivate listeners attached by pin().
|
|
241
|
+
this._stopPinning();
|
|
242
|
+
// Deactivate the panel pin() control logic.
|
|
243
|
+
// TODO: Use off() (https://github.com/ckeditor/ckeditor5-utils/issues/144).
|
|
244
|
+
this.stopListening(this, 'change:isVisible', this._pinWhenIsVisibleCallback);
|
|
245
|
+
this._pinWhenIsVisibleCallback = null;
|
|
246
|
+
this.hide();
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
/**
|
|
250
|
+
* Starts managing the pinned state of the panel. See {@link #pin}.
|
|
251
|
+
*
|
|
252
|
+
* @param options Positioning options compatible with {@link module:utils/dom/position~getOptimalPosition}.
|
|
253
|
+
*/
|
|
254
|
+
_startPinning(options) {
|
|
255
|
+
this.attachTo(options);
|
|
256
|
+
const targetElement = getDomElement(options.target);
|
|
257
|
+
const limiterElement = options.limiter ? getDomElement(options.limiter) : defaultLimiterElement;
|
|
258
|
+
// Then we need to listen on scroll event of eny element in the document.
|
|
259
|
+
this.listenTo(global.document, 'scroll', (evt, domEvt) => {
|
|
260
|
+
const scrollTarget = domEvt.target;
|
|
261
|
+
// The position needs to be updated if the positioning target is within the scrolled element.
|
|
262
|
+
const isWithinScrollTarget = targetElement && scrollTarget.contains(targetElement);
|
|
263
|
+
// The position needs to be updated if the positioning limiter is within the scrolled element.
|
|
264
|
+
const isLimiterWithinScrollTarget = limiterElement && scrollTarget.contains(limiterElement);
|
|
265
|
+
// The positioning target and/or limiter can be a Rect, object etc..
|
|
266
|
+
// There's no way to optimize the listener then.
|
|
267
|
+
if (isWithinScrollTarget || isLimiterWithinScrollTarget || !targetElement || !limiterElement) {
|
|
268
|
+
this.attachTo(options);
|
|
269
|
+
}
|
|
270
|
+
}, { useCapture: true });
|
|
271
|
+
// We need to listen on window resize event and update position.
|
|
272
|
+
this.listenTo(global.window, 'resize', () => {
|
|
273
|
+
this.attachTo(options);
|
|
274
|
+
});
|
|
275
|
+
}
|
|
276
|
+
/**
|
|
277
|
+
* Stops managing the pinned state of the panel. See {@link #pin}.
|
|
278
|
+
*/
|
|
279
|
+
_stopPinning() {
|
|
280
|
+
this.stopListening(global.document, 'scroll');
|
|
281
|
+
this.stopListening(global.window, 'resize');
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
/**
|
|
285
|
+
* A side offset of the arrow tip from the edge of the balloon. Controlled by CSS.
|
|
286
|
+
*
|
|
287
|
+
* ```
|
|
288
|
+
* ┌───────────────────────┐
|
|
289
|
+
* │ │
|
|
290
|
+
* │ Balloon │
|
|
291
|
+
* │ Content │
|
|
292
|
+
* │ │
|
|
293
|
+
* └──+ +───────────────┘
|
|
294
|
+
* | \ /
|
|
295
|
+
* | \/
|
|
296
|
+
* >┼─────┼< ─────────────────────── side offset
|
|
297
|
+
*
|
|
298
|
+
* ```
|
|
299
|
+
*
|
|
300
|
+
* @default 25
|
|
301
|
+
*/
|
|
302
|
+
BalloonPanelView.arrowSideOffset = 25;
|
|
303
|
+
/**
|
|
304
|
+
* A height offset of the arrow from the edge of the balloon. Controlled by CSS.
|
|
305
|
+
*
|
|
306
|
+
* ```
|
|
307
|
+
* ┌───────────────────────┐
|
|
308
|
+
* │ │
|
|
309
|
+
* │ Balloon │
|
|
310
|
+
* │ Content │ ╱-- arrow height offset
|
|
311
|
+
* │ │ V
|
|
312
|
+
* └──+ +───────────────┘ --- ─┼───────
|
|
313
|
+
* \ / │
|
|
314
|
+
* \/ │
|
|
315
|
+
* ────────────────────────────────┼───────
|
|
316
|
+
* ^
|
|
317
|
+
*
|
|
318
|
+
*
|
|
319
|
+
* >┼────┼< arrow height offset
|
|
320
|
+
* │ │
|
|
321
|
+
* │ ┌────────────────────────┐
|
|
322
|
+
* │ │ │
|
|
323
|
+
* │ ╱ │
|
|
324
|
+
* │ ╱ Balloon │
|
|
325
|
+
* │ ╲ Content │
|
|
326
|
+
* │ ╲ │
|
|
327
|
+
* │ │ │
|
|
328
|
+
* │ └────────────────────────┘
|
|
329
|
+
* ```
|
|
330
|
+
*
|
|
331
|
+
* @default 10
|
|
332
|
+
*/
|
|
333
|
+
BalloonPanelView.arrowHeightOffset = 10;
|
|
334
|
+
/**
|
|
335
|
+
* A vertical offset of the balloon panel from the edge of the viewport if sticky.
|
|
336
|
+
* It helps in accessing toolbar buttons underneath the balloon panel.
|
|
337
|
+
*
|
|
338
|
+
* ```
|
|
339
|
+
* ┌───────────────────────────────────────────────────┐
|
|
340
|
+
* │ Target │
|
|
341
|
+
* │ │
|
|
342
|
+
* │ /── vertical offset │
|
|
343
|
+
* ┌─────────────────────────────V─────────────────────────┐
|
|
344
|
+
* │ Toolbar ┌─────────────┐ │
|
|
345
|
+
* ├────────────────────│ Balloon │────────────────────┤
|
|
346
|
+
* │ │ └─────────────┘ │ │
|
|
347
|
+
* │ │ │ │
|
|
348
|
+
* │ │ │ │
|
|
349
|
+
* │ │ │ │
|
|
350
|
+
* │ └───────────────────────────────────────────────────┘ │
|
|
351
|
+
* │ Viewport │
|
|
352
|
+
* └───────────────────────────────────────────────────────┘
|
|
353
|
+
* ```
|
|
354
|
+
*
|
|
355
|
+
* @default 20
|
|
356
|
+
*/
|
|
357
|
+
BalloonPanelView.stickyVerticalOffset = 20;
|
|
358
|
+
/**
|
|
359
|
+
* Function used to calculate the optimal position for the balloon.
|
|
360
|
+
*/
|
|
361
|
+
BalloonPanelView._getOptimalPosition = getOptimalPosition;
|
|
362
|
+
/**
|
|
363
|
+
* A default set of positioning functions used by the balloon panel view
|
|
364
|
+
* when attaching using the {@link module:ui/panel/balloon/balloonpanelview~BalloonPanelView#attachTo} method.
|
|
365
|
+
*
|
|
366
|
+
* The available positioning functions are as follows:
|
|
367
|
+
*
|
|
368
|
+
* **North west**
|
|
369
|
+
*
|
|
370
|
+
* * `northWestArrowSouthWest`
|
|
371
|
+
*
|
|
372
|
+
* ```
|
|
373
|
+
* +-----------------+
|
|
374
|
+
* | Balloon |
|
|
375
|
+
* +-----------------+
|
|
376
|
+
* V
|
|
377
|
+
* [ Target ]
|
|
378
|
+
* ```
|
|
379
|
+
*
|
|
380
|
+
* * `northWestArrowSouthMiddleWest`
|
|
381
|
+
*
|
|
382
|
+
* ```
|
|
383
|
+
* +-----------------+
|
|
384
|
+
* | Balloon |
|
|
385
|
+
* +-----------------+
|
|
386
|
+
* V
|
|
387
|
+
* [ Target ]
|
|
388
|
+
* ```
|
|
389
|
+
*
|
|
390
|
+
* * `northWestArrowSouth`
|
|
391
|
+
*
|
|
392
|
+
* ```
|
|
393
|
+
* +-----------------+
|
|
394
|
+
* | Balloon |
|
|
395
|
+
* +-----------------+
|
|
396
|
+
* V
|
|
397
|
+
* [ Target ]
|
|
398
|
+
* ```
|
|
399
|
+
*
|
|
400
|
+
* * `northWestArrowSouthMiddleEast`
|
|
401
|
+
*
|
|
402
|
+
* ```
|
|
403
|
+
* +-----------------+
|
|
404
|
+
* | Balloon |
|
|
405
|
+
* +-----------------+
|
|
406
|
+
* V
|
|
407
|
+
* [ Target ]
|
|
408
|
+
* ```
|
|
409
|
+
*
|
|
410
|
+
* * `northWestArrowSouthEast`
|
|
411
|
+
*
|
|
412
|
+
* ```
|
|
413
|
+
* +-----------------+
|
|
414
|
+
* | Balloon |
|
|
415
|
+
* +-----------------+
|
|
416
|
+
* V
|
|
417
|
+
* [ Target ]
|
|
418
|
+
* ```
|
|
419
|
+
*
|
|
420
|
+
* **North**
|
|
421
|
+
*
|
|
422
|
+
* * `northArrowSouthWest`
|
|
423
|
+
*
|
|
424
|
+
* ```
|
|
425
|
+
* +-----------------+
|
|
426
|
+
* | Balloon |
|
|
427
|
+
* +-----------------+
|
|
428
|
+
* V
|
|
429
|
+
* [ Target ]
|
|
430
|
+
* ```
|
|
431
|
+
*
|
|
432
|
+
* * `northArrowSouthMiddleWest`
|
|
433
|
+
*
|
|
434
|
+
* ```
|
|
435
|
+
* +-----------------+
|
|
436
|
+
* | Balloon |
|
|
437
|
+
* +-----------------+
|
|
438
|
+
* V
|
|
439
|
+
* [ Target ]
|
|
440
|
+
* ```
|
|
441
|
+
* * `northArrowSouth`
|
|
442
|
+
*
|
|
443
|
+
* ```
|
|
444
|
+
* +-----------------+
|
|
445
|
+
* | Balloon |
|
|
446
|
+
* +-----------------+
|
|
447
|
+
* V
|
|
448
|
+
* [ Target ]
|
|
449
|
+
* ```
|
|
450
|
+
*
|
|
451
|
+
* * `northArrowSouthMiddleEast`
|
|
452
|
+
*
|
|
453
|
+
* ```
|
|
454
|
+
* +-----------------+
|
|
455
|
+
* | Balloon |
|
|
456
|
+
* +-----------------+
|
|
457
|
+
* V
|
|
458
|
+
* [ Target ]
|
|
459
|
+
* ```
|
|
460
|
+
*
|
|
461
|
+
* * `northArrowSouthEast`
|
|
462
|
+
*
|
|
463
|
+
* ```
|
|
464
|
+
* +-----------------+
|
|
465
|
+
* | Balloon |
|
|
466
|
+
* +-----------------+
|
|
467
|
+
* V
|
|
468
|
+
* [ Target ]
|
|
469
|
+
* ```
|
|
470
|
+
*
|
|
471
|
+
* **North east**
|
|
472
|
+
*
|
|
473
|
+
* * `northEastArrowSouthWest`
|
|
474
|
+
*
|
|
475
|
+
* ```
|
|
476
|
+
* +-----------------+
|
|
477
|
+
* | Balloon |
|
|
478
|
+
* +-----------------+
|
|
479
|
+
* V
|
|
480
|
+
* [ Target ]
|
|
481
|
+
* ```
|
|
482
|
+
*
|
|
483
|
+
* * `northEastArrowSouthMiddleWest`
|
|
484
|
+
*
|
|
485
|
+
* ```
|
|
486
|
+
* +-----------------+
|
|
487
|
+
* | Balloon |
|
|
488
|
+
* +-----------------+
|
|
489
|
+
* V
|
|
490
|
+
* [ Target ]
|
|
491
|
+
* ```
|
|
492
|
+
*
|
|
493
|
+
* * `northEastArrowSouth`
|
|
494
|
+
*
|
|
495
|
+
* ```
|
|
496
|
+
* +-----------------+
|
|
497
|
+
* | Balloon |
|
|
498
|
+
* +-----------------+
|
|
499
|
+
* V
|
|
500
|
+
* [ Target ]
|
|
501
|
+
* ```
|
|
502
|
+
*
|
|
503
|
+
* * `northEastArrowSouthMiddleEast`
|
|
504
|
+
*
|
|
505
|
+
* ```
|
|
506
|
+
* +-----------------+
|
|
507
|
+
* | Balloon |
|
|
508
|
+
* +-----------------+
|
|
509
|
+
* V
|
|
510
|
+
* [ Target ]
|
|
511
|
+
* ```
|
|
512
|
+
*
|
|
513
|
+
* * `northEastArrowSouthEast`
|
|
514
|
+
*
|
|
515
|
+
* ```
|
|
516
|
+
* +-----------------+
|
|
517
|
+
* | Balloon |
|
|
518
|
+
* +-----------------+
|
|
519
|
+
* V
|
|
520
|
+
* [ Target ]
|
|
521
|
+
* ```
|
|
522
|
+
*
|
|
523
|
+
* **South**
|
|
524
|
+
*
|
|
525
|
+
* * `southArrowNorthWest`
|
|
526
|
+
*
|
|
527
|
+
* ```
|
|
528
|
+
* [ Target ]
|
|
529
|
+
* ^
|
|
530
|
+
* +-----------------+
|
|
531
|
+
* | Balloon |
|
|
532
|
+
* +-----------------+
|
|
533
|
+
* ```
|
|
534
|
+
*
|
|
535
|
+
* * `southArrowNorthMiddleWest`
|
|
536
|
+
*
|
|
537
|
+
* ```
|
|
538
|
+
* [ Target ]
|
|
539
|
+
* ^
|
|
540
|
+
* +-----------------+
|
|
541
|
+
* | Balloon |
|
|
542
|
+
* +-----------------+
|
|
543
|
+
* ```
|
|
544
|
+
*
|
|
545
|
+
* * `southArrowNorth`
|
|
546
|
+
*
|
|
547
|
+
* ```
|
|
548
|
+
* [ Target ]
|
|
549
|
+
* ^
|
|
550
|
+
* +-----------------+
|
|
551
|
+
* | Balloon |
|
|
552
|
+
* +-----------------+
|
|
553
|
+
* ```
|
|
554
|
+
*
|
|
555
|
+
* * `southArrowNorthMiddleEast`
|
|
556
|
+
*
|
|
557
|
+
* ```
|
|
558
|
+
* [ Target ]
|
|
559
|
+
* ^
|
|
560
|
+
* +-----------------+
|
|
561
|
+
* | Balloon |
|
|
562
|
+
* +-----------------+
|
|
563
|
+
* ```
|
|
564
|
+
*
|
|
565
|
+
* * `southArrowNorthEast`
|
|
566
|
+
*
|
|
567
|
+
* ```
|
|
568
|
+
* [ Target ]
|
|
569
|
+
* ^
|
|
570
|
+
* +-----------------+
|
|
571
|
+
* | Balloon |
|
|
572
|
+
* +-----------------+
|
|
573
|
+
* ```
|
|
574
|
+
*
|
|
575
|
+
* **South west**
|
|
576
|
+
*
|
|
577
|
+
* * `southWestArrowNorthWest`
|
|
578
|
+
*
|
|
579
|
+
*
|
|
580
|
+
* ```
|
|
581
|
+
* [ Target ]
|
|
582
|
+
* ^
|
|
583
|
+
* +-----------------+
|
|
584
|
+
* | Balloon |
|
|
585
|
+
* +-----------------+
|
|
586
|
+
* ```
|
|
587
|
+
*
|
|
588
|
+
* * `southWestArrowNorthMiddleWest`
|
|
589
|
+
*
|
|
590
|
+
* ```
|
|
591
|
+
* [ Target ]
|
|
592
|
+
* ^
|
|
593
|
+
* +-----------------+
|
|
594
|
+
* | Balloon |
|
|
595
|
+
* +-----------------+
|
|
596
|
+
* ```
|
|
597
|
+
*
|
|
598
|
+
* * `southWestArrowNorth`
|
|
599
|
+
*
|
|
600
|
+
* ```
|
|
601
|
+
* [ Target ]
|
|
602
|
+
* ^
|
|
603
|
+
* +-----------------+
|
|
604
|
+
* | Balloon |
|
|
605
|
+
* +-----------------+
|
|
606
|
+
* ```
|
|
607
|
+
*
|
|
608
|
+
* * `southWestArrowNorthMiddleEast`
|
|
609
|
+
*
|
|
610
|
+
* ```
|
|
611
|
+
* [ Target ]
|
|
612
|
+
* ^
|
|
613
|
+
* +-----------------+
|
|
614
|
+
* | Balloon |
|
|
615
|
+
* +-----------------+
|
|
616
|
+
* ```
|
|
617
|
+
*
|
|
618
|
+
* * `southWestArrowNorthEast`
|
|
619
|
+
*
|
|
620
|
+
* ```
|
|
621
|
+
* [ Target ]
|
|
622
|
+
* ^
|
|
623
|
+
* +-----------------+
|
|
624
|
+
* | Balloon |
|
|
625
|
+
* +-----------------+
|
|
626
|
+
* ```
|
|
627
|
+
*
|
|
628
|
+
* **South east**
|
|
629
|
+
*
|
|
630
|
+
* * `southEastArrowNorthWest`
|
|
631
|
+
*
|
|
632
|
+
* ```
|
|
633
|
+
* [ Target ]
|
|
634
|
+
* ^
|
|
635
|
+
* +-----------------+
|
|
636
|
+
* | Balloon |
|
|
637
|
+
* +-----------------+
|
|
638
|
+
* ```
|
|
639
|
+
*
|
|
640
|
+
* * `southEastArrowNorthMiddleWest`
|
|
641
|
+
*
|
|
642
|
+
* ```
|
|
643
|
+
* [ Target ]
|
|
644
|
+
* ^
|
|
645
|
+
* +-----------------+
|
|
646
|
+
* | Balloon |
|
|
647
|
+
* +-----------------+
|
|
648
|
+
* ```
|
|
649
|
+
*
|
|
650
|
+
* * `southEastArrowNorth`
|
|
651
|
+
*
|
|
652
|
+
* ```
|
|
653
|
+
* [ Target ]
|
|
654
|
+
* ^
|
|
655
|
+
* +-----------------+
|
|
656
|
+
* | Balloon |
|
|
657
|
+
* +-----------------+
|
|
658
|
+
* ```
|
|
659
|
+
*
|
|
660
|
+
* * `southEastArrowNorthMiddleEast`
|
|
661
|
+
*
|
|
662
|
+
* ```
|
|
663
|
+
* [ Target ]
|
|
664
|
+
* ^
|
|
665
|
+
* +-----------------+
|
|
666
|
+
* | Balloon |
|
|
667
|
+
* +-----------------+
|
|
668
|
+
* ```
|
|
669
|
+
*
|
|
670
|
+
* * `southEastArrowNorthEast`
|
|
671
|
+
*
|
|
672
|
+
* ```
|
|
673
|
+
* [ Target ]
|
|
674
|
+
* ^
|
|
675
|
+
* +-----------------+
|
|
676
|
+
* | Balloon |
|
|
677
|
+
* +-----------------+
|
|
678
|
+
* ```
|
|
679
|
+
*
|
|
680
|
+
* **West**
|
|
681
|
+
*
|
|
682
|
+
* * `westArrowEast`
|
|
683
|
+
*
|
|
684
|
+
* ```
|
|
685
|
+
* +-----------------+
|
|
686
|
+
* | Balloon |>[ Target ]
|
|
687
|
+
* +-----------------+
|
|
688
|
+
* ```
|
|
689
|
+
*
|
|
690
|
+
* **East**
|
|
691
|
+
*
|
|
692
|
+
* * `eastArrowWest`
|
|
693
|
+
*
|
|
694
|
+
* ```
|
|
695
|
+
* +-----------------+
|
|
696
|
+
* [ Target ]<| Balloon |
|
|
697
|
+
* +-----------------+
|
|
698
|
+
* ```
|
|
699
|
+
*
|
|
700
|
+
* **Sticky**
|
|
701
|
+
*
|
|
702
|
+
* * `viewportStickyNorth`
|
|
703
|
+
*
|
|
704
|
+
* ```
|
|
705
|
+
* +---------------------------+
|
|
706
|
+
* | [ Target ] |
|
|
707
|
+
* | |
|
|
708
|
+
* +-----------------------------------+
|
|
709
|
+
* | | +-----------------+ | |
|
|
710
|
+
* | | | Balloon | | |
|
|
711
|
+
* | | +-----------------+ | |
|
|
712
|
+
* | | | |
|
|
713
|
+
* | | | |
|
|
714
|
+
* | | | |
|
|
715
|
+
* | | | |
|
|
716
|
+
* | +---------------------------+ |
|
|
717
|
+
* | Viewport |
|
|
718
|
+
* +-----------------------------------+
|
|
719
|
+
* ```
|
|
720
|
+
*
|
|
721
|
+
* See {@link module:ui/panel/balloon/balloonpanelview~BalloonPanelView#attachTo}.
|
|
722
|
+
*
|
|
723
|
+
* Positioning functions must be compatible with {@link module:utils/dom/position~Position}.
|
|
724
|
+
*
|
|
725
|
+
* Default positioning functions with customized offsets can be generated using
|
|
726
|
+
* {@link module:ui/panel/balloon/balloonpanelview~generatePositions}.
|
|
727
|
+
*
|
|
728
|
+
* The name that the position function returns will be reflected in the balloon panel's class that
|
|
729
|
+
* controls the placement of the "arrow". See {@link #position} to learn more.
|
|
730
|
+
*/
|
|
731
|
+
BalloonPanelView.defaultPositions = generatePositions();
|
|
732
|
+
/**
|
|
733
|
+
* Returns the DOM element for given object or null, if there is none,
|
|
734
|
+
* e.g. when the passed object is a Rect instance or so.
|
|
735
|
+
*/
|
|
736
|
+
function getDomElement(object) {
|
|
737
|
+
if (isElement(object)) {
|
|
738
|
+
return object;
|
|
739
|
+
}
|
|
740
|
+
if (isRange(object)) {
|
|
741
|
+
return object.commonAncestorContainer;
|
|
742
|
+
}
|
|
743
|
+
if (typeof object == 'function') {
|
|
744
|
+
return getDomElement(object());
|
|
745
|
+
}
|
|
746
|
+
return null;
|
|
747
|
+
}
|
|
748
|
+
/**
|
|
749
|
+
* Returns available {@link module:ui/panel/balloon/balloonpanelview~BalloonPanelView}
|
|
750
|
+
* {@link module:utils/dom/position~PositioningFunction positioning functions} adjusted by the specific offsets.
|
|
751
|
+
*
|
|
752
|
+
* @internal
|
|
753
|
+
* @param options Options to generate positions. If not specified, this helper will simply return
|
|
754
|
+
* {@link module:ui/panel/balloon/balloonpanelview~BalloonPanelView.defaultPositions}.
|
|
755
|
+
* @param options.sideOffset A custom side offset (in pixels) of each position. If
|
|
756
|
+
* not specified, {@link module:ui/panel/balloon/balloonpanelview~BalloonPanelView.arrowSideOffset the default value}
|
|
757
|
+
* will be used.
|
|
758
|
+
* @param options.heightOffset A custom height offset (in pixels) of each position. If
|
|
759
|
+
* not specified, {@link module:ui/panel/balloon/balloonpanelview~BalloonPanelView.arrowHeightOffset the default value}
|
|
760
|
+
* will be used.
|
|
761
|
+
* @param options.stickyVerticalOffset A custom offset (in pixels) of the `viewportStickyNorth` positioning function.
|
|
762
|
+
* If not specified, {@link module:ui/panel/balloon/balloonpanelview~BalloonPanelView.stickyVerticalOffset the default value}
|
|
763
|
+
* will be used.
|
|
764
|
+
* @param options.config Additional configuration of the balloon balloon panel view.
|
|
765
|
+
* Currently only {@link module:ui/panel/balloon/balloonpanelview~BalloonPanelView#withArrow} is supported. Learn more
|
|
766
|
+
* about {@link module:utils/dom/position~PositioningFunction positioning functions}.
|
|
767
|
+
*/
|
|
768
|
+
export function generatePositions(options = {}) {
|
|
769
|
+
const { sideOffset = BalloonPanelView.arrowSideOffset, heightOffset = BalloonPanelView.arrowHeightOffset, stickyVerticalOffset = BalloonPanelView.stickyVerticalOffset, config } = options;
|
|
770
|
+
return {
|
|
771
|
+
// ------- North west
|
|
772
|
+
northWestArrowSouthWest: (targetRect, balloonRect) => ({
|
|
773
|
+
top: getNorthTop(targetRect, balloonRect),
|
|
774
|
+
left: targetRect.left - sideOffset,
|
|
775
|
+
name: 'arrow_sw',
|
|
776
|
+
...(config && { config })
|
|
777
|
+
}),
|
|
778
|
+
northWestArrowSouthMiddleWest: (targetRect, balloonRect) => ({
|
|
779
|
+
top: getNorthTop(targetRect, balloonRect),
|
|
780
|
+
left: targetRect.left - (balloonRect.width * .25) - sideOffset,
|
|
781
|
+
name: 'arrow_smw',
|
|
782
|
+
...(config && { config })
|
|
783
|
+
}),
|
|
784
|
+
northWestArrowSouth: (targetRect, balloonRect) => ({
|
|
785
|
+
top: getNorthTop(targetRect, balloonRect),
|
|
786
|
+
left: targetRect.left - balloonRect.width / 2,
|
|
787
|
+
name: 'arrow_s',
|
|
788
|
+
...(config && { config })
|
|
789
|
+
}),
|
|
790
|
+
northWestArrowSouthMiddleEast: (targetRect, balloonRect) => ({
|
|
791
|
+
top: getNorthTop(targetRect, balloonRect),
|
|
792
|
+
left: targetRect.left - (balloonRect.width * .75) + sideOffset,
|
|
793
|
+
name: 'arrow_sme',
|
|
794
|
+
...(config && { config })
|
|
795
|
+
}),
|
|
796
|
+
northWestArrowSouthEast: (targetRect, balloonRect) => ({
|
|
797
|
+
top: getNorthTop(targetRect, balloonRect),
|
|
798
|
+
left: targetRect.left - balloonRect.width + sideOffset,
|
|
799
|
+
name: 'arrow_se',
|
|
800
|
+
...(config && { config })
|
|
801
|
+
}),
|
|
802
|
+
// ------- North
|
|
803
|
+
northArrowSouthWest: (targetRect, balloonRect) => ({
|
|
804
|
+
top: getNorthTop(targetRect, balloonRect),
|
|
805
|
+
left: targetRect.left + targetRect.width / 2 - sideOffset,
|
|
806
|
+
name: 'arrow_sw',
|
|
807
|
+
...(config && { config })
|
|
808
|
+
}),
|
|
809
|
+
northArrowSouthMiddleWest: (targetRect, balloonRect) => ({
|
|
810
|
+
top: getNorthTop(targetRect, balloonRect),
|
|
811
|
+
left: targetRect.left + targetRect.width / 2 - (balloonRect.width * .25) - sideOffset,
|
|
812
|
+
name: 'arrow_smw',
|
|
813
|
+
...(config && { config })
|
|
814
|
+
}),
|
|
815
|
+
northArrowSouth: (targetRect, balloonRect) => ({
|
|
816
|
+
top: getNorthTop(targetRect, balloonRect),
|
|
817
|
+
left: targetRect.left + targetRect.width / 2 - balloonRect.width / 2,
|
|
818
|
+
name: 'arrow_s',
|
|
819
|
+
...(config && { config })
|
|
820
|
+
}),
|
|
821
|
+
northArrowSouthMiddleEast: (targetRect, balloonRect) => ({
|
|
822
|
+
top: getNorthTop(targetRect, balloonRect),
|
|
823
|
+
left: targetRect.left + targetRect.width / 2 - (balloonRect.width * .75) + sideOffset,
|
|
824
|
+
name: 'arrow_sme',
|
|
825
|
+
...(config && { config })
|
|
826
|
+
}),
|
|
827
|
+
northArrowSouthEast: (targetRect, balloonRect) => ({
|
|
828
|
+
top: getNorthTop(targetRect, balloonRect),
|
|
829
|
+
left: targetRect.left + targetRect.width / 2 - balloonRect.width + sideOffset,
|
|
830
|
+
name: 'arrow_se',
|
|
831
|
+
...(config && { config })
|
|
832
|
+
}),
|
|
833
|
+
// ------- North east
|
|
834
|
+
northEastArrowSouthWest: (targetRect, balloonRect) => ({
|
|
835
|
+
top: getNorthTop(targetRect, balloonRect),
|
|
836
|
+
left: targetRect.right - sideOffset,
|
|
837
|
+
name: 'arrow_sw',
|
|
838
|
+
...(config && { config })
|
|
839
|
+
}),
|
|
840
|
+
northEastArrowSouthMiddleWest: (targetRect, balloonRect) => ({
|
|
841
|
+
top: getNorthTop(targetRect, balloonRect),
|
|
842
|
+
left: targetRect.right - (balloonRect.width * .25) - sideOffset,
|
|
843
|
+
name: 'arrow_smw',
|
|
844
|
+
...(config && { config })
|
|
845
|
+
}),
|
|
846
|
+
northEastArrowSouth: (targetRect, balloonRect) => ({
|
|
847
|
+
top: getNorthTop(targetRect, balloonRect),
|
|
848
|
+
left: targetRect.right - balloonRect.width / 2,
|
|
849
|
+
name: 'arrow_s',
|
|
850
|
+
...(config && { config })
|
|
851
|
+
}),
|
|
852
|
+
northEastArrowSouthMiddleEast: (targetRect, balloonRect) => ({
|
|
853
|
+
top: getNorthTop(targetRect, balloonRect),
|
|
854
|
+
left: targetRect.right - (balloonRect.width * .75) + sideOffset,
|
|
855
|
+
name: 'arrow_sme',
|
|
856
|
+
...(config && { config })
|
|
857
|
+
}),
|
|
858
|
+
northEastArrowSouthEast: (targetRect, balloonRect) => ({
|
|
859
|
+
top: getNorthTop(targetRect, balloonRect),
|
|
860
|
+
left: targetRect.right - balloonRect.width + sideOffset,
|
|
861
|
+
name: 'arrow_se',
|
|
862
|
+
...(config && { config })
|
|
863
|
+
}),
|
|
864
|
+
// ------- South west
|
|
865
|
+
southWestArrowNorthWest: targetRect => ({
|
|
866
|
+
top: getSouthTop(targetRect),
|
|
867
|
+
left: targetRect.left - sideOffset,
|
|
868
|
+
name: 'arrow_nw',
|
|
869
|
+
...(config && { config })
|
|
870
|
+
}),
|
|
871
|
+
southWestArrowNorthMiddleWest: (targetRect, balloonRect) => ({
|
|
872
|
+
top: getSouthTop(targetRect),
|
|
873
|
+
left: targetRect.left - (balloonRect.width * .25) - sideOffset,
|
|
874
|
+
name: 'arrow_nmw',
|
|
875
|
+
...(config && { config })
|
|
876
|
+
}),
|
|
877
|
+
southWestArrowNorth: (targetRect, balloonRect) => ({
|
|
878
|
+
top: getSouthTop(targetRect),
|
|
879
|
+
left: targetRect.left - balloonRect.width / 2,
|
|
880
|
+
name: 'arrow_n',
|
|
881
|
+
...(config && { config })
|
|
882
|
+
}),
|
|
883
|
+
southWestArrowNorthMiddleEast: (targetRect, balloonRect) => ({
|
|
884
|
+
top: getSouthTop(targetRect),
|
|
885
|
+
left: targetRect.left - (balloonRect.width * .75) + sideOffset,
|
|
886
|
+
name: 'arrow_nme',
|
|
887
|
+
...(config && { config })
|
|
888
|
+
}),
|
|
889
|
+
southWestArrowNorthEast: (targetRect, balloonRect) => ({
|
|
890
|
+
top: getSouthTop(targetRect),
|
|
891
|
+
left: targetRect.left - balloonRect.width + sideOffset,
|
|
892
|
+
name: 'arrow_ne',
|
|
893
|
+
...(config && { config })
|
|
894
|
+
}),
|
|
895
|
+
// ------- South
|
|
896
|
+
southArrowNorthWest: targetRect => ({
|
|
897
|
+
top: getSouthTop(targetRect),
|
|
898
|
+
left: targetRect.left + targetRect.width / 2 - sideOffset,
|
|
899
|
+
name: 'arrow_nw',
|
|
900
|
+
...(config && { config })
|
|
901
|
+
}),
|
|
902
|
+
southArrowNorthMiddleWest: (targetRect, balloonRect) => ({
|
|
903
|
+
top: getSouthTop(targetRect),
|
|
904
|
+
left: targetRect.left + targetRect.width / 2 - (balloonRect.width * 0.25) - sideOffset,
|
|
905
|
+
name: 'arrow_nmw',
|
|
906
|
+
...(config && { config })
|
|
907
|
+
}),
|
|
908
|
+
southArrowNorth: (targetRect, balloonRect) => ({
|
|
909
|
+
top: getSouthTop(targetRect),
|
|
910
|
+
left: targetRect.left + targetRect.width / 2 - balloonRect.width / 2,
|
|
911
|
+
name: 'arrow_n',
|
|
912
|
+
...(config && { config })
|
|
913
|
+
}),
|
|
914
|
+
southArrowNorthMiddleEast: (targetRect, balloonRect) => ({
|
|
915
|
+
top: getSouthTop(targetRect),
|
|
916
|
+
left: targetRect.left + targetRect.width / 2 - (balloonRect.width * 0.75) + sideOffset,
|
|
917
|
+
name: 'arrow_nme',
|
|
918
|
+
...(config && { config })
|
|
919
|
+
}),
|
|
920
|
+
southArrowNorthEast: (targetRect, balloonRect) => ({
|
|
921
|
+
top: getSouthTop(targetRect),
|
|
922
|
+
left: targetRect.left + targetRect.width / 2 - balloonRect.width + sideOffset,
|
|
923
|
+
name: 'arrow_ne',
|
|
924
|
+
...(config && { config })
|
|
925
|
+
}),
|
|
926
|
+
// ------- South east
|
|
927
|
+
southEastArrowNorthWest: targetRect => ({
|
|
928
|
+
top: getSouthTop(targetRect),
|
|
929
|
+
left: targetRect.right - sideOffset,
|
|
930
|
+
name: 'arrow_nw',
|
|
931
|
+
...(config && { config })
|
|
932
|
+
}),
|
|
933
|
+
southEastArrowNorthMiddleWest: (targetRect, balloonRect) => ({
|
|
934
|
+
top: getSouthTop(targetRect),
|
|
935
|
+
left: targetRect.right - (balloonRect.width * .25) - sideOffset,
|
|
936
|
+
name: 'arrow_nmw',
|
|
937
|
+
...(config && { config })
|
|
938
|
+
}),
|
|
939
|
+
southEastArrowNorth: (targetRect, balloonRect) => ({
|
|
940
|
+
top: getSouthTop(targetRect),
|
|
941
|
+
left: targetRect.right - balloonRect.width / 2,
|
|
942
|
+
name: 'arrow_n',
|
|
943
|
+
...(config && { config })
|
|
944
|
+
}),
|
|
945
|
+
southEastArrowNorthMiddleEast: (targetRect, balloonRect) => ({
|
|
946
|
+
top: getSouthTop(targetRect),
|
|
947
|
+
left: targetRect.right - (balloonRect.width * .75) + sideOffset,
|
|
948
|
+
name: 'arrow_nme',
|
|
949
|
+
...(config && { config })
|
|
950
|
+
}),
|
|
951
|
+
southEastArrowNorthEast: (targetRect, balloonRect) => ({
|
|
952
|
+
top: getSouthTop(targetRect),
|
|
953
|
+
left: targetRect.right - balloonRect.width + sideOffset,
|
|
954
|
+
name: 'arrow_ne',
|
|
955
|
+
...(config && { config })
|
|
956
|
+
}),
|
|
957
|
+
// ------- West
|
|
958
|
+
westArrowEast: (targetRect, balloonRect) => ({
|
|
959
|
+
top: targetRect.top + targetRect.height / 2 - balloonRect.height / 2,
|
|
960
|
+
left: targetRect.left - balloonRect.width - heightOffset,
|
|
961
|
+
name: 'arrow_e',
|
|
962
|
+
...(config && { config })
|
|
963
|
+
}),
|
|
964
|
+
// ------- East
|
|
965
|
+
eastArrowWest: (targetRect, balloonRect) => ({
|
|
966
|
+
top: targetRect.top + targetRect.height / 2 - balloonRect.height / 2,
|
|
967
|
+
left: targetRect.right + heightOffset,
|
|
968
|
+
name: 'arrow_w',
|
|
969
|
+
...(config && { config })
|
|
970
|
+
}),
|
|
971
|
+
// ------- Sticky
|
|
972
|
+
viewportStickyNorth: (targetRect, balloonRect, viewportRect, limiterRect) => {
|
|
973
|
+
const boundaryRect = limiterRect || viewportRect;
|
|
974
|
+
if (!targetRect.getIntersection(boundaryRect)) {
|
|
975
|
+
return null;
|
|
976
|
+
}
|
|
977
|
+
// Engage when the target top and bottom edges are close or off the boundary.
|
|
978
|
+
// By close, it means there's not enough space for the balloon arrow (offset).
|
|
979
|
+
if (boundaryRect.height - targetRect.height > stickyVerticalOffset) {
|
|
980
|
+
return null;
|
|
981
|
+
}
|
|
982
|
+
return {
|
|
983
|
+
top: boundaryRect.top + stickyVerticalOffset,
|
|
984
|
+
left: targetRect.left + targetRect.width / 2 - balloonRect.width / 2,
|
|
985
|
+
name: 'arrowless',
|
|
986
|
+
config: {
|
|
987
|
+
withArrow: false,
|
|
988
|
+
...config
|
|
989
|
+
}
|
|
990
|
+
};
|
|
991
|
+
}
|
|
992
|
+
};
|
|
993
|
+
/**
|
|
994
|
+
* Returns the top coordinate for positions starting with `north*`.
|
|
995
|
+
*
|
|
996
|
+
* @param targetRect A rect of the target.
|
|
997
|
+
* @param balloonRect A rect of the balloon.
|
|
998
|
+
*/
|
|
999
|
+
function getNorthTop(targetRect, balloonRect) {
|
|
1000
|
+
return targetRect.top - balloonRect.height - heightOffset;
|
|
1001
|
+
}
|
|
1002
|
+
/**
|
|
1003
|
+
* Returns the top coordinate for positions starting with `south*`.
|
|
1004
|
+
*
|
|
1005
|
+
* @param targetRect A rect of the target.
|
|
1006
|
+
*/
|
|
1007
|
+
function getSouthTop(targetRect) {
|
|
1008
|
+
return targetRect.bottom + heightOffset;
|
|
1009
|
+
}
|
|
1010
|
+
}
|