suneditor 3.0.0-beta.2 → 3.0.0-beta.20
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/CONTRIBUTING.md +186 -184
- package/LICENSE +21 -21
- package/README.md +157 -180
- package/dist/suneditor.min.css +1 -1
- package/dist/suneditor.min.js +1 -1
- package/package.json +126 -123
- package/src/assets/design/color.css +131 -121
- package/src/assets/design/index.css +3 -3
- package/src/assets/design/size.css +37 -35
- package/src/assets/design/typography.css +37 -37
- package/src/assets/icons/defaultIcons.js +247 -232
- package/src/assets/suneditor-contents.css +779 -778
- package/src/assets/suneditor.css +43 -35
- package/src/core/base/eventHandlers/handler_toolbar.js +135 -135
- package/src/core/base/eventHandlers/handler_ww_clipboard.js +56 -56
- package/src/core/base/eventHandlers/handler_ww_dragDrop.js +115 -113
- package/src/core/base/eventHandlers/handler_ww_key_input.js +1200 -1200
- package/src/core/base/eventHandlers/handler_ww_mouse.js +194 -194
- package/src/core/base/eventManager.js +1550 -1484
- package/src/core/base/history.js +355 -355
- package/src/core/class/char.js +163 -162
- package/src/core/class/component.js +856 -842
- package/src/core/class/format.js +3433 -3422
- package/src/core/class/html.js +1927 -1890
- package/src/core/class/menu.js +357 -346
- package/src/core/class/nodeTransform.js +424 -424
- package/src/core/class/offset.js +858 -891
- package/src/core/class/selection.js +710 -620
- package/src/core/class/shortcuts.js +98 -98
- package/src/core/class/toolbar.js +438 -430
- package/src/core/class/ui.js +424 -422
- package/src/core/class/viewer.js +750 -750
- package/src/core/editor.js +1810 -1708
- package/src/core/section/actives.js +268 -241
- package/src/core/section/constructor.js +1348 -1661
- package/src/core/section/context.js +102 -102
- package/src/core/section/documentType.js +582 -561
- package/src/core/section/options.js +367 -0
- package/src/core/util/instanceCheck.js +59 -0
- package/src/editorInjector/_classes.js +36 -36
- package/src/editorInjector/_core.js +92 -92
- package/src/editorInjector/index.js +75 -75
- package/src/events.js +634 -622
- package/src/helper/clipboard.js +59 -59
- package/src/helper/converter.js +586 -564
- package/src/helper/dom/domCheck.js +304 -304
- package/src/helper/dom/domQuery.js +677 -669
- package/src/helper/dom/domUtils.js +618 -557
- package/src/helper/dom/index.js +12 -12
- package/src/helper/env.js +249 -240
- package/src/helper/index.js +25 -25
- package/src/helper/keyCodeMap.js +183 -183
- package/src/helper/numbers.js +72 -72
- package/src/helper/unicode.js +47 -47
- package/src/langs/ckb.js +231 -231
- package/src/langs/cs.js +231 -231
- package/src/langs/da.js +231 -231
- package/src/langs/de.js +231 -231
- package/src/langs/en.js +230 -230
- package/src/langs/es.js +231 -231
- package/src/langs/fa.js +231 -231
- package/src/langs/fr.js +231 -231
- package/src/langs/he.js +231 -231
- package/src/langs/hu.js +230 -230
- package/src/langs/index.js +28 -28
- package/src/langs/it.js +231 -231
- package/src/langs/ja.js +230 -230
- package/src/langs/km.js +230 -230
- package/src/langs/ko.js +230 -230
- package/src/langs/lv.js +231 -231
- package/src/langs/nl.js +231 -231
- package/src/langs/pl.js +231 -231
- package/src/langs/pt_br.js +231 -231
- package/src/langs/ro.js +231 -231
- package/src/langs/ru.js +231 -231
- package/src/langs/se.js +231 -231
- package/src/langs/tr.js +231 -231
- package/src/langs/uk.js +231 -231
- package/src/langs/ur.js +231 -231
- package/src/langs/zh_cn.js +231 -231
- package/src/modules/ApiManager.js +191 -191
- package/src/modules/Browser.js +669 -667
- package/src/modules/ColorPicker.js +364 -362
- package/src/modules/Controller.js +474 -454
- package/src/modules/Figure.js +1620 -1617
- package/src/modules/FileManager.js +359 -359
- package/src/modules/HueSlider.js +577 -565
- package/src/modules/Modal.js +346 -346
- package/src/modules/ModalAnchorEditor.js +643 -643
- package/src/modules/SelectMenu.js +549 -549
- package/src/modules/_DragHandle.js +17 -17
- package/src/modules/index.js +14 -14
- package/src/plugins/browser/audioGallery.js +83 -83
- package/src/plugins/browser/fileBrowser.js +103 -103
- package/src/plugins/browser/fileGallery.js +83 -83
- package/src/plugins/browser/imageGallery.js +81 -81
- package/src/plugins/browser/videoGallery.js +103 -103
- package/src/plugins/command/blockquote.js +61 -60
- package/src/plugins/command/exportPDF.js +134 -134
- package/src/plugins/command/fileUpload.js +456 -456
- package/src/plugins/command/list_bulleted.js +149 -148
- package/src/plugins/command/list_numbered.js +152 -151
- package/src/plugins/dropdown/align.js +157 -155
- package/src/plugins/dropdown/backgroundColor.js +108 -104
- package/src/plugins/dropdown/font.js +141 -137
- package/src/plugins/dropdown/fontColor.js +109 -105
- package/src/plugins/dropdown/formatBlock.js +170 -178
- package/src/plugins/dropdown/hr.js +152 -152
- package/src/plugins/dropdown/layout.js +83 -83
- package/src/plugins/dropdown/lineHeight.js +131 -130
- package/src/plugins/dropdown/list.js +123 -122
- package/src/plugins/dropdown/paragraphStyle.js +138 -138
- package/src/plugins/dropdown/table.js +4110 -4000
- package/src/plugins/dropdown/template.js +83 -83
- package/src/plugins/dropdown/textStyle.js +149 -149
- package/src/plugins/field/mention.js +242 -242
- package/src/plugins/index.js +120 -120
- package/src/plugins/input/fontSize.js +414 -410
- package/src/plugins/input/pageNavigator.js +71 -70
- package/src/plugins/modal/audio.js +677 -677
- package/src/plugins/modal/drawing.js +537 -531
- package/src/plugins/modal/embed.js +886 -886
- package/src/plugins/modal/image.js +1377 -1376
- package/src/plugins/modal/link.js +248 -240
- package/src/plugins/modal/math.js +563 -563
- package/src/plugins/modal/video.js +1226 -1226
- package/src/plugins/popup/anchor.js +224 -222
- package/src/suneditor.js +114 -107
- package/src/themes/dark.css +132 -122
- package/src/typedef.js +132 -130
- package/types/assets/icons/defaultIcons.d.ts +8 -0
- package/types/core/base/eventManager.d.ts +29 -4
- package/types/core/class/char.d.ts +2 -1
- package/types/core/class/component.d.ts +1 -2
- package/types/core/class/format.d.ts +8 -1
- package/types/core/class/html.d.ts +8 -0
- package/types/core/class/menu.d.ts +8 -0
- package/types/core/class/offset.d.ts +24 -26
- package/types/core/class/selection.d.ts +2 -0
- package/types/core/class/toolbar.d.ts +6 -0
- package/types/core/class/ui.d.ts +1 -1
- package/types/core/editor.d.ts +34 -12
- package/types/core/section/constructor.d.ts +5 -638
- package/types/core/section/documentType.d.ts +12 -2
- package/types/core/section/options.d.ts +740 -0
- package/types/core/util/instanceCheck.d.ts +50 -0
- package/types/editorInjector/_core.d.ts +5 -5
- package/types/editorInjector/index.d.ts +2 -2
- package/types/events.d.ts +2 -0
- package/types/helper/converter.d.ts +9 -0
- package/types/helper/dom/domQuery.d.ts +5 -5
- package/types/helper/dom/domUtils.d.ts +8 -0
- package/types/helper/env.d.ts +6 -1
- package/types/helper/index.d.ts +4 -1
- package/types/index.d.ts +122 -120
- package/types/langs/_Lang.d.ts +194 -194
- package/types/modules/ColorPicker.d.ts +5 -1
- package/types/modules/Controller.d.ts +8 -4
- package/types/modules/Figure.d.ts +2 -1
- package/types/modules/HueSlider.d.ts +4 -1
- package/types/modules/SelectMenu.d.ts +1 -1
- package/types/plugins/command/blockquote.d.ts +1 -0
- package/types/plugins/command/list_bulleted.d.ts +1 -0
- package/types/plugins/command/list_numbered.d.ts +1 -0
- package/types/plugins/dropdown/align.d.ts +1 -0
- package/types/plugins/dropdown/backgroundColor.d.ts +1 -0
- package/types/plugins/dropdown/font.d.ts +1 -0
- package/types/plugins/dropdown/fontColor.d.ts +1 -0
- package/types/plugins/dropdown/formatBlock.d.ts +3 -2
- package/types/plugins/dropdown/lineHeight.d.ts +1 -0
- package/types/plugins/dropdown/list.d.ts +1 -0
- package/types/plugins/dropdown/table.d.ts +6 -0
- package/types/plugins/input/fontSize.d.ts +1 -0
- package/types/plugins/modal/drawing.d.ts +4 -0
- package/types/plugins/modal/link.d.ts +32 -15
- package/types/suneditor.d.ts +13 -9
- package/types/typedef.d.ts +8 -0
package/src/core/class/offset.js
CHANGED
|
@@ -1,891 +1,858 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @fileoverview Offset class
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
import CoreInjector from '../../editorInjector/_core';
|
|
6
|
-
import { getParentElement } from '../../helper/dom/domQuery';
|
|
7
|
-
import { isWysiwygFrame, isElement } from '../../helper/dom/domCheck';
|
|
8
|
-
import { hasClass, addClass, removeClass, getClientSize } from '../../helper/dom/domUtils';
|
|
9
|
-
import { numbers } from '../../helper';
|
|
10
|
-
import { _w, _d } from '../../helper/env';
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* @typedef {Omit<Offset & Partial<__se__EditorInjector>, 'offset'>} OffsetThis
|
|
14
|
-
*/
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* @typedef {Object} RectsInfo Bounding rectangle information of the selection range.
|
|
18
|
-
* @property {number} rects.left - The left position of the selection.
|
|
19
|
-
* @property {number} rects.right - The right position of the selection.
|
|
20
|
-
* @property {number} rects.top - The top position of the selection.
|
|
21
|
-
* @property {number} rects.bottom - The bottom position of the selection.
|
|
22
|
-
* @property {boolean} [rects.noText] - Whether the selection contains text.
|
|
23
|
-
* @property {number} [rects.width] - The width of the selection.
|
|
24
|
-
* @property {number} [rects.height] - The height of the selection.
|
|
25
|
-
*/
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* @typedef {Object} OffsetInfo
|
|
29
|
-
* @property {number} top - The top position of the node relative to the entire document, including iframe offsets.
|
|
30
|
-
* @property {number} left - The left position of the node relative to the entire document, including iframe offsets.
|
|
31
|
-
*/
|
|
32
|
-
|
|
33
|
-
/**
|
|
34
|
-
* @typedef {Object} OffsetLocalInfo
|
|
35
|
-
* @property {number} top - The top position of the node relative to the WYSIWYG editor.
|
|
36
|
-
* @property {number} left - The left position of the node relative to the WYSIWYG editor.
|
|
37
|
-
* @property {number} right - The right position of the node relative to the WYSIWYG editor.
|
|
38
|
-
* @property {number} scrollX - The horizontal scroll offset inside the WYSIWYG editor.
|
|
39
|
-
* @property {number} scrollY - The vertical scroll offset inside the WYSIWYG editor.
|
|
40
|
-
*/
|
|
41
|
-
|
|
42
|
-
/**
|
|
43
|
-
* @typedef {Object} OffsetGlobalInfo
|
|
44
|
-
* @property {number} top - The top position of the element relative to the entire document.
|
|
45
|
-
* @property {number} left - The left position of the element relative to the entire document.
|
|
46
|
-
* @property {number}
|
|
47
|
-
* @property {number}
|
|
48
|
-
* @property {number}
|
|
49
|
-
* @property {number}
|
|
50
|
-
*/
|
|
51
|
-
|
|
52
|
-
/**
|
|
53
|
-
* @typedef {Object} OffsetGlobalScrollInfo
|
|
54
|
-
* @property {number} top - Total top scroll distance
|
|
55
|
-
* @property {number} left - Total left scroll distance
|
|
56
|
-
* @property {number} width - Total width including scrollable area
|
|
57
|
-
* @property {number} height - Total height including scrollable area
|
|
58
|
-
* @property {number} x - Horizontal offset from the top reference element
|
|
59
|
-
* @property {number} y - Vertical offset from the top reference element
|
|
60
|
-
* @property {HTMLElement|Window|null} ohOffsetEl - Element or window used as the vertical scroll reference
|
|
61
|
-
* @property {HTMLElement|Window|null} owOffsetEl - Element or window used as the horizontal scroll reference
|
|
62
|
-
* @property {number} oh - Height of the vertical scrollable area (clientHeight)
|
|
63
|
-
* @property {number} ow - Width of the horizontal scrollable area (clientWidth)
|
|
64
|
-
* @property {boolean} heightEditorRefer - Indicates if the vertical scroll reference is the editor area
|
|
65
|
-
* @property {boolean} widthEditorRefer - Indicates if the horizontal scroll reference is the editor area
|
|
66
|
-
* @property {number} ts - Top position of the height offset element relative to the viewport
|
|
67
|
-
* @property {number} ls - Left position of the width offset element relative to the viewport
|
|
68
|
-
*/
|
|
69
|
-
|
|
70
|
-
/**
|
|
71
|
-
* @typedef {Object} OffsetWWScrollInfo
|
|
72
|
-
* @property {number} top - The top scroll offset inside the WYSIWYG editor.
|
|
73
|
-
* @property {number} left - The left scroll offset inside the WYSIWYG editor.
|
|
74
|
-
* @property {number} width - The total width of the WYSIWYG editor's scrollable area.
|
|
75
|
-
* @property {number} height - The total height of the WYSIWYG editor's scrollable area.
|
|
76
|
-
* @property {number} bottom - The sum of `top` and `height`, representing the bottom-most scrollable position.
|
|
77
|
-
* @property {RectsInfo} rects - The bounding rectangle of the editor's visible area.
|
|
78
|
-
*/
|
|
79
|
-
|
|
80
|
-
/**
|
|
81
|
-
* @constructor
|
|
82
|
-
* @this {OffsetThis}
|
|
83
|
-
* @description Offset class, get the position of the element
|
|
84
|
-
* @param {__se__EditorCore} editor - The root editor instance
|
|
85
|
-
*/
|
|
86
|
-
function Offset(editor) {
|
|
87
|
-
CoreInjector.call(this, editor);
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
if (el.
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
}
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
}
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
}
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
const
|
|
465
|
-
|
|
466
|
-
const
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
const
|
|
473
|
-
const
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
const
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
const
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
//
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
}
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
element.
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
const
|
|
530
|
-
|
|
531
|
-
const
|
|
532
|
-
const
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
rml =
|
|
539
|
-
rmr =
|
|
540
|
-
}
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
let
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
* @
|
|
599
|
-
*
|
|
600
|
-
* @param {
|
|
601
|
-
* @param {
|
|
602
|
-
*
|
|
603
|
-
* @
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
const
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
const
|
|
619
|
-
const
|
|
620
|
-
const
|
|
621
|
-
const
|
|
622
|
-
const
|
|
623
|
-
const
|
|
624
|
-
const
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
const
|
|
641
|
-
const
|
|
642
|
-
const
|
|
643
|
-
const
|
|
644
|
-
|
|
645
|
-
const
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
*
|
|
660
|
-
*
|
|
661
|
-
* @
|
|
662
|
-
*
|
|
663
|
-
*
|
|
664
|
-
* @param {
|
|
665
|
-
* @param {
|
|
666
|
-
* @param {
|
|
667
|
-
* @param {number}
|
|
668
|
-
* @param {number}
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
const
|
|
675
|
-
const
|
|
676
|
-
|
|
677
|
-
const
|
|
678
|
-
const
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
const
|
|
682
|
-
|
|
683
|
-
let
|
|
684
|
-
const
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
if (
|
|
689
|
-
isDirTop =
|
|
690
|
-
resetTop = true;
|
|
691
|
-
}
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
removeClass(arrow, 'se-arrow-
|
|
703
|
-
addClass(arrow, 'se-arrow-
|
|
704
|
-
}
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
* @
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
*
|
|
726
|
-
*
|
|
727
|
-
* @
|
|
728
|
-
*
|
|
729
|
-
*
|
|
730
|
-
* @param {number
|
|
731
|
-
* @param {
|
|
732
|
-
* @param {
|
|
733
|
-
* @param {
|
|
734
|
-
* @
|
|
735
|
-
*
|
|
736
|
-
*
|
|
737
|
-
*
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
let
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
const
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
const
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
}
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
*
|
|
799
|
-
* @
|
|
800
|
-
* @
|
|
801
|
-
* -
|
|
802
|
-
* -
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
if (arrow) arrow.style.visibility = '';
|
|
811
|
-
addClass(arrow, 'se-arrow-
|
|
812
|
-
removeClass(arrow, 'se-arrow-
|
|
813
|
-
} else {
|
|
814
|
-
if (arrow) arrow.style.visibility = '
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
* @
|
|
824
|
-
*
|
|
825
|
-
*
|
|
826
|
-
*
|
|
827
|
-
*
|
|
828
|
-
*
|
|
829
|
-
*
|
|
830
|
-
*
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
this._scrollEvent = this.editor.eventManager.removeGlobalEvent(this._scrollEvent);
|
|
860
|
-
this._scrollY = 0;
|
|
861
|
-
this._elTop = null;
|
|
862
|
-
}
|
|
863
|
-
},
|
|
864
|
-
|
|
865
|
-
constructor: Offset
|
|
866
|
-
};
|
|
867
|
-
|
|
868
|
-
/**
|
|
869
|
-
* @private
|
|
870
|
-
* @this {OffsetThis}
|
|
871
|
-
* @param {HTMLElement} element - The element to check for a specific class name.
|
|
872
|
-
* @param {HTMLElement} e_container - The root container of the element.
|
|
873
|
-
* @param {HTMLElement} target - The target element to position against.
|
|
874
|
-
* @param {HTMLElement} t_container - The root container of the target element.
|
|
875
|
-
*/
|
|
876
|
-
function FixedScroll(element, e_container, target, t_container) {
|
|
877
|
-
const isFixed = /^fixed$/i.test(_w.getComputedStyle(t_container).position);
|
|
878
|
-
if (!this._isFixed) {
|
|
879
|
-
if (isFixed) {
|
|
880
|
-
this.setRelPosition(element, e_container, target, t_container, true);
|
|
881
|
-
}
|
|
882
|
-
return;
|
|
883
|
-
} else if (!isFixed) {
|
|
884
|
-
this.setRelPosition(element, e_container, target, t_container, true);
|
|
885
|
-
return;
|
|
886
|
-
}
|
|
887
|
-
|
|
888
|
-
element.style.top = `${this._elTop - (this._scrollY - _w.scrollY - t_container.offsetTop)}px`;
|
|
889
|
-
}
|
|
890
|
-
|
|
891
|
-
export default Offset;
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Offset class
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import CoreInjector from '../../editorInjector/_core';
|
|
6
|
+
import { getParentElement } from '../../helper/dom/domQuery';
|
|
7
|
+
import { isWysiwygFrame, isElement } from '../../helper/dom/domCheck';
|
|
8
|
+
import { hasClass, addClass, removeClass, getClientSize } from '../../helper/dom/domUtils';
|
|
9
|
+
import { numbers } from '../../helper';
|
|
10
|
+
import { _w, _d } from '../../helper/env';
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* @typedef {Omit<Offset & Partial<__se__EditorInjector>, 'offset'>} OffsetThis
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* @typedef {Object} RectsInfo Bounding rectangle information of the selection range.
|
|
18
|
+
* @property {number} rects.left - The left position of the selection.
|
|
19
|
+
* @property {number} rects.right - The right position of the selection.
|
|
20
|
+
* @property {number} rects.top - The top position of the selection.
|
|
21
|
+
* @property {number} rects.bottom - The bottom position of the selection.
|
|
22
|
+
* @property {boolean} [rects.noText] - Whether the selection contains text.
|
|
23
|
+
* @property {number} [rects.width] - The width of the selection.
|
|
24
|
+
* @property {number} [rects.height] - The height of the selection.
|
|
25
|
+
*/
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* @typedef {Object} OffsetInfo
|
|
29
|
+
* @property {number} top - The top position of the node relative to the entire document, including iframe offsets.
|
|
30
|
+
* @property {number} left - The left position of the node relative to the entire document, including iframe offsets.
|
|
31
|
+
*/
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* @typedef {Object} OffsetLocalInfo
|
|
35
|
+
* @property {number} top - The top position of the node relative to the WYSIWYG editor.
|
|
36
|
+
* @property {number} left - The left position of the node relative to the WYSIWYG editor.
|
|
37
|
+
* @property {number} right - The right position of the node relative to the WYSIWYG editor.
|
|
38
|
+
* @property {number} scrollX - The horizontal scroll offset inside the WYSIWYG editor.
|
|
39
|
+
* @property {number} scrollY - The vertical scroll offset inside the WYSIWYG editor.
|
|
40
|
+
*/
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* @typedef {Object} OffsetGlobalInfo
|
|
44
|
+
* @property {number} top - The top position of the element relative to the entire document.
|
|
45
|
+
* @property {number} left - The left position of the element relative to the entire document.
|
|
46
|
+
* @property {number} fixedTop - The top position within the current viewport, without taking scrolling into account.
|
|
47
|
+
* @property {number} fixedLeft - The left position within the current viewport, without taking scrolling into account.
|
|
48
|
+
* @property {number} width - The total width of the element, including its content, padding, and border.
|
|
49
|
+
* @property {number} height - The total height of the element, including its content, padding, and border.
|
|
50
|
+
*/
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* @typedef {Object} OffsetGlobalScrollInfo
|
|
54
|
+
* @property {number} top - Total top scroll distance
|
|
55
|
+
* @property {number} left - Total left scroll distance
|
|
56
|
+
* @property {number} width - Total width including scrollable area
|
|
57
|
+
* @property {number} height - Total height including scrollable area
|
|
58
|
+
* @property {number} x - Horizontal offset from the top reference element
|
|
59
|
+
* @property {number} y - Vertical offset from the top reference element
|
|
60
|
+
* @property {HTMLElement|Window|null} ohOffsetEl - Element or window used as the vertical scroll reference
|
|
61
|
+
* @property {HTMLElement|Window|null} owOffsetEl - Element or window used as the horizontal scroll reference
|
|
62
|
+
* @property {number} oh - Height of the vertical scrollable area (clientHeight)
|
|
63
|
+
* @property {number} ow - Width of the horizontal scrollable area (clientWidth)
|
|
64
|
+
* @property {boolean} heightEditorRefer - Indicates if the vertical scroll reference is the editor area
|
|
65
|
+
* @property {boolean} widthEditorRefer - Indicates if the horizontal scroll reference is the editor area
|
|
66
|
+
* @property {number} ts - Top position of the height offset element relative to the viewport
|
|
67
|
+
* @property {number} ls - Left position of the width offset element relative to the viewport
|
|
68
|
+
*/
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* @typedef {Object} OffsetWWScrollInfo
|
|
72
|
+
* @property {number} top - The top scroll offset inside the WYSIWYG editor.
|
|
73
|
+
* @property {number} left - The left scroll offset inside the WYSIWYG editor.
|
|
74
|
+
* @property {number} width - The total width of the WYSIWYG editor's scrollable area.
|
|
75
|
+
* @property {number} height - The total height of the WYSIWYG editor's scrollable area.
|
|
76
|
+
* @property {number} bottom - The sum of `top` and `height`, representing the bottom-most scrollable position.
|
|
77
|
+
* @property {RectsInfo} rects - The bounding rectangle of the editor's visible area.
|
|
78
|
+
*/
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* @constructor
|
|
82
|
+
* @this {OffsetThis}
|
|
83
|
+
* @description Offset class, get the position of the element
|
|
84
|
+
* @param {__se__EditorCore} editor - The root editor instance
|
|
85
|
+
*/
|
|
86
|
+
function Offset(editor) {
|
|
87
|
+
CoreInjector.call(this, editor);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
Offset.prototype = {
|
|
91
|
+
/**
|
|
92
|
+
* @this {OffsetThis}
|
|
93
|
+
* @description Gets the position just outside the argument's internal editor (wysiwygFrame).
|
|
94
|
+
* @param {Node} node Target node.
|
|
95
|
+
* @returns {OffsetInfo} Position relative to the editor frame.
|
|
96
|
+
*/
|
|
97
|
+
get(node) {
|
|
98
|
+
const wFrame = this.editor.frameContext.get('wysiwygFrame');
|
|
99
|
+
const iframe = /iframe/i.test(wFrame?.nodeName);
|
|
100
|
+
const off = this.getLocal(node);
|
|
101
|
+
|
|
102
|
+
return {
|
|
103
|
+
left: off.left + (iframe ? wFrame.parentElement.offsetLeft : 0),
|
|
104
|
+
top: off.top + (iframe ? wFrame.parentElement.offsetTop : 0)
|
|
105
|
+
};
|
|
106
|
+
},
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* @this {OffsetThis}
|
|
110
|
+
* @description Gets the position inside the internal editor of the argument.
|
|
111
|
+
* @param {Node} node Target node.
|
|
112
|
+
* @returns {OffsetLocalInfo} Position relative to the WYSIWYG editor.
|
|
113
|
+
*/
|
|
114
|
+
getLocal(node) {
|
|
115
|
+
const target = /** @type {HTMLElement} */ (node);
|
|
116
|
+
let offsetLeft = 0;
|
|
117
|
+
let offsetTop = 0;
|
|
118
|
+
let l = 0;
|
|
119
|
+
let t = 0;
|
|
120
|
+
let r = 0;
|
|
121
|
+
let offsetElement = target.nodeType === 3 ? target.parentElement : target;
|
|
122
|
+
const targetWidth = target.offsetWidth;
|
|
123
|
+
const wysiwyg = getParentElement(target, isWysiwygFrame.bind(this));
|
|
124
|
+
const self = offsetElement;
|
|
125
|
+
|
|
126
|
+
while (offsetElement && !hasClass(offsetElement, 'se-wrapper') && offsetElement !== wysiwyg) {
|
|
127
|
+
offsetLeft += offsetElement.offsetLeft - (self !== offsetElement ? offsetElement.scrollLeft : 0);
|
|
128
|
+
offsetTop += offsetElement.offsetTop + (self !== offsetElement ? offsetElement.scrollTop : 0);
|
|
129
|
+
offsetElement = /** @type {HTMLElement} */ (offsetElement.offsetParent);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
const wwFrame = this.editor.frameContext.get('wysiwygFrame');
|
|
133
|
+
if (this.editor.frameContext.get('wysiwyg').contains(target)) {
|
|
134
|
+
l = wwFrame.offsetLeft;
|
|
135
|
+
t = wwFrame.offsetTop;
|
|
136
|
+
r = wwFrame.parentElement.offsetWidth - (wwFrame.offsetLeft + wwFrame.offsetWidth);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
const eventWysiwyg = this.editor.frameContext.get('eventWysiwyg');
|
|
140
|
+
offsetLeft += l;
|
|
141
|
+
offsetTop += t - (wysiwyg ? wysiwyg.scrollTop : 0);
|
|
142
|
+
return {
|
|
143
|
+
left: offsetLeft,
|
|
144
|
+
top: offsetTop,
|
|
145
|
+
right: offsetElement?.offsetWidth ? offsetElement.offsetWidth - (offsetLeft - l + targetWidth) + r : 0,
|
|
146
|
+
scrollX: eventWysiwyg.scrollLeft || eventWysiwyg.scrollX || 0,
|
|
147
|
+
scrollY: eventWysiwyg.scrollTop || eventWysiwyg.scrollY || 0
|
|
148
|
+
};
|
|
149
|
+
},
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* @this {OffsetThis}
|
|
153
|
+
* @description Returns the position of the argument relative to the global document.
|
|
154
|
+
* This is a refactored version using getBoundingClientRect for better performance and accuracy.
|
|
155
|
+
* @param {?Node=} node Target element.
|
|
156
|
+
* @returns {OffsetGlobalInfo} Global position and scroll values.
|
|
157
|
+
*/
|
|
158
|
+
getGlobal(node) {
|
|
159
|
+
const topArea = this.editor.frameContext.get('topArea');
|
|
160
|
+
const wFrame = this.editor.frameContext.get('wysiwygFrame');
|
|
161
|
+
|
|
162
|
+
node = node || topArea;
|
|
163
|
+
|
|
164
|
+
if (!isElement(node)) {
|
|
165
|
+
return { top: 0, left: 0, fixedTop: 0, fixedLeft: 0, width: 0, height: 0 };
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
const element = /** @type {HTMLElement} */ (node);
|
|
169
|
+
|
|
170
|
+
const rect = element.getBoundingClientRect();
|
|
171
|
+
|
|
172
|
+
let top = rect.top;
|
|
173
|
+
let left = rect.left;
|
|
174
|
+
|
|
175
|
+
const isIframe = /^iframe$/i.test(wFrame.nodeName);
|
|
176
|
+
if (isIframe && wFrame.contentDocument.contains(element)) {
|
|
177
|
+
const iframeRect = wFrame.getBoundingClientRect();
|
|
178
|
+
top += iframeRect.top;
|
|
179
|
+
left += iframeRect.left;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
let wy = 0;
|
|
183
|
+
let wx = 0;
|
|
184
|
+
if (!this.editor.frameContext.get('isFullScreen')) {
|
|
185
|
+
wy += _w.scrollY;
|
|
186
|
+
wx += _w.scrollX;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
return {
|
|
190
|
+
top: top + wy,
|
|
191
|
+
left: left + wx,
|
|
192
|
+
fixedTop: top,
|
|
193
|
+
fixedLeft: left,
|
|
194
|
+
width: element.offsetWidth,
|
|
195
|
+
height: element.offsetHeight
|
|
196
|
+
};
|
|
197
|
+
},
|
|
198
|
+
|
|
199
|
+
/**
|
|
200
|
+
* @this {OffsetThis}
|
|
201
|
+
* @description Gets the current editor-relative scroll offset.
|
|
202
|
+
* @param {?Node=} node Target element.
|
|
203
|
+
* @returns {OffsetGlobalScrollInfo} Global scroll information.
|
|
204
|
+
*/
|
|
205
|
+
getGlobalScroll(node) {
|
|
206
|
+
const topArea = this.editor.frameContext.get('topArea');
|
|
207
|
+
let isTop = false;
|
|
208
|
+
let targetAbs = false;
|
|
209
|
+
if (!node) node = topArea;
|
|
210
|
+
if (node === topArea) isTop = true;
|
|
211
|
+
if (!isTop && isElement(node)) {
|
|
212
|
+
targetAbs = _w.getComputedStyle(node).position === 'absolute';
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
const element = /** @type {HTMLElement} */ (node);
|
|
216
|
+
let t = 0,
|
|
217
|
+
l = 0,
|
|
218
|
+
h = 0,
|
|
219
|
+
w = 0,
|
|
220
|
+
x = 0,
|
|
221
|
+
y = 0,
|
|
222
|
+
oh = 0,
|
|
223
|
+
ow = 0,
|
|
224
|
+
ohOffsetEl = null,
|
|
225
|
+
owOffsetEl = null,
|
|
226
|
+
ohel = null,
|
|
227
|
+
owel = null,
|
|
228
|
+
el = element;
|
|
229
|
+
|
|
230
|
+
while (el) {
|
|
231
|
+
t += el.scrollTop;
|
|
232
|
+
l += el.scrollLeft;
|
|
233
|
+
h += el.scrollHeight;
|
|
234
|
+
w += el.scrollWidth;
|
|
235
|
+
if (el.scrollTop > 0) {
|
|
236
|
+
y += el.offsetTop;
|
|
237
|
+
}
|
|
238
|
+
if (el.scrollHeight > el.clientHeight) {
|
|
239
|
+
oh = /^html$/i.test(el.nodeName) ? oh || el.clientHeight : el.clientHeight + (ohel ? -ohel.clientTop : 0);
|
|
240
|
+
ohOffsetEl = ohel || ohOffsetEl || el;
|
|
241
|
+
ohel = el;
|
|
242
|
+
}
|
|
243
|
+
if (el.scrollLeft > 0) {
|
|
244
|
+
x += el.offsetLeft;
|
|
245
|
+
}
|
|
246
|
+
if (el.scrollWidth > el.clientWidth) {
|
|
247
|
+
ow = /^html$/i.test(el.nodeName) ? ow || el.clientWidth : el.clientWidth + (owel ? -owel.clientLeft : 0);
|
|
248
|
+
owOffsetEl = owel || owOffsetEl || el;
|
|
249
|
+
owel = el;
|
|
250
|
+
}
|
|
251
|
+
el = el.parentElement;
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
if (!targetAbs && !isTop && /^iframe$/i.test(this.editor.frameContext.get('wysiwygFrame').nodeName)) {
|
|
255
|
+
el = this.editor.frameContext.get('wrapper');
|
|
256
|
+
ohOffsetEl = owOffsetEl = topArea;
|
|
257
|
+
while (el) {
|
|
258
|
+
t += el.scrollTop;
|
|
259
|
+
l += el.scrollLeft;
|
|
260
|
+
h += el.scrollHeight;
|
|
261
|
+
w += el.scrollWidth;
|
|
262
|
+
if (el.scrollTop > 0) {
|
|
263
|
+
y += el.offsetTop;
|
|
264
|
+
}
|
|
265
|
+
if (el.scrollHeight > el.clientHeight) {
|
|
266
|
+
oh = /^html$/i.test(el.nodeName) ? oh || el.clientHeight : el.clientHeight + (ohel ? -ohel.clientTop : 0);
|
|
267
|
+
ohel = el;
|
|
268
|
+
}
|
|
269
|
+
if (el.scrollLeft > 0) {
|
|
270
|
+
x += el.offsetLeft;
|
|
271
|
+
}
|
|
272
|
+
if (el.scrollWidth > el.clientWidth) {
|
|
273
|
+
ow = /^html$/i.test(el.nodeName) ? ow || el.clientWidth : el.clientWidth + (owel ? -owel.clientLeft : 0);
|
|
274
|
+
owel = el;
|
|
275
|
+
}
|
|
276
|
+
el = el.parentElement;
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
el = /** @type {HTMLElement} */ (this.editor._shadowRoot?.host);
|
|
281
|
+
if (el) ohOffsetEl = owOffsetEl = topArea;
|
|
282
|
+
while (el) {
|
|
283
|
+
t += el.scrollTop;
|
|
284
|
+
l += el.scrollLeft;
|
|
285
|
+
h += el.scrollHeight;
|
|
286
|
+
w += el.scrollWidth;
|
|
287
|
+
if (el.scrollTop > 0) {
|
|
288
|
+
y += el.offsetTop;
|
|
289
|
+
}
|
|
290
|
+
if (el.scrollHeight > el.clientHeight) {
|
|
291
|
+
oh = /^html$/i.test(el.nodeName) ? oh || el.clientHeight : el.clientHeight + (ohel ? -ohel.clientTop : 0);
|
|
292
|
+
ohel = el;
|
|
293
|
+
}
|
|
294
|
+
if (el.scrollLeft > 0) {
|
|
295
|
+
x += el.offsetLeft;
|
|
296
|
+
}
|
|
297
|
+
if (el.scrollWidth > el.clientWidth) {
|
|
298
|
+
ow = /^html$/i.test(el.nodeName) ? ow || el.clientWidth : el.clientWidth + (owel ? -owel.clientLeft : 0);
|
|
299
|
+
owel = el;
|
|
300
|
+
}
|
|
301
|
+
el = el.parentElement;
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
const heightEditorRefer = topArea.contains(ohOffsetEl);
|
|
305
|
+
const widthEditorRefer = topArea.contains(owOffsetEl);
|
|
306
|
+
ohOffsetEl = heightEditorRefer ? topArea : ohOffsetEl;
|
|
307
|
+
owOffsetEl = widthEditorRefer ? topArea : owOffsetEl;
|
|
308
|
+
const ts = !ohOffsetEl ? 0 : ohOffsetEl.getBoundingClientRect().top + (!ohOffsetEl.parentElement || /^html$/i.test(ohOffsetEl.parentElement.nodeName) ? _w.scrollY : 0);
|
|
309
|
+
const ls = !owOffsetEl ? 0 : owOffsetEl.getBoundingClientRect().left + (!owOffsetEl.parentElement || /^html$/i.test(owOffsetEl.parentElement.nodeName) ? _w.scrollX : 0);
|
|
310
|
+
|
|
311
|
+
oh = heightEditorRefer ? topArea.clientHeight : oh;
|
|
312
|
+
ow = widthEditorRefer ? topArea.clientWidth : ow;
|
|
313
|
+
|
|
314
|
+
const clientSize = getClientSize(this.editor.frameContext.get('_wd'));
|
|
315
|
+
return {
|
|
316
|
+
top: t,
|
|
317
|
+
left: l,
|
|
318
|
+
ts: ts,
|
|
319
|
+
ls: ls,
|
|
320
|
+
width: w,
|
|
321
|
+
height: h,
|
|
322
|
+
x: x,
|
|
323
|
+
y: y,
|
|
324
|
+
ohOffsetEl: targetAbs ? window : ohOffsetEl,
|
|
325
|
+
owOffsetEl: targetAbs ? window : owOffsetEl,
|
|
326
|
+
oh: targetAbs ? clientSize.h : oh,
|
|
327
|
+
ow: targetAbs ? clientSize.w : ow,
|
|
328
|
+
heightEditorRefer: heightEditorRefer,
|
|
329
|
+
widthEditorRefer: widthEditorRefer
|
|
330
|
+
};
|
|
331
|
+
},
|
|
332
|
+
|
|
333
|
+
/**
|
|
334
|
+
* @this {OffsetThis}
|
|
335
|
+
* @description Get the scroll info of the WYSIWYG area.
|
|
336
|
+
* @returns {OffsetWWScrollInfo} Scroll information within the editor.
|
|
337
|
+
*/
|
|
338
|
+
getWWScroll() {
|
|
339
|
+
const eventWysiwyg = this.editor.frameContext.get('wysiwyg');
|
|
340
|
+
const rects = this.selection.getRects(eventWysiwyg, 'start').rects;
|
|
341
|
+
const top = eventWysiwyg.scrollTop || eventWysiwyg.scrollY || 0;
|
|
342
|
+
const height = eventWysiwyg.scrollHeight || eventWysiwyg.document?.documentElement.scrollHeight || 0;
|
|
343
|
+
|
|
344
|
+
return {
|
|
345
|
+
top,
|
|
346
|
+
left: eventWysiwyg.scrollLeft || eventWysiwyg.scrollX || 0,
|
|
347
|
+
width: eventWysiwyg.scrollWidth || eventWysiwyg.document?.documentElement.scrollWidth || 0,
|
|
348
|
+
height,
|
|
349
|
+
bottom: top + height,
|
|
350
|
+
rects
|
|
351
|
+
};
|
|
352
|
+
},
|
|
353
|
+
|
|
354
|
+
/**
|
|
355
|
+
* @this {OffsetThis}
|
|
356
|
+
* @description Sets the relative position of an element
|
|
357
|
+
* @param {HTMLElement} element Element to position
|
|
358
|
+
* @param {HTMLElement} e_container Element's root container
|
|
359
|
+
* @param {HTMLElement} target Target element to position against
|
|
360
|
+
* @param {HTMLElement} t_container Target's root container
|
|
361
|
+
*/
|
|
362
|
+
setRelPosition(element, e_container, target, t_container) {
|
|
363
|
+
const isFixedContainer = /^fixed$/i.test(_w.getComputedStyle(t_container).position);
|
|
364
|
+
const tGlobal = this.getGlobal(target);
|
|
365
|
+
|
|
366
|
+
if (isFixedContainer) {
|
|
367
|
+
element.style.position = 'fixed';
|
|
368
|
+
element.style.top = `${tGlobal.fixedTop + tGlobal.height}px`;
|
|
369
|
+
element.style.left = `${tGlobal.fixedLeft}px`;
|
|
370
|
+
} else {
|
|
371
|
+
element.style.position = '';
|
|
372
|
+
|
|
373
|
+
// top
|
|
374
|
+
const isSameContainer = t_container.contains(element);
|
|
375
|
+
const containerTop = isSameContainer ? this.getGlobal(e_container).top : 0;
|
|
376
|
+
const elHeight = element.offsetHeight;
|
|
377
|
+
const scrollTop = this.getGlobalScroll().top;
|
|
378
|
+
const bt = tGlobal.top;
|
|
379
|
+
|
|
380
|
+
const menuHeight_bottom = getClientSize(_d).h - (containerTop - scrollTop + bt + target.offsetHeight);
|
|
381
|
+
if (menuHeight_bottom < elHeight) {
|
|
382
|
+
let menuTop = -1 * (elHeight - bt + 3);
|
|
383
|
+
const insTop = containerTop - scrollTop + menuTop;
|
|
384
|
+
const menuHeight_top = elHeight + (insTop < 0 ? insTop : 0);
|
|
385
|
+
|
|
386
|
+
if (menuHeight_top > menuHeight_bottom) {
|
|
387
|
+
element.style.height = `${menuHeight_top}px`;
|
|
388
|
+
menuTop = -1 * (menuHeight_top - bt + 3);
|
|
389
|
+
} else {
|
|
390
|
+
element.style.height = `${menuHeight_bottom}px`;
|
|
391
|
+
menuTop = bt + target.offsetHeight;
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
element.style.top = `${menuTop}px`;
|
|
395
|
+
} else {
|
|
396
|
+
element.style.top = `${bt + target.offsetHeight}px`;
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
// left
|
|
400
|
+
const ew = element.offsetWidth;
|
|
401
|
+
const tw = target.offsetWidth;
|
|
402
|
+
const tl = tGlobal.left;
|
|
403
|
+
const tcleft = this.getGlobal(t_container).left;
|
|
404
|
+
|
|
405
|
+
if (this.options.get('_rtl')) {
|
|
406
|
+
const rtlW = ew > tw ? ew - tw : 0;
|
|
407
|
+
const rtlL = rtlW > 0 ? 0 : tw - ew;
|
|
408
|
+
element.style.left = `${tl - rtlW + rtlL + tcleft}px`;
|
|
409
|
+
if (tcleft > this.getGlobal(element).left) {
|
|
410
|
+
element.style.left = tcleft + 'px';
|
|
411
|
+
}
|
|
412
|
+
} else {
|
|
413
|
+
const cw = t_container.offsetWidth + tcleft;
|
|
414
|
+
const overLeft = cw <= ew ? 0 : cw - (tl + ew);
|
|
415
|
+
if (overLeft < 0) element.style.left = `${tl + overLeft + tcleft}px`;
|
|
416
|
+
else element.style.left = `${tl}px`;
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
},
|
|
420
|
+
|
|
421
|
+
/**
|
|
422
|
+
* @this {OffsetThis}
|
|
423
|
+
* @description Sets the absolute position of an element
|
|
424
|
+
* @param {HTMLElement} element Element to position
|
|
425
|
+
* @param {HTMLElement} target Target element
|
|
426
|
+
* @param {Object} params Position parameters
|
|
427
|
+
* @param {boolean} [params.isWWTarget=false] Whether the target is within the editor's WYSIWYG area
|
|
428
|
+
* @param {{left:number, top:number}} [params.addOffset={left:0, top:0}] Additional offset
|
|
429
|
+
* @param {"bottom"|"top"} [params.position="bottom"] Position ('bottom'|'top')
|
|
430
|
+
* @param {*} params.inst Instance object of caller
|
|
431
|
+
* @param {HTMLElement} [params.sibling] The sibling controller element
|
|
432
|
+
* @returns {{position: "top" | "bottom"} | undefined} Success -> {position: current position}
|
|
433
|
+
*/
|
|
434
|
+
setAbsPosition(element, target, params) {
|
|
435
|
+
const addOffset = {
|
|
436
|
+
left: 0,
|
|
437
|
+
top: 0,
|
|
438
|
+
...params.addOffset
|
|
439
|
+
};
|
|
440
|
+
const position = params.position || 'bottom';
|
|
441
|
+
const inst = params.inst;
|
|
442
|
+
const isLTR = !this.options.get('_rtl');
|
|
443
|
+
|
|
444
|
+
if (!isLTR) {
|
|
445
|
+
addOffset.left *= -1;
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
const isIframe = this.editor.frameOptions.get('iframe');
|
|
449
|
+
const isWWTarget = this.editor.frameContext.get('wrapper').contains(target) || params.isWWTarget || (isIframe ? this.editor.frameContext.get('wysiwyg').contains(target) : false);
|
|
450
|
+
|
|
451
|
+
const isCtrlTarget = target.nodeType === 1;
|
|
452
|
+
const isTargetAbs = isWWTarget && !isCtrlTarget;
|
|
453
|
+
const isInlineTarget = isCtrlTarget && /inline/.test(_w.getComputedStyle(target).display);
|
|
454
|
+
const clientSize = getClientSize(_d);
|
|
455
|
+
const wwScroll = isTargetAbs ? this.getWWScroll() : this._getWindowScroll();
|
|
456
|
+
const targetRect = !isIframe && isCtrlTarget ? target.getBoundingClientRect() : this.selection.getRects(target, 'start').rects;
|
|
457
|
+
const targetOffset = this.getGlobal(target);
|
|
458
|
+
const arrow = /** @type {HTMLElement} */ (hasClass(element.firstElementChild, 'se-arrow') ? element.firstElementChild : null);
|
|
459
|
+
|
|
460
|
+
// top ----------------------------------------------------------------------------------------------------
|
|
461
|
+
const siblingH = params.sibling?.offsetHeight || 0;
|
|
462
|
+
const ah = arrow ? arrow.offsetHeight : 0;
|
|
463
|
+
const elH = element.offsetHeight;
|
|
464
|
+
const targetH = target.offsetHeight;
|
|
465
|
+
// margin
|
|
466
|
+
const tmtw = targetRect.top;
|
|
467
|
+
const tmbw = clientSize.h - targetRect.bottom;
|
|
468
|
+
const globalTop = this.getGlobal(this.editor.frameContext.get('topArea')).top;
|
|
469
|
+
const wScrollY = _w.scrollY;
|
|
470
|
+
const th = this.context.get('toolbar.main').offsetHeight;
|
|
471
|
+
const containerToolbar = this.options.get('toolbar_container');
|
|
472
|
+
const headLess = this.editor.isBalloon || this.editor.isInline || containerToolbar;
|
|
473
|
+
const toolbarH = (containerToolbar && globalTop - wScrollY - th > 0) || (!this.editor.toolbar._sticky && headLess) ? 0 : th;
|
|
474
|
+
|
|
475
|
+
// check margin
|
|
476
|
+
const { rmt, rmb, bMargin, rt } = this._getVMargin(tmtw, tmbw, toolbarH, clientSize, targetRect, isTargetAbs, wwScroll);
|
|
477
|
+
if (isWWTarget && ((rmb > 0 ? bMargin : rmb) + targetH <= 0 || rmt + rt + targetH - (this.editor.toolbar._sticky && isInlineTarget ? toolbarH : 0) <= 0)) return;
|
|
478
|
+
|
|
479
|
+
const isSticky = this.editor.toolbar._sticky && this.context.get('toolbar.main').style.display !== 'none' && (!headLess || this.editor.frameContext.get('topArea').getBoundingClientRect().top <= th);
|
|
480
|
+
const statusBarH = this.editor.frameContext.get('statusbar')?.offsetHeight || 0;
|
|
481
|
+
let t = addOffset.top;
|
|
482
|
+
let y = 0;
|
|
483
|
+
let arrowDir = '';
|
|
484
|
+
|
|
485
|
+
// [bottom] position
|
|
486
|
+
if (position === 'bottom') {
|
|
487
|
+
let trmt = rmt - (isSticky && globalTop - wScrollY <= toolbarH ? toolbarH : 0);
|
|
488
|
+
if (isSticky && trmt + toolbarH < 0) trmt += toolbarH;
|
|
489
|
+
arrowDir = 'up';
|
|
490
|
+
t += targetRect.bottom + ah + wScrollY;
|
|
491
|
+
y = rmb - (elH + ah) - statusBarH;
|
|
492
|
+
// change to <top> position
|
|
493
|
+
if (y - siblingH < 0) {
|
|
494
|
+
arrowDir = 'down';
|
|
495
|
+
t -= targetH + elH + ah * 2;
|
|
496
|
+
y = trmt - (elH + ah);
|
|
497
|
+
// sticky the <top> position
|
|
498
|
+
if (y - siblingH < 0) {
|
|
499
|
+
arrowDir = '';
|
|
500
|
+
t -= y - siblingH - Math.max(1, y + elH + ah) + (!isSticky && trmt < 0 ? toolbarH : 0) - (isSticky ? this.context.get('toolbar.main').offsetTop : 0);
|
|
501
|
+
}
|
|
502
|
+
}
|
|
503
|
+
}
|
|
504
|
+
// <top> position
|
|
505
|
+
else {
|
|
506
|
+
arrowDir = 'down';
|
|
507
|
+
t += targetRect.top - elH - ah + wScrollY;
|
|
508
|
+
y = (isSticky ? targetRect.top - toolbarH : rmt) - elH - ah;
|
|
509
|
+
// change to [bottom] position
|
|
510
|
+
if (y - siblingH < 0) {
|
|
511
|
+
arrowDir = 'up';
|
|
512
|
+
t += targetH + elH + ah * 2;
|
|
513
|
+
y = (rmb > 0 ? bMargin : rmb) - (elH + ah) - statusBarH;
|
|
514
|
+
// sticky the [bottom] position
|
|
515
|
+
if (y - siblingH < 0) {
|
|
516
|
+
arrowDir = '';
|
|
517
|
+
t += y - 2;
|
|
518
|
+
}
|
|
519
|
+
}
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
this._setArrow(arrow, arrowDir);
|
|
523
|
+
element.style.top = `${t}px`;
|
|
524
|
+
|
|
525
|
+
// left ----------------------------------------------------------------------------------------------------
|
|
526
|
+
const radius = (element.nodeType === 1 ? numbers.get(_w.getComputedStyle(element).borderRadius) : 0) || 0;
|
|
527
|
+
const targetW = targetOffset.width;
|
|
528
|
+
const elW = element.offsetWidth;
|
|
529
|
+
const aw = arrow ? arrow.offsetWidth : 0;
|
|
530
|
+
// margin
|
|
531
|
+
const tmlw = targetRect.left;
|
|
532
|
+
const tmrw = clientSize.w - targetRect.right;
|
|
533
|
+
let rml, rmr;
|
|
534
|
+
if (this.editor.frameContext.get('isFullScreen')) {
|
|
535
|
+
rml = tmlw;
|
|
536
|
+
rmr = tmrw;
|
|
537
|
+
} else {
|
|
538
|
+
rml = targetRect.left;
|
|
539
|
+
rmr = clientSize.w - targetRect.right;
|
|
540
|
+
}
|
|
541
|
+
|
|
542
|
+
if (isWWTarget && (rml + targetW <= 0 || rmr + targetW <= 0)) return;
|
|
543
|
+
if (arrow) {
|
|
544
|
+
arrow.style.left = '';
|
|
545
|
+
arrow.style.right = '';
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
let l = addOffset.left;
|
|
549
|
+
let x = 0;
|
|
550
|
+
let ax = 0;
|
|
551
|
+
let awLimit = 0;
|
|
552
|
+
if (isLTR) {
|
|
553
|
+
l += targetRect.left + _w.scrollX - (rml < 0 ? rml : 0);
|
|
554
|
+
x = targetW + rml;
|
|
555
|
+
if (x < aw) {
|
|
556
|
+
awLimit = aw / 2 - 1 + (radius <= 2 ? 0 : radius - 2);
|
|
557
|
+
ax = awLimit;
|
|
558
|
+
}
|
|
559
|
+
x = targetW + rmr - elW;
|
|
560
|
+
if (x < 0) {
|
|
561
|
+
l += x;
|
|
562
|
+
awLimit = elW - 1 - (aw / 2 + (radius <= 2 ? 0 : radius - 2));
|
|
563
|
+
ax = -(x - aw / 2);
|
|
564
|
+
ax = ax > awLimit ? awLimit : ax;
|
|
565
|
+
}
|
|
566
|
+
if (arrow && ax > 0) arrow.style.left = ax + 'px';
|
|
567
|
+
} else {
|
|
568
|
+
l += targetRect.right - elW + _w.scrollX + (rmr < 0 ? rmr : 0);
|
|
569
|
+
x = targetW + rmr;
|
|
570
|
+
if (x < aw) {
|
|
571
|
+
awLimit = aw / 2 - 1 + (radius <= 2 ? 0 : radius - 2);
|
|
572
|
+
ax = awLimit;
|
|
573
|
+
}
|
|
574
|
+
x = targetW + rml - elW;
|
|
575
|
+
if (x < 0) {
|
|
576
|
+
l -= x;
|
|
577
|
+
awLimit = aw / 2 - 1 + (radius <= 2 ? 0 : radius - 2);
|
|
578
|
+
ax = -(x - aw / 2);
|
|
579
|
+
ax = ax < awLimit ? awLimit : ax > elW - awLimit ? elW - awLimit : ax;
|
|
580
|
+
}
|
|
581
|
+
if (arrow && ax > 0) arrow.style.right = ax + 'px';
|
|
582
|
+
}
|
|
583
|
+
|
|
584
|
+
element.style.left = `${l}px`;
|
|
585
|
+
inst.__offset = {
|
|
586
|
+
left: element.offsetLeft + wwScroll.left,
|
|
587
|
+
top: element.offsetTop + wwScroll.top,
|
|
588
|
+
addOffset: addOffset
|
|
589
|
+
};
|
|
590
|
+
|
|
591
|
+
return { position: arrowDir === 'up' ? 'bottom' : 'top' };
|
|
592
|
+
},
|
|
593
|
+
|
|
594
|
+
/**
|
|
595
|
+
* @this {OffsetThis}
|
|
596
|
+
* @description Sets the position of an element relative to a range
|
|
597
|
+
* @param {HTMLElement} element Element to position
|
|
598
|
+
* @param {?Range} range Range to position against.
|
|
599
|
+
* - if null, the current selection range is used
|
|
600
|
+
* @param {Object} [options={}] Position options
|
|
601
|
+
* @param {"bottom"|"top"} [options.position="bottom"] Position ('bottom'|'top')
|
|
602
|
+
* @param {number} [options.addTop=0] Additional top offset
|
|
603
|
+
* @returns {boolean} Success / Failure
|
|
604
|
+
*/
|
|
605
|
+
setRangePosition(element, range, { position, addTop } = {}) {
|
|
606
|
+
element.style.top = '-10000px';
|
|
607
|
+
element.style.visibility = 'hidden';
|
|
608
|
+
element.style.display = 'block';
|
|
609
|
+
|
|
610
|
+
let positionTop = position === 'top';
|
|
611
|
+
range = range || this.selection.getRange();
|
|
612
|
+
const rectsObj = this.selection.getRects(range, positionTop ? 'start' : 'end');
|
|
613
|
+
positionTop = rectsObj.position === 'start';
|
|
614
|
+
|
|
615
|
+
const isFullScreen = this.editor.frameContext.get('isFullScreen');
|
|
616
|
+
const topArea = this.editor.frameContext.get('topArea');
|
|
617
|
+
const rects = rectsObj.rects;
|
|
618
|
+
const scrollLeft = isFullScreen ? 0 : rectsObj.scrollLeft;
|
|
619
|
+
const scrollTop = isFullScreen ? 0 : rectsObj.scrollTop;
|
|
620
|
+
const editorWidth = topArea.offsetWidth;
|
|
621
|
+
const offsets = this.getGlobal(topArea);
|
|
622
|
+
const editorLeft = offsets.left;
|
|
623
|
+
const toolbarWidth = element.offsetWidth;
|
|
624
|
+
const toolbarHeight = element.offsetHeight;
|
|
625
|
+
|
|
626
|
+
this._setOffsetOnRange(positionTop, rects, element, editorLeft, editorWidth, scrollLeft, scrollTop, addTop);
|
|
627
|
+
if (this.getGlobal(element).top - offsets.top < 0) {
|
|
628
|
+
positionTop = !positionTop;
|
|
629
|
+
this._setOffsetOnRange(positionTop, rects, element, editorLeft, editorWidth, scrollLeft, scrollTop, addTop);
|
|
630
|
+
}
|
|
631
|
+
|
|
632
|
+
if (toolbarWidth !== element.offsetWidth || toolbarHeight !== element.offsetHeight) {
|
|
633
|
+
this._setOffsetOnRange(positionTop, rects, element, editorLeft, editorWidth, scrollLeft, scrollTop, addTop);
|
|
634
|
+
}
|
|
635
|
+
|
|
636
|
+
// check margin
|
|
637
|
+
const isTargetAbs = !this.carrierWrapper.contains(element);
|
|
638
|
+
const clientSize = getClientSize(_d);
|
|
639
|
+
const wwScroll = isTargetAbs ? this.getWWScroll() : this._getWindowScroll();
|
|
640
|
+
const targetH = rects.height;
|
|
641
|
+
const tmtw = rects.top;
|
|
642
|
+
const tmbw = clientSize.h - rects.bottom;
|
|
643
|
+
const toolbarH = !this.editor.toolbar._sticky && (this.editor.isBalloon || this.editor.isInline) ? 0 : this.context.get('toolbar.main').offsetHeight;
|
|
644
|
+
|
|
645
|
+
const { rmt, rmb, rt } = this._getVMargin(tmtw, tmbw, toolbarH, clientSize, rects, isTargetAbs, wwScroll);
|
|
646
|
+
if (rmb + targetH <= 0 || rmt + rt + targetH <= 0) return;
|
|
647
|
+
|
|
648
|
+
_w.setTimeout(() => {
|
|
649
|
+
element.style.visibility = '';
|
|
650
|
+
}, 0);
|
|
651
|
+
|
|
652
|
+
return true;
|
|
653
|
+
},
|
|
654
|
+
|
|
655
|
+
/**
|
|
656
|
+
* @private
|
|
657
|
+
* @this {OffsetThis}
|
|
658
|
+
* @description Sets the position of an element relative to the selection range in the editor.
|
|
659
|
+
* - This method calculates the top and left offsets for the element, ensuring it
|
|
660
|
+
* - does not overflow the editor boundaries and adjusts the arrow positioning accordingly.
|
|
661
|
+
* @param {boolean} isDirTop - Determines whether the element should be positioned above (`true`) or below (`false`) the target.
|
|
662
|
+
* @param {RectsInfo} rects - Bounding rectangle information of the selection range.
|
|
663
|
+
* @param {HTMLElement} element - The element to be positioned.
|
|
664
|
+
* @param {number} editorLeft - The left position of the editor.
|
|
665
|
+
* @param {number} editorWidth - The width of the editor.
|
|
666
|
+
* @param {number} scrollLeft - The horizontal scroll offset.
|
|
667
|
+
* @param {number} scrollTop - The vertical scroll offset.
|
|
668
|
+
* @param {number} [addTop=0] - Additional top margin adjustment.
|
|
669
|
+
*/
|
|
670
|
+
_setOffsetOnRange(isDirTop, rects, element, editorLeft, editorWidth, scrollLeft, scrollTop, addTop = 0) {
|
|
671
|
+
const padding = 1;
|
|
672
|
+
const arrow = /** @type {HTMLElement} */ (element.querySelector('.se-arrow '));
|
|
673
|
+
const arrowMargin = Math.round(arrow.offsetWidth / 2);
|
|
674
|
+
const elW = element.offsetWidth;
|
|
675
|
+
const elH = rects.noText && !isDirTop ? 0 : element.offsetHeight;
|
|
676
|
+
|
|
677
|
+
const absoluteLeft = (isDirTop ? rects.left : rects.right) - editorLeft - elW / 2 + scrollLeft;
|
|
678
|
+
const overRight = absoluteLeft + elW - editorWidth;
|
|
679
|
+
|
|
680
|
+
let t = (isDirTop ? rects.top - elH - arrowMargin : rects.bottom + arrowMargin) - (rects.noText ? 0 : addTop) + scrollTop;
|
|
681
|
+
const l = absoluteLeft < 0 ? padding : overRight < 0 ? absoluteLeft : absoluteLeft - overRight - padding - 1;
|
|
682
|
+
|
|
683
|
+
let resetTop = false;
|
|
684
|
+
const space = t + (isDirTop ? this.getGlobal(this.editor.frameContext.get('topArea')).top : element.offsetHeight - this.editor.frameContext.get('wysiwyg').offsetHeight);
|
|
685
|
+
if (!isDirTop && space > 0 && this._getPageBottomSpace() < space) {
|
|
686
|
+
isDirTop = true;
|
|
687
|
+
resetTop = true;
|
|
688
|
+
} else if (isDirTop && _d.documentElement.offsetTop > space) {
|
|
689
|
+
isDirTop = false;
|
|
690
|
+
resetTop = true;
|
|
691
|
+
}
|
|
692
|
+
|
|
693
|
+
if (resetTop) t = (isDirTop ? rects.top - elH - arrowMargin : rects.bottom + arrowMargin) - (rects.noText ? 0 : addTop) + scrollTop;
|
|
694
|
+
|
|
695
|
+
element.style.left = Math.floor(l) + 'px';
|
|
696
|
+
element.style.top = Math.floor(t) + 'px';
|
|
697
|
+
|
|
698
|
+
if (isDirTop) {
|
|
699
|
+
removeClass(arrow, 'se-arrow-up');
|
|
700
|
+
addClass(arrow, 'se-arrow-down');
|
|
701
|
+
} else {
|
|
702
|
+
removeClass(arrow, 'se-arrow-down');
|
|
703
|
+
addClass(arrow, 'se-arrow-up');
|
|
704
|
+
}
|
|
705
|
+
|
|
706
|
+
const arrow_left = Math.floor(elW / 2 + (absoluteLeft - l));
|
|
707
|
+
arrow.style.left = (arrow_left + arrowMargin > element.offsetWidth ? element.offsetWidth - arrowMargin : arrow_left < arrowMargin ? arrowMargin : arrow_left) + 'px';
|
|
708
|
+
},
|
|
709
|
+
|
|
710
|
+
/**
|
|
711
|
+
* @private
|
|
712
|
+
* @this {OffsetThis}
|
|
713
|
+
* @description Get available space from page bottom
|
|
714
|
+
* @returns {number} Available space
|
|
715
|
+
*/
|
|
716
|
+
_getPageBottomSpace() {
|
|
717
|
+
const topArea = this.editor.frameContext.get('topArea');
|
|
718
|
+
return _d.documentElement.scrollHeight - (this.getGlobal(topArea).top + topArea.offsetHeight);
|
|
719
|
+
},
|
|
720
|
+
|
|
721
|
+
/**
|
|
722
|
+
* @private
|
|
723
|
+
* @this {OffsetThis}
|
|
724
|
+
* @description Calculates the vertical margin offsets for the target element relative to the editor frame.
|
|
725
|
+
* - This method determines the top and bottom margins based on various conditions such as
|
|
726
|
+
* - fullscreen mode, iframe usage, toolbar height, and scroll positions.
|
|
727
|
+
* @param {number} tmtw Top margin to window
|
|
728
|
+
* @param {number} tmbw Bottom margin to window
|
|
729
|
+
* @param {number} toolbarH Toolbar height
|
|
730
|
+
* @param {{w: number, h: number}} clientSize documentElement.clientWidth, documentElement.clientHeight
|
|
731
|
+
* @param {RectsInfo} targetRect Target rect object
|
|
732
|
+
* @param {boolean} isTargetAbs Is target absolute position
|
|
733
|
+
* @param {OffsetWWScrollInfo} wwScroll WYSIWYG scroll info
|
|
734
|
+
* @returns {{rmt:number, rmb:number, rt:number, tMargin:number, bMargin:number}} Margin values
|
|
735
|
+
* - rmt: top margin to frame
|
|
736
|
+
* - rmb: bottom margin to frame
|
|
737
|
+
* - rt: Toolbar height offset adjustment
|
|
738
|
+
* - tMargin: top margin
|
|
739
|
+
* - bMargin: bottom margin
|
|
740
|
+
*/
|
|
741
|
+
_getVMargin(tmtw, tmbw, toolbarH, clientSize, targetRect, isTargetAbs, wwScroll) {
|
|
742
|
+
let rmt = 0;
|
|
743
|
+
let rmb = 0;
|
|
744
|
+
let rt = 0;
|
|
745
|
+
let tMargin = 0;
|
|
746
|
+
let bMargin = 0;
|
|
747
|
+
|
|
748
|
+
if (this.editor.frameContext.get('isFullScreen')) {
|
|
749
|
+
rmt = tmtw - toolbarH;
|
|
750
|
+
rmb = tmbw;
|
|
751
|
+
} else {
|
|
752
|
+
const isIframeAbs = isTargetAbs && this.editor.frameOptions.get('iframe');
|
|
753
|
+
tMargin = targetRect.top;
|
|
754
|
+
bMargin = clientSize.h - targetRect.bottom;
|
|
755
|
+
const editorOffset = this.getGlobal();
|
|
756
|
+
const editorScroll = this.getGlobalScroll();
|
|
757
|
+
const statusBarH = this.editor.frameContext.get('statusbar')?.offsetHeight || 0;
|
|
758
|
+
|
|
759
|
+
if (isIframeAbs) {
|
|
760
|
+
const emt = editorOffset.top - editorScroll.top - editorScroll.ts;
|
|
761
|
+
const editorH = this.editor.frameContext.get('topArea').offsetHeight;
|
|
762
|
+
rmt = targetRect.top - emt;
|
|
763
|
+
rmb = bMargin - (editorScroll.oh - (editorH + emt) + statusBarH);
|
|
764
|
+
} else {
|
|
765
|
+
rt = !this.editor.toolbar._sticky && !this.options.get('toolbar_container') ? toolbarH : 0;
|
|
766
|
+
const wst = !isTargetAbs && /\d+/.test(this.editor.frameOptions.get('height')) ? editorOffset.top - _w.scrollY + rt : 0;
|
|
767
|
+
const wsb = !isTargetAbs && /\d+/.test(this.editor.frameOptions.get('height')) ? this.status.currentViewportHeight - (editorOffset.top + editorOffset.height - _w.scrollY) : 0;
|
|
768
|
+
let st = wst;
|
|
769
|
+
if (toolbarH > wst) {
|
|
770
|
+
if (this.editor.toolbar._sticky) {
|
|
771
|
+
st = toolbarH;
|
|
772
|
+
} else {
|
|
773
|
+
st = wst + toolbarH;
|
|
774
|
+
}
|
|
775
|
+
} else if (this.options.get('toolbar_container') && !this.editor.toolbar._sticky) {
|
|
776
|
+
toolbarH = 0;
|
|
777
|
+
} else {
|
|
778
|
+
st = wst + toolbarH;
|
|
779
|
+
}
|
|
780
|
+
|
|
781
|
+
rmt = targetRect.top - wwScroll.rects.top - st + toolbarH;
|
|
782
|
+
rmb = wwScroll.rects.bottom - targetRect.bottom - wsb;
|
|
783
|
+
// display margin
|
|
784
|
+
rmt = rmt > 0 ? rmt : rmt - toolbarH;
|
|
785
|
+
}
|
|
786
|
+
}
|
|
787
|
+
|
|
788
|
+
return {
|
|
789
|
+
rmt,
|
|
790
|
+
rmb,
|
|
791
|
+
rt,
|
|
792
|
+
tMargin,
|
|
793
|
+
bMargin
|
|
794
|
+
};
|
|
795
|
+
},
|
|
796
|
+
|
|
797
|
+
/**
|
|
798
|
+
* @private
|
|
799
|
+
* @this {OffsetThis}
|
|
800
|
+
* @description Sets the visibility and direction of the arrow element.
|
|
801
|
+
* - This method applies the appropriate class (`se-arrow-up` or `se-arrow-down`)
|
|
802
|
+
* - based on the specified direction key and adjusts the visibility of the arrow.
|
|
803
|
+
* @param {HTMLElement} arrow - The arrow element to be updated.
|
|
804
|
+
* @param {string} key - The direction of the arrow. ("up"|"down"|"")
|
|
805
|
+
* - Accepts `'up'` for an upward arrow, `'down'` for a downward arrow,
|
|
806
|
+
* - or any other value to hide the arrow.
|
|
807
|
+
*/
|
|
808
|
+
_setArrow(arrow, key) {
|
|
809
|
+
if (key === 'up') {
|
|
810
|
+
if (arrow) arrow.style.visibility = '';
|
|
811
|
+
addClass(arrow, 'se-arrow-up');
|
|
812
|
+
removeClass(arrow, 'se-arrow-down');
|
|
813
|
+
} else if (key === 'down') {
|
|
814
|
+
if (arrow) arrow.style.visibility = '';
|
|
815
|
+
addClass(arrow, 'se-arrow-down');
|
|
816
|
+
removeClass(arrow, 'se-arrow-up');
|
|
817
|
+
} else {
|
|
818
|
+
if (arrow) arrow.style.visibility = 'hidden';
|
|
819
|
+
}
|
|
820
|
+
},
|
|
821
|
+
|
|
822
|
+
/**
|
|
823
|
+
* @private
|
|
824
|
+
* @this {OffsetThis}
|
|
825
|
+
* @description Retrieves the current window scroll position and viewport size.
|
|
826
|
+
* - Returns an object containing the scroll offsets, viewport dimensions, and boundary rects.
|
|
827
|
+
* @returns {{
|
|
828
|
+
* top: number,
|
|
829
|
+
* left: number,
|
|
830
|
+
* width: number,
|
|
831
|
+
* height: number,
|
|
832
|
+
* bottom: number,
|
|
833
|
+
* rects: RectsInfo
|
|
834
|
+
* }} An object with scroll and viewport information.
|
|
835
|
+
*/
|
|
836
|
+
|
|
837
|
+
_getWindowScroll() {
|
|
838
|
+
const viewPort = getClientSize(_d);
|
|
839
|
+
return {
|
|
840
|
+
top: _w.scrollY,
|
|
841
|
+
left: _w.scrollX,
|
|
842
|
+
width: viewPort.w,
|
|
843
|
+
height: viewPort.h,
|
|
844
|
+
bottom: _w.scrollY + viewPort.h,
|
|
845
|
+
rects: {
|
|
846
|
+
left: 0,
|
|
847
|
+
top: 0,
|
|
848
|
+
right: _w.innerWidth,
|
|
849
|
+
bottom: _w.innerHeight,
|
|
850
|
+
noText: true
|
|
851
|
+
}
|
|
852
|
+
};
|
|
853
|
+
},
|
|
854
|
+
|
|
855
|
+
constructor: Offset
|
|
856
|
+
};
|
|
857
|
+
|
|
858
|
+
export default Offset;
|