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
|
@@ -1,1484 +1,1550 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @fileoverview eventManager class
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
import CoreInjector from '../../editorInjector/_core';
|
|
6
|
-
import { dom, unicode, numbers, env, converter } from '../../helper';
|
|
7
|
-
import { _DragHandle } from '../../modules';
|
|
8
|
-
|
|
9
|
-
// event handlers
|
|
10
|
-
import { ButtonsHandler, OnClick_menuTray, OnClick_toolbar } from './eventHandlers/handler_toolbar';
|
|
11
|
-
import { OnMouseDown_wysiwyg, OnMouseUp_wysiwyg, OnClick_wysiwyg, OnMouseMove_wysiwyg, OnMouseLeave_wysiwyg } from './eventHandlers/handler_ww_mouse';
|
|
12
|
-
import { OnInput_wysiwyg, OnKeyDown_wysiwyg, OnKeyUp_wysiwyg } from './eventHandlers/handler_ww_key_input';
|
|
13
|
-
import { OnPaste_wysiwyg, OnCopy_wysiwyg, OnCut_wysiwyg } from './eventHandlers/handler_ww_clipboard';
|
|
14
|
-
import { OnDragOver_wysiwyg, OnDragEnd_wysiwyg, OnDrop_wysiwyg } from './eventHandlers/handler_ww_dragDrop';
|
|
15
|
-
|
|
16
|
-
const { _w, ON_OVER_COMPONENT, isMobile } = env;
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* @typedef {Omit<EventManager & Partial<__se__EditorInjector>, 'eventManager'>} EventManagerThis
|
|
20
|
-
*/
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
* @constructor
|
|
24
|
-
* @this {EventManagerThis}
|
|
25
|
-
* @description Event manager, editor's all event management class
|
|
26
|
-
* @param {__se__EditorCore} editor - The root editor instance
|
|
27
|
-
* @property {__se__EditorCore} editor - The root editor instance
|
|
28
|
-
*/
|
|
29
|
-
function EventManager(editor) {
|
|
30
|
-
CoreInjector.call(this, editor);
|
|
31
|
-
|
|
32
|
-
/**
|
|
33
|
-
* @description Old browsers: When there is no 'e.isComposing' in the keyup event
|
|
34
|
-
* @type {boolean}
|
|
35
|
-
*/
|
|
36
|
-
this.isComposing = false;
|
|
37
|
-
|
|
38
|
-
/**
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
/** @type {
|
|
45
|
-
this.
|
|
46
|
-
/** @type {
|
|
47
|
-
this.
|
|
48
|
-
/** @type {
|
|
49
|
-
this.
|
|
50
|
-
/** @type {
|
|
51
|
-
this.
|
|
52
|
-
/** @type {
|
|
53
|
-
this.
|
|
54
|
-
/** @type {
|
|
55
|
-
this.
|
|
56
|
-
/** @type {
|
|
57
|
-
this.
|
|
58
|
-
/** @type {
|
|
59
|
-
this.
|
|
60
|
-
/** @type {
|
|
61
|
-
this.
|
|
62
|
-
/** @type {
|
|
63
|
-
this.
|
|
64
|
-
/** @type {
|
|
65
|
-
this.
|
|
66
|
-
/** @type {__se__GlobalEventInfo|null} */
|
|
67
|
-
this.
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
/** @type {
|
|
71
|
-
this.
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
/** @type {
|
|
75
|
-
this.
|
|
76
|
-
/** @type {
|
|
77
|
-
this.
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
/** @type {
|
|
81
|
-
this.
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
/** @type {
|
|
85
|
-
this.
|
|
86
|
-
/** @type {
|
|
87
|
-
this.
|
|
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
|
-
type,
|
|
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
|
-
const
|
|
213
|
-
const
|
|
214
|
-
const
|
|
215
|
-
|
|
216
|
-
const
|
|
217
|
-
const
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
const
|
|
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
|
-
|
|
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
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
return
|
|
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
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
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
|
-
if (
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
}
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
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
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
if (
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
if (
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
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
|
-
this.
|
|
790
|
-
|
|
791
|
-
/**
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
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
|
-
this.
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
);
|
|
863
|
-
this.addEvent(eventWysiwyg, '
|
|
864
|
-
this.addEvent(eventWysiwyg, '
|
|
865
|
-
this.addEvent(eventWysiwyg, '
|
|
866
|
-
this.addEvent(eventWysiwyg, '
|
|
867
|
-
this.addEvent(eventWysiwyg, '
|
|
868
|
-
this.addEvent(
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
);
|
|
881
|
-
|
|
882
|
-
/**
|
|
883
|
-
const
|
|
884
|
-
this.addEvent(
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
(
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
this.
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
/**
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
*
|
|
940
|
-
* @
|
|
941
|
-
* @
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
*
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
*
|
|
981
|
-
* @
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
this.context.get('toolbar.
|
|
992
|
-
this.context.get('toolbar.
|
|
993
|
-
}
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
this.editor._lineBreaker_t.
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
this.editor._lineBreaker_b.
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
*
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
this.
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
if (
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
if (
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
if (
|
|
1084
|
-
this.
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
if (this.
|
|
1091
|
-
this.
|
|
1092
|
-
|
|
1093
|
-
}
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
this.
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
this.component.
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
}
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
}
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
this.
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
this.
|
|
1317
|
-
|
|
1318
|
-
});
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
}
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
this.
|
|
1335
|
-
this.ui.
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
* @
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
if (
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
if (this.
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview eventManager class
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import CoreInjector from '../../editorInjector/_core';
|
|
6
|
+
import { dom, unicode, numbers, env, converter } from '../../helper';
|
|
7
|
+
import { _DragHandle } from '../../modules';
|
|
8
|
+
|
|
9
|
+
// event handlers
|
|
10
|
+
import { ButtonsHandler, OnClick_menuTray, OnClick_toolbar } from './eventHandlers/handler_toolbar';
|
|
11
|
+
import { OnMouseDown_wysiwyg, OnMouseUp_wysiwyg, OnClick_wysiwyg, OnMouseMove_wysiwyg, OnMouseLeave_wysiwyg } from './eventHandlers/handler_ww_mouse';
|
|
12
|
+
import { OnInput_wysiwyg, OnKeyDown_wysiwyg, OnKeyUp_wysiwyg } from './eventHandlers/handler_ww_key_input';
|
|
13
|
+
import { OnPaste_wysiwyg, OnCopy_wysiwyg, OnCut_wysiwyg } from './eventHandlers/handler_ww_clipboard';
|
|
14
|
+
import { OnDragOver_wysiwyg, OnDragEnd_wysiwyg, OnDrop_wysiwyg } from './eventHandlers/handler_ww_dragDrop';
|
|
15
|
+
|
|
16
|
+
const { _w, _d, ON_OVER_COMPONENT, isMobile, isTouchDevice } = env;
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* @typedef {Omit<EventManager & Partial<__se__EditorInjector>, 'eventManager'>} EventManagerThis
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* @constructor
|
|
24
|
+
* @this {EventManagerThis}
|
|
25
|
+
* @description Event manager, editor's all event management class
|
|
26
|
+
* @param {__se__EditorCore} editor - The root editor instance
|
|
27
|
+
* @property {__se__EditorCore} editor - The root editor instance
|
|
28
|
+
*/
|
|
29
|
+
function EventManager(editor) {
|
|
30
|
+
CoreInjector.call(this, editor);
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* @description Old browsers: When there is no 'e.isComposing' in the keyup event
|
|
34
|
+
* @type {boolean}
|
|
35
|
+
*/
|
|
36
|
+
this.isComposing = false;
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* @description An array of parent containers that can be scrolled (in descending order)
|
|
40
|
+
* @type {Array<Element>}
|
|
41
|
+
*/
|
|
42
|
+
this.scrollparents = [];
|
|
43
|
+
|
|
44
|
+
/** @type {Array<*>} */
|
|
45
|
+
this._events = [];
|
|
46
|
+
/** @type {RegExp} */
|
|
47
|
+
this._onButtonsCheck = new RegExp(`^(${Object.keys(editor.options.get('_defaultStyleTagMap')).join('|')})$`, 'i');
|
|
48
|
+
/** @type {boolean} */
|
|
49
|
+
this._onShortcutKey = false;
|
|
50
|
+
/** @type {number} */
|
|
51
|
+
this._balloonDelay = null;
|
|
52
|
+
/** @type {ResizeObserver} */
|
|
53
|
+
this._wwFrameObserver = null;
|
|
54
|
+
/** @type {ResizeObserver} */
|
|
55
|
+
this._toolbarObserver = null;
|
|
56
|
+
/** @type {Element|null} */
|
|
57
|
+
this._lineBreakComp = null;
|
|
58
|
+
/** @type {Object<string, *>|null} */
|
|
59
|
+
this._formatAttrsTemp = null;
|
|
60
|
+
/** @type {number} */
|
|
61
|
+
this._resizeClientY = 0;
|
|
62
|
+
/** @type {__se__GlobalEventInfo|null} */
|
|
63
|
+
this.__resize_editor = null;
|
|
64
|
+
/** @type {__se__GlobalEventInfo|null} */
|
|
65
|
+
this.__close_move = null;
|
|
66
|
+
/** @type {__se__GlobalEventInfo|null} */
|
|
67
|
+
this.__geckoActiveEvent = null;
|
|
68
|
+
/** @type {Array<Node>} */
|
|
69
|
+
this.__cacheStyleNodes = [];
|
|
70
|
+
/** @type {__se__GlobalEventInfo|null} */
|
|
71
|
+
this.__selectionSyncEvent = null;
|
|
72
|
+
|
|
73
|
+
// input plugins
|
|
74
|
+
/** @type {boolean} */
|
|
75
|
+
this._inputFocus = false;
|
|
76
|
+
/** @type {Object<string, *>|null} */
|
|
77
|
+
this.__inputPlugin = null;
|
|
78
|
+
/** @type {?__se__EventInfo=} */
|
|
79
|
+
this.__inputBlurEvent = null;
|
|
80
|
+
/** @type {?__se__EventInfo=} */
|
|
81
|
+
this.__inputKeyEvent = null;
|
|
82
|
+
|
|
83
|
+
// viewport
|
|
84
|
+
/** @type {HTMLInputElement} */
|
|
85
|
+
this.__focusTemp = this.carrierWrapper.querySelector('.__se__focus__temp__');
|
|
86
|
+
/** @type {number|void} */
|
|
87
|
+
this.__retainTimer = null;
|
|
88
|
+
/** @type {Element} */
|
|
89
|
+
this.__eventDoc = null;
|
|
90
|
+
/** @type {string} */
|
|
91
|
+
this.__secopy = null;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
EventManager.prototype = {
|
|
95
|
+
/**
|
|
96
|
+
* @this {EventManagerThis}
|
|
97
|
+
* @description Register for an event.
|
|
98
|
+
* - Only events registered with this method are unregistered or re-registered when methods such as 'setOptions', 'destroy' are called.
|
|
99
|
+
* @param {*} target Target element
|
|
100
|
+
* @param {string} type Event type
|
|
101
|
+
* @param {(...args: *) => *} listener Event handler
|
|
102
|
+
* @param {boolean|AddEventListenerOptions=} useCapture Event useCapture option
|
|
103
|
+
* @return {__se__EventInfo|null} Registered event information
|
|
104
|
+
*/
|
|
105
|
+
addEvent(target, type, listener, useCapture) {
|
|
106
|
+
if (!target) return null;
|
|
107
|
+
if (!numbers.is(target.length) || target.nodeName || (!Array.isArray(target) && target.length < 1)) target = [target];
|
|
108
|
+
if (target.length === 0) return null;
|
|
109
|
+
|
|
110
|
+
const len = target.length;
|
|
111
|
+
for (let i = 0; i < len; i++) {
|
|
112
|
+
target[i].addEventListener(type, listener, useCapture);
|
|
113
|
+
this._events.push({
|
|
114
|
+
target: target[i],
|
|
115
|
+
type,
|
|
116
|
+
listener,
|
|
117
|
+
useCapture
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
return {
|
|
122
|
+
target: len > 1 ? target : target[0],
|
|
123
|
+
type,
|
|
124
|
+
listener,
|
|
125
|
+
useCapture
|
|
126
|
+
};
|
|
127
|
+
},
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* @this {EventManagerThis}
|
|
131
|
+
* @description Remove event
|
|
132
|
+
* @param {__se__EventInfo} params event info = this.addEvent()
|
|
133
|
+
* @returns {undefined|null} Success: null, Not found: undefined
|
|
134
|
+
*/
|
|
135
|
+
removeEvent(params) {
|
|
136
|
+
if (!params) return;
|
|
137
|
+
|
|
138
|
+
let target = params.target;
|
|
139
|
+
const type = params.type;
|
|
140
|
+
const listener = params.listener;
|
|
141
|
+
const useCapture = params.useCapture;
|
|
142
|
+
|
|
143
|
+
if (!target) return;
|
|
144
|
+
if (!numbers.is(target.length) || target.nodeName || (!Array.isArray(target) && target.length < 1)) target = /** @type {Array<Element>} */ ([target]);
|
|
145
|
+
if (target.length === 0) return;
|
|
146
|
+
|
|
147
|
+
for (let i = 0, len = target.length; i < len; i++) {
|
|
148
|
+
target[i].removeEventListener(type, listener, useCapture);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
return null;
|
|
152
|
+
},
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* @this {EventManagerThis}
|
|
156
|
+
* @description Add an event to document.
|
|
157
|
+
* - When created as an Iframe, the same event is added to the document in the Iframe.
|
|
158
|
+
* @param {string} type Event type
|
|
159
|
+
* @param {(...args: *) => *} listener Event listener
|
|
160
|
+
* @param {boolean|AddEventListenerOptions=} useCapture Use event capture
|
|
161
|
+
* @return {__se__GlobalEventInfo} Registered event information
|
|
162
|
+
*/
|
|
163
|
+
addGlobalEvent(type, listener, useCapture) {
|
|
164
|
+
if (this.editor.frameOptions.get('iframe')) {
|
|
165
|
+
this.editor.frameContext.get('_ww').addEventListener(type, listener, useCapture);
|
|
166
|
+
}
|
|
167
|
+
this._w.addEventListener(type, listener, useCapture);
|
|
168
|
+
return {
|
|
169
|
+
type,
|
|
170
|
+
listener,
|
|
171
|
+
useCapture
|
|
172
|
+
};
|
|
173
|
+
},
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* @this {EventManagerThis}
|
|
177
|
+
* @description Remove events from document.
|
|
178
|
+
* - When created as an Iframe, the event of the document inside the Iframe is also removed.
|
|
179
|
+
* @param {string|__se__GlobalEventInfo} type Event type or (Event info = this.addGlobalEvent())
|
|
180
|
+
* @param {(...args: *) => *=} listener Event listener
|
|
181
|
+
* @param {boolean|AddEventListenerOptions=} useCapture Use event capture
|
|
182
|
+
* @returns {undefined|null} Success: null, Not found: undefined
|
|
183
|
+
*/
|
|
184
|
+
removeGlobalEvent(type, listener, useCapture) {
|
|
185
|
+
if (!type) return;
|
|
186
|
+
|
|
187
|
+
if (typeof type === 'object') {
|
|
188
|
+
listener = type.listener;
|
|
189
|
+
useCapture = type.useCapture;
|
|
190
|
+
type = type.type;
|
|
191
|
+
}
|
|
192
|
+
if (this.editor.frameOptions.get('iframe')) {
|
|
193
|
+
this.editor.frameContext.get('_ww').removeEventListener(type, listener, useCapture);
|
|
194
|
+
}
|
|
195
|
+
this._w.removeEventListener(type, listener, useCapture);
|
|
196
|
+
|
|
197
|
+
return null;
|
|
198
|
+
},
|
|
199
|
+
|
|
200
|
+
/**
|
|
201
|
+
* @this {EventManagerThis}
|
|
202
|
+
* @description Activates the corresponding button with the tags information of the current cursor position,
|
|
203
|
+
* - such as 'bold', 'underline', etc., and executes the 'active' method of the plugins.
|
|
204
|
+
* @param {?Node=} selectionNode selectionNode
|
|
205
|
+
* @returns {Node|undefined} selectionNode
|
|
206
|
+
*/
|
|
207
|
+
applyTagEffect(selectionNode) {
|
|
208
|
+
selectionNode = selectionNode || this.selection.getNode();
|
|
209
|
+
if (selectionNode === this.editor.effectNode) return;
|
|
210
|
+
this.editor.effectNode = selectionNode;
|
|
211
|
+
|
|
212
|
+
const marginDir = this.options.get('_rtl') ? 'marginRight' : 'marginLeft';
|
|
213
|
+
const plugins = this.plugins;
|
|
214
|
+
const commandTargets = this.editor.commandTargets;
|
|
215
|
+
const classOnCheck = this._onButtonsCheck;
|
|
216
|
+
const styleCommand = this.options.get('_styleCommandMap');
|
|
217
|
+
const commandMapNodes = [];
|
|
218
|
+
const currentNodes = [];
|
|
219
|
+
|
|
220
|
+
const styleTags = this.options.get('_textStyleTags');
|
|
221
|
+
const styleNodes = [];
|
|
222
|
+
|
|
223
|
+
const ignoreCommands = [];
|
|
224
|
+
const activeCommands = this.editor.activeCommands;
|
|
225
|
+
const cLen = activeCommands.length;
|
|
226
|
+
let nodeName = '';
|
|
227
|
+
|
|
228
|
+
if (this.component.is(selectionNode) && !this.component.__selectionSelected) {
|
|
229
|
+
const component = this.component.get(selectionNode);
|
|
230
|
+
if (!component) return;
|
|
231
|
+
this.component.select(component.target, component.pluginName);
|
|
232
|
+
return;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
while (selectionNode.firstChild) {
|
|
236
|
+
selectionNode = selectionNode.firstChild;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
const fc = this.editor.frameContext;
|
|
240
|
+
const notReadonly = !fc.get('isReadOnly');
|
|
241
|
+
for (let element = selectionNode; !dom.check.isWysiwygFrame(element); element = element.parentElement) {
|
|
242
|
+
if (!element) break;
|
|
243
|
+
if (element.nodeType !== 1 || dom.check.isBreak(element)) continue;
|
|
244
|
+
if (this._isNonFocusNode(element)) {
|
|
245
|
+
this.editor.blur();
|
|
246
|
+
return;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
nodeName = element.nodeName.toLowerCase();
|
|
250
|
+
currentNodes.push(nodeName);
|
|
251
|
+
if (styleTags.includes(nodeName) && !this.format.isLine(nodeName)) styleNodes.push(element);
|
|
252
|
+
|
|
253
|
+
/* Active plugins */
|
|
254
|
+
if (notReadonly) {
|
|
255
|
+
for (let c = 0, name; c < cLen; c++) {
|
|
256
|
+
name = activeCommands[c];
|
|
257
|
+
if (
|
|
258
|
+
!commandMapNodes.includes(name) &&
|
|
259
|
+
!ignoreCommands.includes(name) &&
|
|
260
|
+
commandTargets.get(name) &&
|
|
261
|
+
commandTargets.get(name).filter((e) => {
|
|
262
|
+
const r = plugins[name]?.active(element, e);
|
|
263
|
+
if (r === undefined) {
|
|
264
|
+
ignoreCommands.push(name);
|
|
265
|
+
}
|
|
266
|
+
return r;
|
|
267
|
+
}).length > 0
|
|
268
|
+
) {
|
|
269
|
+
commandMapNodes.push(name);
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
/** indent, outdent */
|
|
275
|
+
if (this.format.isLine(element)) {
|
|
276
|
+
/* Outdent */
|
|
277
|
+
if (!commandMapNodes.includes('outdent') && commandTargets.has('outdent') && (dom.check.isListCell(element) || (element.style[marginDir] && numbers.get(element.style[marginDir], 0) > 0))) {
|
|
278
|
+
if (
|
|
279
|
+
commandTargets.get('outdent').filter((e) => {
|
|
280
|
+
if (dom.check.isImportantDisabled(e)) return false;
|
|
281
|
+
e.disabled = false;
|
|
282
|
+
return true;
|
|
283
|
+
}).length > 0
|
|
284
|
+
) {
|
|
285
|
+
commandMapNodes.push('outdent');
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
/* Indent */
|
|
289
|
+
if (!commandMapNodes.includes('indent') && commandTargets.has('indent')) {
|
|
290
|
+
const indentDisable = dom.check.isListCell(element) && !element.previousElementSibling;
|
|
291
|
+
if (
|
|
292
|
+
commandTargets.get('indent').filter((e) => {
|
|
293
|
+
if (dom.check.isImportantDisabled(e)) return false;
|
|
294
|
+
e.disabled = indentDisable;
|
|
295
|
+
return true;
|
|
296
|
+
}).length > 0
|
|
297
|
+
) {
|
|
298
|
+
commandMapNodes.push('indent');
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
continue;
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
/** default active buttons [strong, ins, em, del, sub, sup] */
|
|
306
|
+
if (classOnCheck.test(nodeName)) {
|
|
307
|
+
nodeName = styleCommand[nodeName] || nodeName;
|
|
308
|
+
commandMapNodes.push(nodeName);
|
|
309
|
+
dom.utils.addClass(commandTargets.get(nodeName), 'active');
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
this._setKeyEffect(commandMapNodes);
|
|
314
|
+
|
|
315
|
+
// cache style nodes
|
|
316
|
+
this.__cacheStyleNodes = styleNodes.reverse();
|
|
317
|
+
|
|
318
|
+
/** save current nodes */
|
|
319
|
+
this.status.currentNodes = currentNodes.reverse();
|
|
320
|
+
this.status.currentNodesMap = commandMapNodes;
|
|
321
|
+
|
|
322
|
+
/** Displays the current node structure to statusbar */
|
|
323
|
+
if (this.editor.frameOptions.get('statusbar_showPathLabel') && fc.get('navigation')) {
|
|
324
|
+
fc.get('navigation').textContent = this.options.get('_rtl') ? this.status.currentNodes.reverse().join(' < ') : this.status.currentNodes.join(' > ');
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
return selectionNode;
|
|
328
|
+
},
|
|
329
|
+
|
|
330
|
+
/**
|
|
331
|
+
* @private
|
|
332
|
+
* @this {EventManagerThis}
|
|
333
|
+
* @description Gives an active effect when the mouse down event is blocked. (Used when "env.isGecko" is true)
|
|
334
|
+
* @param {Node} target Target element
|
|
335
|
+
* @private
|
|
336
|
+
*/
|
|
337
|
+
_injectActiveEvent(target) {
|
|
338
|
+
dom.utils.addClass(target, '__se__active');
|
|
339
|
+
this.__geckoActiveEvent = this.addGlobalEvent('mouseup', () => {
|
|
340
|
+
dom.utils.removeClass(target, '__se__active');
|
|
341
|
+
this.__geckoActiveEvent = this.removeGlobalEvent(this.__geckoActiveEvent);
|
|
342
|
+
});
|
|
343
|
+
},
|
|
344
|
+
|
|
345
|
+
/**
|
|
346
|
+
* @private
|
|
347
|
+
* @this {EventManagerThis}
|
|
348
|
+
* @description remove class, display text.
|
|
349
|
+
* @param {Array<string>} ignoredList Igonred button list
|
|
350
|
+
* @private
|
|
351
|
+
*/
|
|
352
|
+
_setKeyEffect(ignoredList) {
|
|
353
|
+
const activeCommands = this.editor.activeCommands;
|
|
354
|
+
const commandTargets = this.editor.commandTargets;
|
|
355
|
+
const plugins = this.plugins;
|
|
356
|
+
for (let i = 0, len = activeCommands.length, k, c, p; i < len; i++) {
|
|
357
|
+
k = activeCommands[i];
|
|
358
|
+
if (ignoredList.includes(k) || !(c = commandTargets.get(k))) continue;
|
|
359
|
+
|
|
360
|
+
p = plugins[k];
|
|
361
|
+
for (let j = 0, jLen = c.length, e; j < jLen; j++) {
|
|
362
|
+
e = c[j];
|
|
363
|
+
if (!e) continue;
|
|
364
|
+
if (p) {
|
|
365
|
+
p.active(null, e);
|
|
366
|
+
} else if (/^outdent$/i.test(k)) {
|
|
367
|
+
if (!dom.check.isImportantDisabled(e)) e.disabled = true;
|
|
368
|
+
} else if (/^indent$/i.test(k)) {
|
|
369
|
+
if (!dom.check.isImportantDisabled(e)) e.disabled = false;
|
|
370
|
+
} else {
|
|
371
|
+
dom.utils.removeClass(e, 'active');
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
},
|
|
376
|
+
|
|
377
|
+
/**
|
|
378
|
+
* @private
|
|
379
|
+
* @this {EventManagerThis}
|
|
380
|
+
* @description Show toolbar-balloon with delay.
|
|
381
|
+
*/
|
|
382
|
+
_showToolbarBalloonDelay() {
|
|
383
|
+
if (this._balloonDelay) {
|
|
384
|
+
_w.clearTimeout(this._balloonDelay);
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
this._balloonDelay = _w.setTimeout(() => {
|
|
388
|
+
_w.clearTimeout(this._balloonDelay);
|
|
389
|
+
this._balloonDelay = null;
|
|
390
|
+
if (this.editor.isSubBalloon) this.subToolbar._showBalloon();
|
|
391
|
+
else this.toolbar._showBalloon();
|
|
392
|
+
}, 250);
|
|
393
|
+
},
|
|
394
|
+
|
|
395
|
+
/**
|
|
396
|
+
* @private
|
|
397
|
+
* @this {EventManagerThis}
|
|
398
|
+
* @description Show or hide the toolbar-balloon.
|
|
399
|
+
*/
|
|
400
|
+
_toggleToolbarBalloon() {
|
|
401
|
+
this.selection._init();
|
|
402
|
+
const range = this.selection.getRange();
|
|
403
|
+
const hasSubMode = this.options.has('_subMode');
|
|
404
|
+
|
|
405
|
+
if (!(hasSubMode ? this.editor.isSubBalloonAlways : this.editor.isBalloonAlways) && range.collapsed) {
|
|
406
|
+
if (hasSubMode) this._hideToolbar_sub();
|
|
407
|
+
else this._hideToolbar();
|
|
408
|
+
} else {
|
|
409
|
+
if (hasSubMode) this.subToolbar._showBalloon(range);
|
|
410
|
+
else this.toolbar._showBalloon(range);
|
|
411
|
+
}
|
|
412
|
+
},
|
|
413
|
+
|
|
414
|
+
/**
|
|
415
|
+
* @private
|
|
416
|
+
* @this {EventManagerThis}
|
|
417
|
+
* @description Hide the toolbar.
|
|
418
|
+
*/
|
|
419
|
+
_hideToolbar() {
|
|
420
|
+
if (!this.editor._notHideToolbar && !this.editor.frameContext.get('isFullScreen')) {
|
|
421
|
+
this.toolbar.hide();
|
|
422
|
+
}
|
|
423
|
+
},
|
|
424
|
+
|
|
425
|
+
/**
|
|
426
|
+
* @private
|
|
427
|
+
* @this {EventManagerThis}
|
|
428
|
+
* @description Hide the Sub-Toolbar.
|
|
429
|
+
*/
|
|
430
|
+
_hideToolbar_sub() {
|
|
431
|
+
if (this.subToolbar && !this.editor._notHideToolbar) {
|
|
432
|
+
this.subToolbar.hide();
|
|
433
|
+
}
|
|
434
|
+
},
|
|
435
|
+
|
|
436
|
+
/**
|
|
437
|
+
* @private
|
|
438
|
+
* @this {EventManagerThis}
|
|
439
|
+
* @description Checks if a node is a non-focusable element(.data-se-non-focus). (e.g. fileUpload.component > span)
|
|
440
|
+
* @param {Node} node Node to check
|
|
441
|
+
* @returns {boolean} True if the node is non-focusable, otherwise false
|
|
442
|
+
*/
|
|
443
|
+
_isNonFocusNode(node) {
|
|
444
|
+
return dom.check.isElement(node) && node.getAttribute('data-se-non-focus') === 'true';
|
|
445
|
+
},
|
|
446
|
+
|
|
447
|
+
/**
|
|
448
|
+
* @private
|
|
449
|
+
* @this {EventManagerThis}
|
|
450
|
+
* @description Determines if the "range" is within an uneditable node.
|
|
451
|
+
* @param {Range} range The range object
|
|
452
|
+
* @param {boolean} isFront Whether to check the start or end of the range
|
|
453
|
+
* @returns {Node|null} The uneditable node if found, otherwise null
|
|
454
|
+
*/
|
|
455
|
+
_isUneditableNode(range, isFront) {
|
|
456
|
+
const container = isFront ? range.startContainer : range.endContainer;
|
|
457
|
+
const offset = isFront ? range.startOffset : range.endOffset;
|
|
458
|
+
const siblingKey = isFront ? 'previousSibling' : 'nextSibling';
|
|
459
|
+
const isElement = container.nodeType === 1;
|
|
460
|
+
|
|
461
|
+
let siblingNode;
|
|
462
|
+
if (isElement) {
|
|
463
|
+
siblingNode = /** @type {HTMLElement} */ (this._isUneditableNode_getSibling(container.childNodes[offset], siblingKey, container));
|
|
464
|
+
return siblingNode && siblingNode.nodeType === 1 && siblingNode.getAttribute('contenteditable') === 'false' ? siblingNode : null;
|
|
465
|
+
} else {
|
|
466
|
+
siblingNode = /** @type {HTMLElement} */ (this._isUneditableNode_getSibling(container, siblingKey, container));
|
|
467
|
+
return dom.check.isEdgePoint(container, offset, isFront ? 'front' : 'end') && siblingNode && siblingNode.nodeType === 1 && siblingNode.getAttribute('contenteditable') === 'false' ? siblingNode : null;
|
|
468
|
+
}
|
|
469
|
+
},
|
|
470
|
+
|
|
471
|
+
/**
|
|
472
|
+
* @private
|
|
473
|
+
* @this {EventManagerThis}
|
|
474
|
+
* @description Retrieves the sibling node of a selected node if it is uneditable.
|
|
475
|
+
* - Used only in `_isUneditableNode`.
|
|
476
|
+
* @param {Node} selectNode The selected node
|
|
477
|
+
* @param {string} siblingKey The key to access the sibling (`previousSibling` or `nextSibling`)
|
|
478
|
+
* @param {Node} container The parent container node
|
|
479
|
+
* @returns {Node|null} The sibling node if found, otherwise null
|
|
480
|
+
*/
|
|
481
|
+
_isUneditableNode_getSibling(selectNode, siblingKey, container) {
|
|
482
|
+
if (!selectNode) return null;
|
|
483
|
+
let siblingNode = selectNode[siblingKey];
|
|
484
|
+
|
|
485
|
+
if (!siblingNode) {
|
|
486
|
+
siblingNode = this.format.getLine(container);
|
|
487
|
+
siblingNode = siblingNode ? siblingNode[siblingKey] : null;
|
|
488
|
+
if (siblingNode && !this.component.is(siblingNode)) siblingNode = siblingKey === 'previousSibling' ? siblingNode.firstChild : siblingNode.lastChild;
|
|
489
|
+
else return null;
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
return siblingNode;
|
|
493
|
+
},
|
|
494
|
+
|
|
495
|
+
/**
|
|
496
|
+
* @private
|
|
497
|
+
* @this {EventManagerThis}
|
|
498
|
+
* @description Deletes specific elements such as tables in "Firefox" and media elements (image, video, audio) in "Chrome".
|
|
499
|
+
* - Handles deletion logic based on selection range and node types.
|
|
500
|
+
* @returns {boolean} Returns `true` if an element was deleted and focus was adjusted, otherwise `false`.
|
|
501
|
+
*/
|
|
502
|
+
_hardDelete() {
|
|
503
|
+
const range = this.selection.getRange();
|
|
504
|
+
const sc = range.startContainer;
|
|
505
|
+
const ec = range.endContainer;
|
|
506
|
+
|
|
507
|
+
// table
|
|
508
|
+
const sCell = this.format.getBlock(sc);
|
|
509
|
+
const eCell = this.format.getBlock(ec);
|
|
510
|
+
const sIsCell = dom.check.isTableCell(sCell);
|
|
511
|
+
const eIsCell = dom.check.isTableCell(eCell);
|
|
512
|
+
if (((sIsCell && !sCell.previousElementSibling && !sCell.parentElement.previousElementSibling) || (eIsCell && !eCell.nextElementSibling && !eCell.parentElement.nextElementSibling)) && sCell !== eCell) {
|
|
513
|
+
const ancestor = dom.query.getParentElement(range.commonAncestorContainer, dom.check.isFigure)?.parentElement || range.commonAncestorContainer;
|
|
514
|
+
if (!sIsCell) {
|
|
515
|
+
dom.utils.removeItem(dom.query.getParentElement(eCell, (current) => ancestor === current.parentNode));
|
|
516
|
+
} else if (!eIsCell) {
|
|
517
|
+
dom.utils.removeItem(dom.query.getParentElement(sCell, (current) => ancestor === current.parentNode));
|
|
518
|
+
} else {
|
|
519
|
+
dom.utils.removeItem(dom.query.getParentElement(sCell, (current) => ancestor === current.parentNode));
|
|
520
|
+
this.editor._nativeFocus();
|
|
521
|
+
return true;
|
|
522
|
+
}
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
// component
|
|
526
|
+
const sComp = sc.nodeType === 1 ? dom.query.getParentElement(sc, '.se-component') : null;
|
|
527
|
+
const eComp = ec.nodeType === 1 ? dom.query.getParentElement(ec, '.se-component') : null;
|
|
528
|
+
if (sComp) dom.utils.removeItem(sComp);
|
|
529
|
+
if (eComp) dom.utils.removeItem(eComp);
|
|
530
|
+
|
|
531
|
+
return false;
|
|
532
|
+
},
|
|
533
|
+
|
|
534
|
+
/**
|
|
535
|
+
* @private
|
|
536
|
+
* @this {EventManagerThis}
|
|
537
|
+
* @description If there is no default format, add a line and move 'selection'.
|
|
538
|
+
* @param {string|null} formatName Format tag name (default: 'P')
|
|
539
|
+
*/
|
|
540
|
+
_setDefaultLine(formatName) {
|
|
541
|
+
if (!this.options.get('__lineFormatFilter')) return null;
|
|
542
|
+
if (this.editor._fileManager.pluginRegExp.test(this.editor.currentControllerName)) return;
|
|
543
|
+
|
|
544
|
+
const range = this.selection.getRange();
|
|
545
|
+
const commonCon = /** @type {HTMLElement} */ (range.commonAncestorContainer);
|
|
546
|
+
const startCon = range.startContainer;
|
|
547
|
+
const rangeEl = this.format.getBlock(commonCon, null);
|
|
548
|
+
|
|
549
|
+
/** @type {Node} */
|
|
550
|
+
let focusNode;
|
|
551
|
+
let offset, format;
|
|
552
|
+
|
|
553
|
+
if (rangeEl) {
|
|
554
|
+
format = dom.utils.createElement(formatName || this.options.get('defaultLine'));
|
|
555
|
+
format.innerHTML = rangeEl.innerHTML;
|
|
556
|
+
if (format.childNodes.length === 0) format.innerHTML = unicode.zeroWidthSpace;
|
|
557
|
+
|
|
558
|
+
rangeEl.innerHTML = format.outerHTML;
|
|
559
|
+
format = rangeEl.firstChild;
|
|
560
|
+
focusNode = dom.query.getEdgeChildNodes(format, null).sc;
|
|
561
|
+
|
|
562
|
+
if (!focusNode) {
|
|
563
|
+
focusNode = dom.utils.createTextNode(unicode.zeroWidthSpace);
|
|
564
|
+
format.insertBefore(focusNode, format.firstChild);
|
|
565
|
+
}
|
|
566
|
+
|
|
567
|
+
offset = focusNode.textContent.length;
|
|
568
|
+
this.selection.setRange(focusNode, offset, focusNode, offset);
|
|
569
|
+
return;
|
|
570
|
+
}
|
|
571
|
+
|
|
572
|
+
if (commonCon.nodeType === 3 && this.component.is(commonCon.parentElement)) {
|
|
573
|
+
const compInfo = this.component.get(commonCon.parentElement);
|
|
574
|
+
if (!compInfo) return;
|
|
575
|
+
|
|
576
|
+
const container = compInfo.container;
|
|
577
|
+
|
|
578
|
+
if (commonCon.parentElement === container) {
|
|
579
|
+
const siblingEl = commonCon.nextElementSibling ? container : container.nextElementSibling;
|
|
580
|
+
const el = dom.utils.createElement(this.options.get('defaultLine'), null, commonCon);
|
|
581
|
+
container.parentElement.insertBefore(el, siblingEl);
|
|
582
|
+
this.editor.focusEdge(el);
|
|
583
|
+
return;
|
|
584
|
+
}
|
|
585
|
+
|
|
586
|
+
this.component.select(compInfo.target, compInfo.pluginName);
|
|
587
|
+
return null;
|
|
588
|
+
} else if (commonCon.nodeType === 1 && commonCon.getAttribute('data-se-embed') === 'true') {
|
|
589
|
+
let el = commonCon.nextElementSibling;
|
|
590
|
+
if (!this.format.isLine(el)) el = this.format.addLine(commonCon, this.options.get('defaultLine'));
|
|
591
|
+
this.selection.setRange(el.firstChild, 0, el.firstChild, 0);
|
|
592
|
+
return;
|
|
593
|
+
}
|
|
594
|
+
|
|
595
|
+
if ((this.format.isBlock(startCon) || dom.check.isWysiwygFrame(startCon)) && (this.component.is(startCon.children[range.startOffset]) || this.component.is(startCon.children[range.startOffset - 1]))) return;
|
|
596
|
+
if (dom.query.getParentElement(commonCon, dom.check.isExcludeFormat)) return null;
|
|
597
|
+
|
|
598
|
+
if (this.format.isBlock(commonCon) && commonCon.childNodes.length <= 1) {
|
|
599
|
+
let br = null;
|
|
600
|
+
if (commonCon.childNodes.length === 1 && dom.check.isBreak(commonCon.firstChild)) {
|
|
601
|
+
br = commonCon.firstChild;
|
|
602
|
+
} else {
|
|
603
|
+
br = dom.utils.createTextNode(unicode.zeroWidthSpace);
|
|
604
|
+
commonCon.appendChild(br);
|
|
605
|
+
}
|
|
606
|
+
|
|
607
|
+
this.selection.setRange(br, 1, br, 1);
|
|
608
|
+
return;
|
|
609
|
+
}
|
|
610
|
+
|
|
611
|
+
/* eslint-disable @typescript-eslint/no-unused-vars */
|
|
612
|
+
try {
|
|
613
|
+
if (commonCon.nodeType === 3) {
|
|
614
|
+
format = dom.utils.createElement(formatName || this.options.get('defaultLine'));
|
|
615
|
+
commonCon.parentNode.insertBefore(format, commonCon);
|
|
616
|
+
format.appendChild(commonCon);
|
|
617
|
+
}
|
|
618
|
+
|
|
619
|
+
if (dom.check.isBreak(format.nextSibling)) dom.utils.removeItem(format.nextSibling);
|
|
620
|
+
if (dom.check.isBreak(format.previousSibling)) dom.utils.removeItem(format.previousSibling);
|
|
621
|
+
if (dom.check.isBreak(focusNode)) {
|
|
622
|
+
const zeroWidth = dom.utils.createTextNode(unicode.zeroWidthSpace);
|
|
623
|
+
focusNode.parentNode.insertBefore(zeroWidth, focusNode);
|
|
624
|
+
focusNode = zeroWidth;
|
|
625
|
+
}
|
|
626
|
+
} catch (e) {
|
|
627
|
+
this.editor.execCommand('formatBlock', false, formatName || this.options.get('defaultLine'));
|
|
628
|
+
this.selection.removeRange();
|
|
629
|
+
this.selection._init();
|
|
630
|
+
this.editor.effectNode = null;
|
|
631
|
+
return;
|
|
632
|
+
}
|
|
633
|
+
/* eslint-disable @typescript-eslint/no-unused-vars */
|
|
634
|
+
|
|
635
|
+
if (format) {
|
|
636
|
+
if (dom.check.isBreak(format.nextSibling)) dom.utils.removeItem(format.nextSibling);
|
|
637
|
+
if (dom.check.isBreak(format.previousSibling)) dom.utils.removeItem(format.previousSibling);
|
|
638
|
+
if (dom.check.isBreak(focusNode)) {
|
|
639
|
+
const zeroWidth = dom.utils.createTextNode(unicode.zeroWidthSpace);
|
|
640
|
+
focusNode.parentNode.insertBefore(zeroWidth, focusNode);
|
|
641
|
+
focusNode = zeroWidth;
|
|
642
|
+
}
|
|
643
|
+
}
|
|
644
|
+
|
|
645
|
+
this.editor.effectNode = null;
|
|
646
|
+
if (startCon) {
|
|
647
|
+
this.selection.setRange(startCon, 1, startCon, 1);
|
|
648
|
+
} else {
|
|
649
|
+
this.editor._nativeFocus();
|
|
650
|
+
}
|
|
651
|
+
},
|
|
652
|
+
|
|
653
|
+
/**
|
|
654
|
+
* @private
|
|
655
|
+
* @this {EventManagerThis}
|
|
656
|
+
* @description Handles data transfer actions for paste and drop events.
|
|
657
|
+
* - It processes clipboard data, triggers relevant events, and inserts cleaned data into the editor.
|
|
658
|
+
* @param {"paste"|"drop"} type The type of event
|
|
659
|
+
* @param {Event} e The original event object
|
|
660
|
+
* @param {DataTransfer} clipboardData The clipboard data object
|
|
661
|
+
* @param {__se__FrameContext} frameContext The frame context
|
|
662
|
+
* @returns {Promise<boolean>} Resolves to `false` if processing is complete, otherwise allows default behavior
|
|
663
|
+
*/
|
|
664
|
+
async _dataTransferAction(type, e, clipboardData, frameContext) {
|
|
665
|
+
try {
|
|
666
|
+
this.ui.showLoading();
|
|
667
|
+
await this._setClipboardData(type, e, clipboardData, frameContext);
|
|
668
|
+
e.preventDefault();
|
|
669
|
+
e.stopPropagation();
|
|
670
|
+
return false;
|
|
671
|
+
} catch (err) {
|
|
672
|
+
console.warn('[SUNEDITOR.paste.error]', err);
|
|
673
|
+
} finally {
|
|
674
|
+
this.ui.hideLoading();
|
|
675
|
+
}
|
|
676
|
+
},
|
|
677
|
+
|
|
678
|
+
/**
|
|
679
|
+
* @private
|
|
680
|
+
* @this {EventManagerThis}
|
|
681
|
+
* @description Processes clipboard data for paste and drop events, handling text and HTML cleanup.
|
|
682
|
+
* - Supports specific handling for content from Microsoft Office applications.
|
|
683
|
+
* @param {"paste"|"drop"} type The type of event
|
|
684
|
+
* @param {Event} e The original event object
|
|
685
|
+
* @param {DataTransfer} clipboardData The clipboard data object
|
|
686
|
+
* @param {__se__FrameContext} frameContext The frame context
|
|
687
|
+
* @returns {Promise<boolean>} Resolves to `false` if processing is complete, otherwise allows default behavior
|
|
688
|
+
*/
|
|
689
|
+
async _setClipboardData(type, e, clipboardData, frameContext) {
|
|
690
|
+
e.preventDefault();
|
|
691
|
+
e.stopPropagation();
|
|
692
|
+
|
|
693
|
+
let plainText = clipboardData.getData('text/plain');
|
|
694
|
+
let cleanData = clipboardData.getData('text/html');
|
|
695
|
+
const onlyText = !cleanData;
|
|
696
|
+
|
|
697
|
+
// SE copy data
|
|
698
|
+
const SEData = this.__secopy === plainText;
|
|
699
|
+
// MS word, OneNode, Excel
|
|
700
|
+
const MSData = /class=["']*Mso(Normal|List)/i.test(cleanData) || /content=["']*Word.Document/i.test(cleanData) || /content=["']*OneNote.File/i.test(cleanData) || /content=["']*Excel.Sheet/i.test(cleanData);
|
|
701
|
+
// from
|
|
702
|
+
const from = SEData ? 'SE' : MSData ? 'MS' : '';
|
|
703
|
+
|
|
704
|
+
if (onlyText) {
|
|
705
|
+
cleanData = converter.htmlToEntity(plainText).replace(/\n/g, '<br>');
|
|
706
|
+
} else {
|
|
707
|
+
cleanData = cleanData.replace(/^<html>\r?\n?<body>\r?\n?\x3C!--StartFragment-->|\x3C!--EndFragment-->\r?\n?<\/body>\r?\n?<\/html>$/g, '');
|
|
708
|
+
if (MSData) {
|
|
709
|
+
cleanData = cleanData.replace(/\n/g, ' ');
|
|
710
|
+
plainText = plainText.replace(/\n/g, ' ');
|
|
711
|
+
}
|
|
712
|
+
}
|
|
713
|
+
|
|
714
|
+
if (!SEData) {
|
|
715
|
+
const autoLinkify = this.options.get('autoLinkify');
|
|
716
|
+
if (autoLinkify) {
|
|
717
|
+
const domParser = new DOMParser().parseFromString(cleanData, 'text/html');
|
|
718
|
+
dom.query.getListChildNodes(domParser.body, converter.textToAnchor);
|
|
719
|
+
cleanData = domParser.body.innerHTML;
|
|
720
|
+
}
|
|
721
|
+
}
|
|
722
|
+
|
|
723
|
+
if (!onlyText) {
|
|
724
|
+
cleanData = this.html.clean(cleanData, { forceFormat: false, whitelist: null, blacklist: null });
|
|
725
|
+
}
|
|
726
|
+
|
|
727
|
+
const maxCharCount = this.char.test(this.editor.frameOptions.get('charCounter_type') === 'byte-html' ? cleanData : plainText, false);
|
|
728
|
+
// user event - paste
|
|
729
|
+
if (type === 'paste') {
|
|
730
|
+
const value = await this.triggerEvent('onPaste', { frameContext, event: e, data: cleanData, maxCharCount, from });
|
|
731
|
+
if (value === false) {
|
|
732
|
+
return false;
|
|
733
|
+
} else if (typeof value === 'string') {
|
|
734
|
+
if (!value) return false;
|
|
735
|
+
cleanData = value;
|
|
736
|
+
}
|
|
737
|
+
}
|
|
738
|
+
// user event - drop
|
|
739
|
+
if (type === 'drop') {
|
|
740
|
+
const value = await this.triggerEvent('onDrop', { frameContext, event: e, data: cleanData, maxCharCount, from });
|
|
741
|
+
if (value === false) {
|
|
742
|
+
return false;
|
|
743
|
+
} else if (typeof value === 'string') {
|
|
744
|
+
if (!value) return false;
|
|
745
|
+
cleanData = value;
|
|
746
|
+
}
|
|
747
|
+
}
|
|
748
|
+
|
|
749
|
+
// files
|
|
750
|
+
const files = clipboardData.files;
|
|
751
|
+
if (files.length > 0 && !MSData) {
|
|
752
|
+
for (let i = 0, len = files.length; i < len; i++) {
|
|
753
|
+
this._callPluginEvent('onFilePasteAndDrop', { frameContext, event: e, file: files[i] });
|
|
754
|
+
}
|
|
755
|
+
|
|
756
|
+
return false;
|
|
757
|
+
}
|
|
758
|
+
|
|
759
|
+
if (!maxCharCount) {
|
|
760
|
+
return false;
|
|
761
|
+
}
|
|
762
|
+
|
|
763
|
+
if (cleanData) {
|
|
764
|
+
const domParser = new DOMParser().parseFromString(cleanData, 'text/html');
|
|
765
|
+
if (this._callPluginEvent('onPaste', { frameContext, event: e, data: cleanData, doc: domParser }) !== true) {
|
|
766
|
+
this.html.insert(cleanData, { selectInserted: false, skipCharCount: true, skipCleaning: true });
|
|
767
|
+
}
|
|
768
|
+
|
|
769
|
+
// document type
|
|
770
|
+
if (frameContext.has('documentType-use-header')) {
|
|
771
|
+
frameContext.get('documentType').reHeader();
|
|
772
|
+
}
|
|
773
|
+
return false;
|
|
774
|
+
}
|
|
775
|
+
},
|
|
776
|
+
|
|
777
|
+
/**
|
|
778
|
+
* @private
|
|
779
|
+
* @this {EventManagerThis}
|
|
780
|
+
* @description Registers common UI events such as toolbar and menu interactions.
|
|
781
|
+
* - Adds event listeners for various UI elements, sets up observers, and configures window events.
|
|
782
|
+
*/
|
|
783
|
+
_addCommonEvents() {
|
|
784
|
+
const buttonsHandler = ButtonsHandler.bind(this);
|
|
785
|
+
const toolbarHandler = OnClick_toolbar.bind(this);
|
|
786
|
+
|
|
787
|
+
/** menu event */
|
|
788
|
+
this.addEvent(this.context.get('menuTray'), 'mousedown', buttonsHandler, false);
|
|
789
|
+
this.addEvent(this.context.get('menuTray'), 'click', OnClick_menuTray.bind(this), true);
|
|
790
|
+
|
|
791
|
+
/** toolbar event */
|
|
792
|
+
this.addEvent(this.context.get('toolbar.main'), 'mousedown', buttonsHandler, false);
|
|
793
|
+
this.addEvent(this.context.get('toolbar.main'), 'click', toolbarHandler, false);
|
|
794
|
+
// subToolbar
|
|
795
|
+
if (this.options.has('_subMode')) {
|
|
796
|
+
this.addEvent(this.context.get('toolbar.sub.main'), 'mousedown', buttonsHandler, false);
|
|
797
|
+
this.addEvent(this.context.get('toolbar.sub.main'), 'click', toolbarHandler, false);
|
|
798
|
+
}
|
|
799
|
+
|
|
800
|
+
/** set response toolbar */
|
|
801
|
+
this.toolbar._setResponsive();
|
|
802
|
+
|
|
803
|
+
/** observer */
|
|
804
|
+
if (env.isResizeObserverSupported) {
|
|
805
|
+
this._toolbarObserver = new ResizeObserver(() => {
|
|
806
|
+
_w.setTimeout(() => {
|
|
807
|
+
this.toolbar.resetResponsiveToolbar();
|
|
808
|
+
}, 0);
|
|
809
|
+
});
|
|
810
|
+
this._wwFrameObserver = new ResizeObserver((entries) => {
|
|
811
|
+
_w.setTimeout(() => {
|
|
812
|
+
entries.forEach((e) => {
|
|
813
|
+
this.editor.__callResizeFunction(this.frameRoots.get(e.target.getAttribute('data-root-key')), -1, e);
|
|
814
|
+
});
|
|
815
|
+
}, 0);
|
|
816
|
+
});
|
|
817
|
+
}
|
|
818
|
+
|
|
819
|
+
/** modal outside click */
|
|
820
|
+
if (this.options.get('closeModalOutsideClick')) {
|
|
821
|
+
this.addEvent(
|
|
822
|
+
this.carrierWrapper.querySelector('.se-modal .se-modal-inner'),
|
|
823
|
+
'click',
|
|
824
|
+
(e) => {
|
|
825
|
+
if (e.target === this.carrierWrapper.querySelector('.se-modal .se-modal-inner')) {
|
|
826
|
+
this.ui._offCurrentModal();
|
|
827
|
+
}
|
|
828
|
+
},
|
|
829
|
+
false
|
|
830
|
+
);
|
|
831
|
+
}
|
|
832
|
+
|
|
833
|
+
/** global event */
|
|
834
|
+
this.addEvent(_w, 'resize', OnResize_window.bind(this), false);
|
|
835
|
+
this.addEvent(_w.visualViewport, 'resize', OnResize_viewport.bind(this), false);
|
|
836
|
+
this.addEvent(_w, 'scroll', OnScroll_window.bind(this), false);
|
|
837
|
+
if (isTouchDevice) {
|
|
838
|
+
this.addEvent(_w.visualViewport, 'scroll', OnMobileScroll_viewport.bind(this), false);
|
|
839
|
+
}
|
|
840
|
+
},
|
|
841
|
+
|
|
842
|
+
/**
|
|
843
|
+
* @private
|
|
844
|
+
* @this {EventManagerThis}
|
|
845
|
+
* @description Registers event listeners for the editor's frame, including text input, selection, and UI interactions.
|
|
846
|
+
* - Handles events inside an iframe or within the standard wysiwyg editor.
|
|
847
|
+
* @param {__se__FrameContext} fc The frame context object
|
|
848
|
+
*/
|
|
849
|
+
_addFrameEvents(fc) {
|
|
850
|
+
const isIframe = fc.get('options').get('iframe');
|
|
851
|
+
const eventWysiwyg = isIframe ? fc.get('_ww') : fc.get('wysiwyg');
|
|
852
|
+
fc.set('eventWysiwyg', eventWysiwyg);
|
|
853
|
+
const codeArea = fc.get('code');
|
|
854
|
+
const dragCursor = this.editor.carrierWrapper.querySelector('.se-drag-cursor');
|
|
855
|
+
|
|
856
|
+
/** editor area */
|
|
857
|
+
const wwMouseMove = OnMouseMove_wysiwyg.bind(this, fc);
|
|
858
|
+
this.addEvent(eventWysiwyg, 'mousemove', wwMouseMove, false);
|
|
859
|
+
this.addEvent(eventWysiwyg, 'mouseleave', OnMouseLeave_wysiwyg.bind(this, fc), false);
|
|
860
|
+
this.addEvent(eventWysiwyg, 'mousedown', OnMouseDown_wysiwyg.bind(this, fc), false);
|
|
861
|
+
this.addEvent(eventWysiwyg, 'mouseup', OnMouseUp_wysiwyg.bind(this, fc), false);
|
|
862
|
+
this.addEvent(eventWysiwyg, 'click', OnClick_wysiwyg.bind(this, fc), false);
|
|
863
|
+
this.addEvent(eventWysiwyg, 'input', OnInput_wysiwyg.bind(this, fc), false);
|
|
864
|
+
this.addEvent(eventWysiwyg, 'keydown', OnKeyDown_wysiwyg.bind(this, fc), false);
|
|
865
|
+
this.addEvent(eventWysiwyg, 'keyup', OnKeyUp_wysiwyg.bind(this, fc), false);
|
|
866
|
+
this.addEvent(eventWysiwyg, 'paste', OnPaste_wysiwyg.bind(this, fc), false);
|
|
867
|
+
this.addEvent(eventWysiwyg, 'copy', OnCopy_wysiwyg.bind(this, fc), false);
|
|
868
|
+
this.addEvent(eventWysiwyg, 'cut', OnCut_wysiwyg.bind(this, fc), false);
|
|
869
|
+
this.addEvent(
|
|
870
|
+
eventWysiwyg,
|
|
871
|
+
'dragover',
|
|
872
|
+
OnDragOver_wysiwyg.bind(this, fc, dragCursor, isIframe ? this.editor.frameContext.get('topArea') : null, !this.options.get('toolbar_container') && !this.editor.isBalloon && !this.editor.isInline),
|
|
873
|
+
false
|
|
874
|
+
);
|
|
875
|
+
this.addEvent(eventWysiwyg, 'dragend', OnDragEnd_wysiwyg.bind(this, dragCursor), false);
|
|
876
|
+
this.addEvent(eventWysiwyg, 'drop', OnDrop_wysiwyg.bind(this, fc, dragCursor), false);
|
|
877
|
+
this.addEvent(eventWysiwyg, 'scroll', OnScroll_wysiwyg.bind(this, fc, eventWysiwyg), { passive: true, capture: false });
|
|
878
|
+
this.addEvent(eventWysiwyg, 'focus', OnFocus_wysiwyg.bind(this, fc), false);
|
|
879
|
+
this.addEvent(eventWysiwyg, 'blur', OnBlur_wysiwyg.bind(this, fc), false);
|
|
880
|
+
this.addEvent(codeArea, 'mousedown', OnFocus_code.bind(this, fc), false);
|
|
881
|
+
|
|
882
|
+
/** drag handle */
|
|
883
|
+
const dragHandle = fc.get('wrapper').querySelector('.se-drag-handle');
|
|
884
|
+
this.addEvent(
|
|
885
|
+
dragHandle,
|
|
886
|
+
'wheel',
|
|
887
|
+
(event) => {
|
|
888
|
+
event.preventDefault();
|
|
889
|
+
this.component.deselect();
|
|
890
|
+
},
|
|
891
|
+
false
|
|
892
|
+
);
|
|
893
|
+
|
|
894
|
+
/** line breaker */
|
|
895
|
+
this.addEvent(fc.get('lineBreaker_t'), 'pointerdown', DisplayLineBreak.bind(this, 't'), false);
|
|
896
|
+
this.addEvent(fc.get('lineBreaker_b'), 'pointerdown', DisplayLineBreak.bind(this, 'b'), false);
|
|
897
|
+
|
|
898
|
+
/** Events are registered mobile. */
|
|
899
|
+
if (isTouchDevice) {
|
|
900
|
+
this.addEvent(eventWysiwyg, 'touchstart', wwMouseMove, {
|
|
901
|
+
passive: true,
|
|
902
|
+
capture: false
|
|
903
|
+
});
|
|
904
|
+
}
|
|
905
|
+
|
|
906
|
+
/** code view area auto line */
|
|
907
|
+
if (!this.options.get('hasCodeMirror')) {
|
|
908
|
+
const codeNumbers = fc.get('codeNumbers');
|
|
909
|
+
const cvAuthHeight = this.viewer._codeViewAutoHeight.bind(this.viewer, fc.get('code'), codeNumbers, this.editor.frameOptions.get('height') === 'auto');
|
|
910
|
+
|
|
911
|
+
this.addEvent(codeArea, 'keydown', cvAuthHeight, false);
|
|
912
|
+
this.addEvent(codeArea, 'keyup', cvAuthHeight, false);
|
|
913
|
+
this.addEvent(codeArea, 'paste', cvAuthHeight, false);
|
|
914
|
+
|
|
915
|
+
/** code view numbers */
|
|
916
|
+
if (codeNumbers) this.addEvent(codeArea, 'scroll', this.viewer._scrollLineNumbers.bind(codeArea, codeNumbers), false);
|
|
917
|
+
}
|
|
918
|
+
|
|
919
|
+
if (fc.has('statusbar')) this.__addStatusbarEvent(fc, fc.get('options'));
|
|
920
|
+
|
|
921
|
+
const OnScrollAbs = OnScroll_Abs.bind(this);
|
|
922
|
+
const scrollParents = dom.query.getScrollParents(fc.get('originElement'));
|
|
923
|
+
for (const parent of scrollParents) {
|
|
924
|
+
this.scrollparents.push(parent);
|
|
925
|
+
this.addEvent(parent, 'scroll', OnScrollAbs, false);
|
|
926
|
+
}
|
|
927
|
+
|
|
928
|
+
/** focus temp (mobile) */
|
|
929
|
+
this.addEvent(this.__focusTemp, 'focus', (e) => e.preventDefault(), false);
|
|
930
|
+
|
|
931
|
+
/** document event */
|
|
932
|
+
if (this.__eventDoc !== fc.get('_wd')) {
|
|
933
|
+
this.__eventDoc = fc.get('_wd');
|
|
934
|
+
this.addEvent(this.__eventDoc, 'selectionchange', OnSelectionchange_document.bind(this, this.__eventDoc), false);
|
|
935
|
+
}
|
|
936
|
+
},
|
|
937
|
+
|
|
938
|
+
/**
|
|
939
|
+
* @private
|
|
940
|
+
* @this {EventManagerThis}
|
|
941
|
+
* @description Adds event listeners for resizing the status bar if resizing is enabled.
|
|
942
|
+
* - If resizing is not enabled, applies a non-resizable class.
|
|
943
|
+
* @param {__se__FrameContext} fc The frame context object
|
|
944
|
+
* @param {__se__FrameOptions} fo The frame options object
|
|
945
|
+
*/
|
|
946
|
+
__addStatusbarEvent(fc, fo) {
|
|
947
|
+
if (/\d+/.test(fo.get('height')) && fo.get('statusbar_resizeEnable')) {
|
|
948
|
+
fo.set('__statusbarEvent', this.addEvent(fc.get('statusbar'), 'mousedown', OnMouseDown_statusbar.bind(this), false));
|
|
949
|
+
} else {
|
|
950
|
+
dom.utils.addClass(fc.get('statusbar'), 'se-resizing-none');
|
|
951
|
+
}
|
|
952
|
+
},
|
|
953
|
+
|
|
954
|
+
/**
|
|
955
|
+
* @private
|
|
956
|
+
* @this {EventManagerThis}
|
|
957
|
+
* @description Removes all registered event listeners from the editor.
|
|
958
|
+
* - Disconnects observers and clears stored event references.
|
|
959
|
+
*/
|
|
960
|
+
_removeAllEvents() {
|
|
961
|
+
for (let i = 0, len = this._events.length, e; i < len; i++) {
|
|
962
|
+
e = this._events[i];
|
|
963
|
+
e.target.removeEventListener(e.type, e.listener, e.useCapture);
|
|
964
|
+
}
|
|
965
|
+
|
|
966
|
+
this._events = [];
|
|
967
|
+
|
|
968
|
+
if (this._wwFrameObserver) {
|
|
969
|
+
this._wwFrameObserver.disconnect();
|
|
970
|
+
this._wwFrameObserver = null;
|
|
971
|
+
}
|
|
972
|
+
|
|
973
|
+
if (this._toolbarObserver) {
|
|
974
|
+
this._toolbarObserver.disconnect();
|
|
975
|
+
this._toolbarObserver = null;
|
|
976
|
+
}
|
|
977
|
+
},
|
|
978
|
+
|
|
979
|
+
/**
|
|
980
|
+
* @private
|
|
981
|
+
* @this {EventManagerThis}
|
|
982
|
+
* @description Adjusts the position of the editor's toolbar, controllers, and other floating elements based on scroll position.
|
|
983
|
+
* - Ensures UI elements maintain their intended relative positions when scrolling.
|
|
984
|
+
* @param {*} eventWysiwyg The wysiwyg event object containing scroll data (Window or element)
|
|
985
|
+
*/
|
|
986
|
+
_moveContainer(eventWysiwyg) {
|
|
987
|
+
const y = eventWysiwyg.scrollTop || eventWysiwyg.scrollY || 0;
|
|
988
|
+
const x = eventWysiwyg.scrollLeft || eventWysiwyg.scrollX || 0;
|
|
989
|
+
|
|
990
|
+
if (this.editor.isBalloon) {
|
|
991
|
+
this.context.get('toolbar.main').style.top = this.toolbar._balloonOffset.top - y + 'px';
|
|
992
|
+
this.context.get('toolbar.main').style.left = this.toolbar._balloonOffset.left - x + 'px';
|
|
993
|
+
} else if (this.editor.isSubBalloon) {
|
|
994
|
+
this.context.get('toolbar.sub.main').style.top = this.subToolbar._balloonOffset.top - y + 'px';
|
|
995
|
+
this.context.get('toolbar.sub.main').style.left = this.subToolbar._balloonOffset.left - x + 'px';
|
|
996
|
+
}
|
|
997
|
+
|
|
998
|
+
if (this.editor._controllerTargetContext !== this.editor.frameContext.get('topArea')) {
|
|
999
|
+
this.ui._offCurrentController();
|
|
1000
|
+
}
|
|
1001
|
+
|
|
1002
|
+
if (this.editor._lineBreaker_t) {
|
|
1003
|
+
const t_style = this.editor._lineBreaker_t.style;
|
|
1004
|
+
if (t_style.display !== 'none') {
|
|
1005
|
+
const t_offset = (this.editor._lineBreaker_t.getAttribute('data-offset') || ',').split(',');
|
|
1006
|
+
t_style.top = numbers.get(t_style.top, 0) - (y - numbers.get(t_offset[0], 0)) + 'px';
|
|
1007
|
+
t_style.left = numbers.get(t_style.left, 0) - (x - numbers.get(t_offset[1], 0)) + 'px';
|
|
1008
|
+
this.editor._lineBreaker_t.setAttribute('data-offset', y + ',' + x);
|
|
1009
|
+
}
|
|
1010
|
+
}
|
|
1011
|
+
|
|
1012
|
+
if (this.editor._lineBreaker_b) {
|
|
1013
|
+
const b_style = this.editor._lineBreaker_b.style;
|
|
1014
|
+
if (b_style.display !== 'none') {
|
|
1015
|
+
const b_offset = (this.editor._lineBreaker_b.getAttribute('data-offset') || ',').split(',');
|
|
1016
|
+
b_style.top = numbers.get(b_style.top, 0) - (y - numbers.get(b_offset[0], 0)) + 'px';
|
|
1017
|
+
b_style[b_offset[1]] = numbers.get(b_style[b_offset[1]], 0) - (x - numbers.get(b_offset[2], 0)) + 'px';
|
|
1018
|
+
this.editor._lineBreaker_b.setAttribute('data-offset', y + ',' + b_offset[1] + ',' + x);
|
|
1019
|
+
}
|
|
1020
|
+
}
|
|
1021
|
+
|
|
1022
|
+
const openCont = this.editor.opendControllers;
|
|
1023
|
+
for (let i = 0; i < openCont.length; i++) {
|
|
1024
|
+
if (!openCont[i].notInCarrier) continue;
|
|
1025
|
+
openCont[i].form.style.top = openCont[i].inst.__offset.top - y + 'px';
|
|
1026
|
+
openCont[i].form.style.left = openCont[i].inst.__offset.left - x + 'px';
|
|
1027
|
+
}
|
|
1028
|
+
},
|
|
1029
|
+
|
|
1030
|
+
/**
|
|
1031
|
+
* @private
|
|
1032
|
+
* @this {EventManagerThis}
|
|
1033
|
+
* @description Handles the scrolling of the editor container.
|
|
1034
|
+
* - Repositions open controllers if necessary.
|
|
1035
|
+
*/
|
|
1036
|
+
_scrollContainer() {
|
|
1037
|
+
if (this.menu.currentDropdownActiveButton && this.menu.currentDropdown) {
|
|
1038
|
+
this.menu._resetMenuPosition(this.menu.currentDropdownActiveButton, this.menu.currentDropdown);
|
|
1039
|
+
}
|
|
1040
|
+
|
|
1041
|
+
const openCont = this.editor.opendControllers;
|
|
1042
|
+
if (!openCont.length) return;
|
|
1043
|
+
|
|
1044
|
+
this.__rePositionController(openCont);
|
|
1045
|
+
},
|
|
1046
|
+
|
|
1047
|
+
/**
|
|
1048
|
+
* @private
|
|
1049
|
+
* @this {EventManagerThis}
|
|
1050
|
+
* @description Repositions the currently open controllers within the editor.
|
|
1051
|
+
* - Ensures elements are displayed in their correct positions after scrolling.
|
|
1052
|
+
* @param {Array<object>} cont List of controllers to reposition
|
|
1053
|
+
*/
|
|
1054
|
+
__rePositionController(cont) {
|
|
1055
|
+
if (_DragHandle.get('__dragMove')) _DragHandle.get('__dragMove')();
|
|
1056
|
+
for (let i = 0; i < cont.length; i++) {
|
|
1057
|
+
if (cont[i].notInCarrier) continue;
|
|
1058
|
+
cont[i].inst?.show();
|
|
1059
|
+
}
|
|
1060
|
+
},
|
|
1061
|
+
|
|
1062
|
+
/**
|
|
1063
|
+
* @private
|
|
1064
|
+
* @this {EventManagerThis}
|
|
1065
|
+
* @description Resets the frame status, adjusting toolbar and UI elements based on the current state.
|
|
1066
|
+
* - Handles inline editor adjustments, fullscreen mode, and responsive toolbar updates.
|
|
1067
|
+
*/
|
|
1068
|
+
_resetFrameStatus() {
|
|
1069
|
+
if (!env.isResizeObserverSupported) {
|
|
1070
|
+
this.toolbar.resetResponsiveToolbar();
|
|
1071
|
+
if (this.options.get('_subMode')) this.subToolbar.resetResponsiveToolbar();
|
|
1072
|
+
}
|
|
1073
|
+
|
|
1074
|
+
const toolbar = this.context.get('toolbar.main');
|
|
1075
|
+
const isToolbarHidden = toolbar.style.display === 'none' || (this.editor.isInline && !this.toolbar._inlineToolbarAttr.isShow);
|
|
1076
|
+
if (toolbar.offsetWidth === 0 && !isToolbarHidden) return;
|
|
1077
|
+
|
|
1078
|
+
const opendBrowser = this.editor.opendBrowser;
|
|
1079
|
+
if (opendBrowser && opendBrowser.area.style.display === 'block') {
|
|
1080
|
+
opendBrowser.body.style.maxHeight = dom.utils.getClientSize().h - opendBrowser.header.offsetHeight - 50 + 'px';
|
|
1081
|
+
}
|
|
1082
|
+
|
|
1083
|
+
if (this.menu.currentDropdownActiveButton && this.menu.currentDropdown) {
|
|
1084
|
+
this.menu._resetMenuPosition(this.menu.currentDropdownActiveButton, this.menu.currentDropdown);
|
|
1085
|
+
}
|
|
1086
|
+
|
|
1087
|
+
if (this.viewer._resetFullScreenHeight()) return;
|
|
1088
|
+
|
|
1089
|
+
const fc = this.editor.frameContext;
|
|
1090
|
+
if (fc.get('isCodeView') && this.editor.isInline) {
|
|
1091
|
+
this.toolbar._showInline();
|
|
1092
|
+
return;
|
|
1093
|
+
}
|
|
1094
|
+
|
|
1095
|
+
this.editor._iframeAutoHeight(fc);
|
|
1096
|
+
|
|
1097
|
+
if (this.toolbar._sticky) {
|
|
1098
|
+
this.context.get('toolbar.main').style.width = fc.get('topArea').offsetWidth - 2 + 'px';
|
|
1099
|
+
this.toolbar._resetSticky();
|
|
1100
|
+
}
|
|
1101
|
+
},
|
|
1102
|
+
|
|
1103
|
+
/**
|
|
1104
|
+
* @private
|
|
1105
|
+
* @this {EventManagerThis}
|
|
1106
|
+
* @description Synchronizes the selection state by resetting it on mouseup.
|
|
1107
|
+
* - Ensures selection updates correctly across different interactions.
|
|
1108
|
+
*/
|
|
1109
|
+
_setSelectionSync() {
|
|
1110
|
+
this.removeGlobalEvent(this.__selectionSyncEvent);
|
|
1111
|
+
this.__selectionSyncEvent = this.addGlobalEvent('mouseup', () => {
|
|
1112
|
+
this.selection._init();
|
|
1113
|
+
this.removeGlobalEvent(this.__selectionSyncEvent);
|
|
1114
|
+
});
|
|
1115
|
+
},
|
|
1116
|
+
|
|
1117
|
+
/**
|
|
1118
|
+
* @private
|
|
1119
|
+
* @this {EventManagerThis}
|
|
1120
|
+
* @description Retains the style nodes for formatting consistency when applying styles.
|
|
1121
|
+
* - Preserves nested styling by cloning and restructuring the style nodes.
|
|
1122
|
+
* @param {HTMLElement} formatEl The format element where styles should be retained
|
|
1123
|
+
* @param {Array<Node>} _styleNodes The list of style nodes to retain
|
|
1124
|
+
*/
|
|
1125
|
+
_retainStyleNodes(formatEl, _styleNodes) {
|
|
1126
|
+
const el = _styleNodes[0].cloneNode(false);
|
|
1127
|
+
let n = el;
|
|
1128
|
+
for (let i = 1, len = _styleNodes.length, t; i < len; i++) {
|
|
1129
|
+
t = _styleNodes[i].cloneNode(false);
|
|
1130
|
+
n.appendChild(t);
|
|
1131
|
+
n = t;
|
|
1132
|
+
}
|
|
1133
|
+
|
|
1134
|
+
const { parent, inner } = this.nodeTransform.createNestedNode(_styleNodes, null);
|
|
1135
|
+
const zeroWidth = dom.utils.createTextNode(unicode.zeroWidthSpace);
|
|
1136
|
+
inner.appendChild(zeroWidth);
|
|
1137
|
+
|
|
1138
|
+
formatEl.innerHTML = '';
|
|
1139
|
+
formatEl.appendChild(parent);
|
|
1140
|
+
|
|
1141
|
+
this.selection.setRange(zeroWidth, 1, zeroWidth, 1);
|
|
1142
|
+
},
|
|
1143
|
+
|
|
1144
|
+
/**
|
|
1145
|
+
* @private
|
|
1146
|
+
* @this {EventManagerThis}
|
|
1147
|
+
* @description Clears retained style nodes by replacing content with a single line break.
|
|
1148
|
+
* - Resets the selection to the start of the cleared element.
|
|
1149
|
+
* @param {HTMLElement} formatEl The format element where styles should be cleared
|
|
1150
|
+
*/
|
|
1151
|
+
_clearRetainStyleNodes(formatEl) {
|
|
1152
|
+
formatEl.innerHTML = '<br>';
|
|
1153
|
+
this.selection.setRange(formatEl, 0, formatEl, 0);
|
|
1154
|
+
},
|
|
1155
|
+
|
|
1156
|
+
/**
|
|
1157
|
+
* @private
|
|
1158
|
+
* @this {EventManagerThis}
|
|
1159
|
+
* @description Calls a registered plugin event and executes associated handlers.
|
|
1160
|
+
* - If any handler returns `false`, the event propagation stops.
|
|
1161
|
+
* @param {string} name The name of the plugin event
|
|
1162
|
+
* @param {{ frameContext: __se__FrameContext, event: Event, data?: string, line?: Node, range?: Range, file?: File, doc?: Document }} e The event object passed to the plugin event handler
|
|
1163
|
+
* @returns {boolean|undefined} Returns `false` if any handler stops the event, otherwise `undefined`
|
|
1164
|
+
*/
|
|
1165
|
+
_callPluginEvent(name, e) {
|
|
1166
|
+
const eventPlugins = this.editor._onPluginEvents.get(name);
|
|
1167
|
+
for (let i = 0, r; i < eventPlugins.length; i++) {
|
|
1168
|
+
r = eventPlugins[i](e);
|
|
1169
|
+
if (typeof r === 'boolean') return r;
|
|
1170
|
+
}
|
|
1171
|
+
},
|
|
1172
|
+
|
|
1173
|
+
/**
|
|
1174
|
+
* @private
|
|
1175
|
+
* @this {EventManagerThis}
|
|
1176
|
+
* @description Handles the selection of a component when hovering over it.
|
|
1177
|
+
* - If the target is a component, it ensures that the component is selected properly.
|
|
1178
|
+
* @param {Element} target The element being hovered over
|
|
1179
|
+
*/
|
|
1180
|
+
_overComponentSelect(target) {
|
|
1181
|
+
const figure = dom.query.getParentElement(target, dom.check.isFigure);
|
|
1182
|
+
let info = this.component.get(target);
|
|
1183
|
+
if (info || figure) {
|
|
1184
|
+
if (!info) info = this.component.get(figure);
|
|
1185
|
+
if (info && !dom.utils.hasClass(info.container, 'se-component-selected')) {
|
|
1186
|
+
this.ui._offCurrentController();
|
|
1187
|
+
_DragHandle.set('__overInfo', ON_OVER_COMPONENT);
|
|
1188
|
+
this.component.select(info.target, info.pluginName);
|
|
1189
|
+
}
|
|
1190
|
+
} else if (_DragHandle.get('__overInfo') !== null && !dom.utils.hasClass(target, 'se-drag-handle')) {
|
|
1191
|
+
this.component.__deselect();
|
|
1192
|
+
_DragHandle.set('__overInfo', null);
|
|
1193
|
+
}
|
|
1194
|
+
},
|
|
1195
|
+
|
|
1196
|
+
/**
|
|
1197
|
+
* @private
|
|
1198
|
+
* @this {EventManagerThis}
|
|
1199
|
+
* @description Removes input event listeners and resets input-related properties.
|
|
1200
|
+
*/
|
|
1201
|
+
__removeInput() {
|
|
1202
|
+
this._inputFocus = this.editor._preventBlur = false;
|
|
1203
|
+
this.__inputBlurEvent = this.removeEvent(this.__inputBlurEvent);
|
|
1204
|
+
this.__inputKeyEvent = this.removeEvent(this.__inputKeyEvent);
|
|
1205
|
+
this.__inputPlugin = null;
|
|
1206
|
+
},
|
|
1207
|
+
|
|
1208
|
+
/**
|
|
1209
|
+
* @private
|
|
1210
|
+
* @this {EventManagerThis}
|
|
1211
|
+
* @description Prevents the default behavior of the Enter key and refocuses the editor.
|
|
1212
|
+
* @param {Event} e The keyboard event
|
|
1213
|
+
*/
|
|
1214
|
+
__enterPrevent(e) {
|
|
1215
|
+
e.preventDefault();
|
|
1216
|
+
if (!isMobile) return;
|
|
1217
|
+
|
|
1218
|
+
this.__focusTemp.focus({ preventScroll: true });
|
|
1219
|
+
this.editor.frameContext.get('wysiwyg').focus({ preventScroll: true });
|
|
1220
|
+
},
|
|
1221
|
+
|
|
1222
|
+
/**
|
|
1223
|
+
* @private
|
|
1224
|
+
* @description Scrolls the editor view to the caret position after pressing Enter. (Ignored on mobile devices)
|
|
1225
|
+
* @this {EventManagerThis}
|
|
1226
|
+
* @param {*} range Range object
|
|
1227
|
+
*/
|
|
1228
|
+
__enterScrollTo(range) {
|
|
1229
|
+
this.editor._iframeAutoHeight(this.editor.frameContext);
|
|
1230
|
+
|
|
1231
|
+
// scroll to
|
|
1232
|
+
if (env.isMobile && this.scrollparents.length > 0) return;
|
|
1233
|
+
this.editor.selection.scrollTo(range, { behavior: 'auto', block: 'nearest', inline: 'nearest' });
|
|
1234
|
+
},
|
|
1235
|
+
|
|
1236
|
+
/**
|
|
1237
|
+
* @private
|
|
1238
|
+
* @description Focus Event Postprocessing
|
|
1239
|
+
* @this {EventManagerThis}
|
|
1240
|
+
* @param {__se__FrameContext} frameContext - frame context object
|
|
1241
|
+
* @param {Event} event - Event object
|
|
1242
|
+
*/
|
|
1243
|
+
__postFocusEvent(frameContext, event) {
|
|
1244
|
+
if (this.editor.isInline || this.editor.isBalloonAlways) this.toolbar.show();
|
|
1245
|
+
if (this.editor.isSubBalloonAlways) this.subToolbar.show();
|
|
1246
|
+
|
|
1247
|
+
// user event
|
|
1248
|
+
this.triggerEvent('onFocus', { frameContext, event });
|
|
1249
|
+
// plugin event
|
|
1250
|
+
this._callPluginEvent('onFocus', { frameContext, event });
|
|
1251
|
+
},
|
|
1252
|
+
|
|
1253
|
+
/**
|
|
1254
|
+
* @private
|
|
1255
|
+
* @description Blur Event Postprocessing
|
|
1256
|
+
* @this {EventManagerThis}
|
|
1257
|
+
* @param {__se__FrameContext} frameContext - frame context object
|
|
1258
|
+
* @param {Event} event - Event object
|
|
1259
|
+
*/
|
|
1260
|
+
__postBlurEvent(frameContext, event) {
|
|
1261
|
+
if (this.editor.isInline || this.editor.isBalloon) this._hideToolbar();
|
|
1262
|
+
if (this.editor.isSubBalloon) this._hideToolbar_sub();
|
|
1263
|
+
|
|
1264
|
+
// user event
|
|
1265
|
+
this.triggerEvent('onBlur', { frameContext, event });
|
|
1266
|
+
// plugin event
|
|
1267
|
+
this._callPluginEvent('onBlur', { frameContext, event });
|
|
1268
|
+
},
|
|
1269
|
+
|
|
1270
|
+
/**
|
|
1271
|
+
* @private
|
|
1272
|
+
* @description Records the current viewport size.
|
|
1273
|
+
* @this {EventManagerThis}
|
|
1274
|
+
*/
|
|
1275
|
+
__setViewportSize() {
|
|
1276
|
+
const currentVisibleHeight = (this.status.currentViewportHeight = numbers.get(_w.visualViewport.height, 0));
|
|
1277
|
+
this.editor.setRootCssVar('--se-var-viewport-height', `${currentVisibleHeight}px`);
|
|
1278
|
+
},
|
|
1279
|
+
|
|
1280
|
+
constructor: EventManager
|
|
1281
|
+
};
|
|
1282
|
+
|
|
1283
|
+
/**
|
|
1284
|
+
* @this {EventManagerThis}
|
|
1285
|
+
* @param {__se__FrameContext} frameContext - frame context object
|
|
1286
|
+
* @param {Element|Window} eventWysiwyg - wysiwyg event object
|
|
1287
|
+
* @param {Event} e - Event object
|
|
1288
|
+
*/
|
|
1289
|
+
function OnScroll_wysiwyg(frameContext, eventWysiwyg, e) {
|
|
1290
|
+
this._moveContainer(eventWysiwyg);
|
|
1291
|
+
this._scrollContainer();
|
|
1292
|
+
|
|
1293
|
+
// plugin event
|
|
1294
|
+
this._callPluginEvent('onScroll', { frameContext, event: e });
|
|
1295
|
+
|
|
1296
|
+
// document type page
|
|
1297
|
+
if (frameContext.has('documentType-use-page')) {
|
|
1298
|
+
frameContext.get('documentType').scrollPage();
|
|
1299
|
+
}
|
|
1300
|
+
|
|
1301
|
+
// user event
|
|
1302
|
+
this.triggerEvent('onScroll', { frameContext, event: e });
|
|
1303
|
+
}
|
|
1304
|
+
|
|
1305
|
+
/**
|
|
1306
|
+
* @this {EventManagerThis}
|
|
1307
|
+
* @param {__se__FrameContext} frameContext - frame context object
|
|
1308
|
+
* @param {Event} e - Event object
|
|
1309
|
+
*/
|
|
1310
|
+
function OnFocus_wysiwyg(frameContext, e) {
|
|
1311
|
+
if (this.selection.__iframeFocus || frameContext.get('isReadOnly') || frameContext.get('isDisabled')) {
|
|
1312
|
+
e.preventDefault();
|
|
1313
|
+
return false;
|
|
1314
|
+
}
|
|
1315
|
+
|
|
1316
|
+
this.status.hasFocus = true;
|
|
1317
|
+
this.component.__prevent = false;
|
|
1318
|
+
this.triggerEvent('onNativeFocus', { frameContext, event: e });
|
|
1319
|
+
|
|
1320
|
+
const rootKey = frameContext.get('key');
|
|
1321
|
+
|
|
1322
|
+
if (this._inputFocus) {
|
|
1323
|
+
if (this.editor.isInline) {
|
|
1324
|
+
this._w.setTimeout(() => {
|
|
1325
|
+
this.toolbar._showInline();
|
|
1326
|
+
}, 0);
|
|
1327
|
+
}
|
|
1328
|
+
return;
|
|
1329
|
+
}
|
|
1330
|
+
|
|
1331
|
+
if ((this.status.rootKey === rootKey && this.editor._preventBlur) || this.editor._preventFocus) return;
|
|
1332
|
+
this.editor._preventFocus = true;
|
|
1333
|
+
|
|
1334
|
+
const onSelected = this.editor.status.onSelected || this.editor.opendModal;
|
|
1335
|
+
this.ui._offCurrentController();
|
|
1336
|
+
|
|
1337
|
+
dom.utils.removeClass(this.editor.commandTargets.get('codeView'), 'active');
|
|
1338
|
+
dom.utils.setDisabled(this.editor._codeViewDisabledButtons, false);
|
|
1339
|
+
|
|
1340
|
+
this.editor.changeFrameContext(rootKey);
|
|
1341
|
+
this.history.resetButtons(rootKey, null);
|
|
1342
|
+
|
|
1343
|
+
if (!onSelected) {
|
|
1344
|
+
this.applyTagEffect();
|
|
1345
|
+
}
|
|
1346
|
+
|
|
1347
|
+
this._w.setTimeout(() => {
|
|
1348
|
+
this.__postFocusEvent(frameContext, e);
|
|
1349
|
+
}, 0);
|
|
1350
|
+
}
|
|
1351
|
+
|
|
1352
|
+
/**
|
|
1353
|
+
* @this {EventManagerThis}
|
|
1354
|
+
* @param {__se__FrameContext} frameContext - frame context object
|
|
1355
|
+
* @param {Event} e - Event object
|
|
1356
|
+
*/
|
|
1357
|
+
function OnBlur_wysiwyg(frameContext, e) {
|
|
1358
|
+
if (frameContext.get('isCodeView') || frameContext.get('isReadOnly') || frameContext.get('isDisabled')) return;
|
|
1359
|
+
|
|
1360
|
+
this.status.hasFocus = false;
|
|
1361
|
+
this.editor.effectNode = null;
|
|
1362
|
+
this.triggerEvent('onNativeBlur', { frameContext, event: e });
|
|
1363
|
+
|
|
1364
|
+
if (this._inputFocus || this.editor._preventBlur) return;
|
|
1365
|
+
this.editor._preventFocus = false;
|
|
1366
|
+
|
|
1367
|
+
this._setKeyEffect([]);
|
|
1368
|
+
|
|
1369
|
+
this.status.currentNodes = [];
|
|
1370
|
+
this.status.currentNodesMap = [];
|
|
1371
|
+
|
|
1372
|
+
this.editor.applyFrameRoots((root) => {
|
|
1373
|
+
if (root.get('navigation')) root.get('navigation').textContent = '';
|
|
1374
|
+
});
|
|
1375
|
+
|
|
1376
|
+
this.history.check(frameContext.get('key'), this.status._range);
|
|
1377
|
+
|
|
1378
|
+
this.__postBlurEvent(frameContext, e);
|
|
1379
|
+
}
|
|
1380
|
+
|
|
1381
|
+
/**
|
|
1382
|
+
* @this {EventManagerThis}
|
|
1383
|
+
* @param {MouseEvent} e - Event object
|
|
1384
|
+
*/
|
|
1385
|
+
function OnMouseDown_statusbar(e) {
|
|
1386
|
+
e.stopPropagation();
|
|
1387
|
+
this._resizeClientY = e.clientY;
|
|
1388
|
+
this.ui.enableBackWrapper('ns-resize');
|
|
1389
|
+
this.__resize_editor = this.addGlobalEvent('mousemove', __resizeEditor.bind(this));
|
|
1390
|
+
this.__close_move = this.addGlobalEvent('mouseup', __closeMove.bind(this));
|
|
1391
|
+
}
|
|
1392
|
+
|
|
1393
|
+
/**
|
|
1394
|
+
* @this {EventManagerThis}
|
|
1395
|
+
* @param {MouseEvent} e - Event object
|
|
1396
|
+
*/
|
|
1397
|
+
function __resizeEditor(e) {
|
|
1398
|
+
const fc = this.editor.frameContext;
|
|
1399
|
+
const resizeInterval = fc.get('wrapper').offsetHeight + (e.clientY - this._resizeClientY);
|
|
1400
|
+
const h = resizeInterval < fc.get('_minHeight') ? fc.get('_minHeight') : resizeInterval;
|
|
1401
|
+
fc.get('wysiwygFrame').style.height = fc.get('code').style.height = h + 'px';
|
|
1402
|
+
this._resizeClientY = e.clientY;
|
|
1403
|
+
if (!env.isResizeObserverSupported) this.editor.__callResizeFunction(fc, h, null);
|
|
1404
|
+
}
|
|
1405
|
+
|
|
1406
|
+
/**
|
|
1407
|
+
* @this {EventManagerThis}
|
|
1408
|
+
*/
|
|
1409
|
+
function __closeMove() {
|
|
1410
|
+
this.ui.disableBackWrapper();
|
|
1411
|
+
if (this.__resize_editor) this.__resize_editor = this.removeGlobalEvent(this.__resize_editor);
|
|
1412
|
+
if (this.__close_move) this.__close_move = this.removeGlobalEvent(this.__close_move);
|
|
1413
|
+
}
|
|
1414
|
+
|
|
1415
|
+
/**
|
|
1416
|
+
* @this {EventManagerThis}
|
|
1417
|
+
* @param {"t"|"b"} dir - Direction
|
|
1418
|
+
* @param {Event} e - Event object
|
|
1419
|
+
*/
|
|
1420
|
+
function DisplayLineBreak(dir, e) {
|
|
1421
|
+
e.preventDefault();
|
|
1422
|
+
|
|
1423
|
+
const component = this._lineBreakComp;
|
|
1424
|
+
if (!component) return;
|
|
1425
|
+
|
|
1426
|
+
const isList = dom.check.isListCell(component.parentElement);
|
|
1427
|
+
const format = dom.utils.createElement(isList ? 'BR' : dom.check.isTableCell(component.parentElement) ? 'DIV' : this.options.get('defaultLine'));
|
|
1428
|
+
if (!isList) format.innerHTML = '<br>';
|
|
1429
|
+
|
|
1430
|
+
if (this.editor.frameOptions.get('charCounter_type') === 'byte-html' && !this.char.check(format.outerHTML)) return;
|
|
1431
|
+
|
|
1432
|
+
component.parentNode.insertBefore(format, dir === 't' ? component : component.nextSibling);
|
|
1433
|
+
this.component.deselect();
|
|
1434
|
+
|
|
1435
|
+
try {
|
|
1436
|
+
const focusEl = isList ? format : format.firstChild;
|
|
1437
|
+
this.selection.setRange(focusEl, 1, focusEl, 1);
|
|
1438
|
+
this.history.push(false);
|
|
1439
|
+
} catch (err) {
|
|
1440
|
+
console.warn('[SUNEDITOR.lineBreaker.error]', err);
|
|
1441
|
+
}
|
|
1442
|
+
}
|
|
1443
|
+
|
|
1444
|
+
/**
|
|
1445
|
+
* @this {EventManagerThis}
|
|
1446
|
+
*/
|
|
1447
|
+
function OnResize_window() {
|
|
1448
|
+
this.status.initViewportHeight = _w.visualViewport.height;
|
|
1449
|
+
|
|
1450
|
+
if (!isMobile) {
|
|
1451
|
+
this.ui._offCurrentController();
|
|
1452
|
+
}
|
|
1453
|
+
|
|
1454
|
+
if (this.editor.isBalloon) this.toolbar.hide();
|
|
1455
|
+
else if (this.editor.isSubBalloon) this.subToolbar.hide();
|
|
1456
|
+
|
|
1457
|
+
this._resetFrameStatus();
|
|
1458
|
+
}
|
|
1459
|
+
|
|
1460
|
+
/**
|
|
1461
|
+
* @this {EventManagerThis}
|
|
1462
|
+
*/
|
|
1463
|
+
function OnResize_viewport() {
|
|
1464
|
+
if (isMobile && this.options.get('toolbar_sticky') > -1) {
|
|
1465
|
+
this.toolbar._resetSticky();
|
|
1466
|
+
this.editor.menu._restoreMenuPosition();
|
|
1467
|
+
}
|
|
1468
|
+
|
|
1469
|
+
this._scrollContainer();
|
|
1470
|
+
this.__setViewportSize();
|
|
1471
|
+
}
|
|
1472
|
+
|
|
1473
|
+
/**
|
|
1474
|
+
* @this {EventManagerThis}
|
|
1475
|
+
*/
|
|
1476
|
+
function OnScroll_window() {
|
|
1477
|
+
if (this.options.get('toolbar_sticky') > -1) {
|
|
1478
|
+
this.toolbar._resetSticky();
|
|
1479
|
+
}
|
|
1480
|
+
|
|
1481
|
+
if (this.editor.isBalloon && this.context.get('toolbar.main').style.display === 'block') {
|
|
1482
|
+
this.toolbar._setBalloonOffset(this.toolbar._balloonOffset.position === 'top');
|
|
1483
|
+
} else if (this.editor.isSubBalloon && this.context.get('toolbar.sub.main').style.display === 'block') {
|
|
1484
|
+
this.subToolbar._setBalloonOffset(this.subToolbar._balloonOffset.position === 'top');
|
|
1485
|
+
}
|
|
1486
|
+
|
|
1487
|
+
this._scrollContainer();
|
|
1488
|
+
|
|
1489
|
+
// document type page
|
|
1490
|
+
if (this.editor.frameContext.has('documentType-use-page')) {
|
|
1491
|
+
this.editor.frameContext.get('documentType').scrollWindow();
|
|
1492
|
+
}
|
|
1493
|
+
}
|
|
1494
|
+
|
|
1495
|
+
/**
|
|
1496
|
+
* @this {EventManagerThis}
|
|
1497
|
+
*/
|
|
1498
|
+
function OnMobileScroll_viewport() {
|
|
1499
|
+
if (this.options.get('toolbar_sticky') > -1) {
|
|
1500
|
+
this.toolbar._resetSticky();
|
|
1501
|
+
this.editor.menu._restoreMenuPosition();
|
|
1502
|
+
}
|
|
1503
|
+
}
|
|
1504
|
+
|
|
1505
|
+
/**
|
|
1506
|
+
* @this {EventManagerThis}
|
|
1507
|
+
* @param {Document} _wd - Wysiwyg document
|
|
1508
|
+
*/
|
|
1509
|
+
function OnSelectionchange_document(_wd) {
|
|
1510
|
+
if (this.editor._preventSelection) return;
|
|
1511
|
+
|
|
1512
|
+
const selection = _wd.getSelection();
|
|
1513
|
+
let anchorNode = selection.anchorNode;
|
|
1514
|
+
|
|
1515
|
+
this.editor.applyFrameRoots((root) => {
|
|
1516
|
+
if (anchorNode && root.get('wysiwyg').contains(anchorNode)) {
|
|
1517
|
+
if (root.get('isReadOnly') || root.get('isDisabled')) return;
|
|
1518
|
+
|
|
1519
|
+
anchorNode = null;
|
|
1520
|
+
this.selection._init();
|
|
1521
|
+
this.applyTagEffect();
|
|
1522
|
+
|
|
1523
|
+
// document type
|
|
1524
|
+
if (root.has('documentType-use-header')) {
|
|
1525
|
+
const el = dom.query.getParentElement(this.selection.selectionNode, this.format.isLine.bind(this.format));
|
|
1526
|
+
root.get('documentType').on(el);
|
|
1527
|
+
}
|
|
1528
|
+
}
|
|
1529
|
+
});
|
|
1530
|
+
}
|
|
1531
|
+
|
|
1532
|
+
/**
|
|
1533
|
+
* @this {EventManagerThis}
|
|
1534
|
+
*/
|
|
1535
|
+
function OnScroll_Abs() {
|
|
1536
|
+
this.menu.dropdownOff();
|
|
1537
|
+
this._scrollContainer();
|
|
1538
|
+
}
|
|
1539
|
+
|
|
1540
|
+
/**
|
|
1541
|
+
* @this {EventManagerThis}
|
|
1542
|
+
* @param {__se__FrameContext} frameContext - frame context object
|
|
1543
|
+
*/
|
|
1544
|
+
function OnFocus_code(frameContext) {
|
|
1545
|
+
this.editor.changeFrameContext(frameContext.get('key'));
|
|
1546
|
+
dom.utils.addClass(this.editor.commandTargets.get('codeView'), 'active');
|
|
1547
|
+
dom.utils.setDisabled(this.editor._codeViewDisabledButtons, true);
|
|
1548
|
+
}
|
|
1549
|
+
|
|
1550
|
+
export default EventManager;
|