suneditor 3.0.0-beta.2 → 3.0.0-beta.20
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CONTRIBUTING.md +186 -184
- package/LICENSE +21 -21
- package/README.md +157 -180
- package/dist/suneditor.min.css +1 -1
- package/dist/suneditor.min.js +1 -1
- package/package.json +126 -123
- package/src/assets/design/color.css +131 -121
- package/src/assets/design/index.css +3 -3
- package/src/assets/design/size.css +37 -35
- package/src/assets/design/typography.css +37 -37
- package/src/assets/icons/defaultIcons.js +247 -232
- package/src/assets/suneditor-contents.css +779 -778
- package/src/assets/suneditor.css +43 -35
- package/src/core/base/eventHandlers/handler_toolbar.js +135 -135
- package/src/core/base/eventHandlers/handler_ww_clipboard.js +56 -56
- package/src/core/base/eventHandlers/handler_ww_dragDrop.js +115 -113
- package/src/core/base/eventHandlers/handler_ww_key_input.js +1200 -1200
- package/src/core/base/eventHandlers/handler_ww_mouse.js +194 -194
- package/src/core/base/eventManager.js +1550 -1484
- package/src/core/base/history.js +355 -355
- package/src/core/class/char.js +163 -162
- package/src/core/class/component.js +856 -842
- package/src/core/class/format.js +3433 -3422
- package/src/core/class/html.js +1927 -1890
- package/src/core/class/menu.js +357 -346
- package/src/core/class/nodeTransform.js +424 -424
- package/src/core/class/offset.js +858 -891
- package/src/core/class/selection.js +710 -620
- package/src/core/class/shortcuts.js +98 -98
- package/src/core/class/toolbar.js +438 -430
- package/src/core/class/ui.js +424 -422
- package/src/core/class/viewer.js +750 -750
- package/src/core/editor.js +1810 -1708
- package/src/core/section/actives.js +268 -241
- package/src/core/section/constructor.js +1348 -1661
- package/src/core/section/context.js +102 -102
- package/src/core/section/documentType.js +582 -561
- package/src/core/section/options.js +367 -0
- package/src/core/util/instanceCheck.js +59 -0
- package/src/editorInjector/_classes.js +36 -36
- package/src/editorInjector/_core.js +92 -92
- package/src/editorInjector/index.js +75 -75
- package/src/events.js +634 -622
- package/src/helper/clipboard.js +59 -59
- package/src/helper/converter.js +586 -564
- package/src/helper/dom/domCheck.js +304 -304
- package/src/helper/dom/domQuery.js +677 -669
- package/src/helper/dom/domUtils.js +618 -557
- package/src/helper/dom/index.js +12 -12
- package/src/helper/env.js +249 -240
- package/src/helper/index.js +25 -25
- package/src/helper/keyCodeMap.js +183 -183
- package/src/helper/numbers.js +72 -72
- package/src/helper/unicode.js +47 -47
- package/src/langs/ckb.js +231 -231
- package/src/langs/cs.js +231 -231
- package/src/langs/da.js +231 -231
- package/src/langs/de.js +231 -231
- package/src/langs/en.js +230 -230
- package/src/langs/es.js +231 -231
- package/src/langs/fa.js +231 -231
- package/src/langs/fr.js +231 -231
- package/src/langs/he.js +231 -231
- package/src/langs/hu.js +230 -230
- package/src/langs/index.js +28 -28
- package/src/langs/it.js +231 -231
- package/src/langs/ja.js +230 -230
- package/src/langs/km.js +230 -230
- package/src/langs/ko.js +230 -230
- package/src/langs/lv.js +231 -231
- package/src/langs/nl.js +231 -231
- package/src/langs/pl.js +231 -231
- package/src/langs/pt_br.js +231 -231
- package/src/langs/ro.js +231 -231
- package/src/langs/ru.js +231 -231
- package/src/langs/se.js +231 -231
- package/src/langs/tr.js +231 -231
- package/src/langs/uk.js +231 -231
- package/src/langs/ur.js +231 -231
- package/src/langs/zh_cn.js +231 -231
- package/src/modules/ApiManager.js +191 -191
- package/src/modules/Browser.js +669 -667
- package/src/modules/ColorPicker.js +364 -362
- package/src/modules/Controller.js +474 -454
- package/src/modules/Figure.js +1620 -1617
- package/src/modules/FileManager.js +359 -359
- package/src/modules/HueSlider.js +577 -565
- package/src/modules/Modal.js +346 -346
- package/src/modules/ModalAnchorEditor.js +643 -643
- package/src/modules/SelectMenu.js +549 -549
- package/src/modules/_DragHandle.js +17 -17
- package/src/modules/index.js +14 -14
- package/src/plugins/browser/audioGallery.js +83 -83
- package/src/plugins/browser/fileBrowser.js +103 -103
- package/src/plugins/browser/fileGallery.js +83 -83
- package/src/plugins/browser/imageGallery.js +81 -81
- package/src/plugins/browser/videoGallery.js +103 -103
- package/src/plugins/command/blockquote.js +61 -60
- package/src/plugins/command/exportPDF.js +134 -134
- package/src/plugins/command/fileUpload.js +456 -456
- package/src/plugins/command/list_bulleted.js +149 -148
- package/src/plugins/command/list_numbered.js +152 -151
- package/src/plugins/dropdown/align.js +157 -155
- package/src/plugins/dropdown/backgroundColor.js +108 -104
- package/src/plugins/dropdown/font.js +141 -137
- package/src/plugins/dropdown/fontColor.js +109 -105
- package/src/plugins/dropdown/formatBlock.js +170 -178
- package/src/plugins/dropdown/hr.js +152 -152
- package/src/plugins/dropdown/layout.js +83 -83
- package/src/plugins/dropdown/lineHeight.js +131 -130
- package/src/plugins/dropdown/list.js +123 -122
- package/src/plugins/dropdown/paragraphStyle.js +138 -138
- package/src/plugins/dropdown/table.js +4110 -4000
- package/src/plugins/dropdown/template.js +83 -83
- package/src/plugins/dropdown/textStyle.js +149 -149
- package/src/plugins/field/mention.js +242 -242
- package/src/plugins/index.js +120 -120
- package/src/plugins/input/fontSize.js +414 -410
- package/src/plugins/input/pageNavigator.js +71 -70
- package/src/plugins/modal/audio.js +677 -677
- package/src/plugins/modal/drawing.js +537 -531
- package/src/plugins/modal/embed.js +886 -886
- package/src/plugins/modal/image.js +1377 -1376
- package/src/plugins/modal/link.js +248 -240
- package/src/plugins/modal/math.js +563 -563
- package/src/plugins/modal/video.js +1226 -1226
- package/src/plugins/popup/anchor.js +224 -222
- package/src/suneditor.js +114 -107
- package/src/themes/dark.css +132 -122
- package/src/typedef.js +132 -130
- package/types/assets/icons/defaultIcons.d.ts +8 -0
- package/types/core/base/eventManager.d.ts +29 -4
- package/types/core/class/char.d.ts +2 -1
- package/types/core/class/component.d.ts +1 -2
- package/types/core/class/format.d.ts +8 -1
- package/types/core/class/html.d.ts +8 -0
- package/types/core/class/menu.d.ts +8 -0
- package/types/core/class/offset.d.ts +24 -26
- package/types/core/class/selection.d.ts +2 -0
- package/types/core/class/toolbar.d.ts +6 -0
- package/types/core/class/ui.d.ts +1 -1
- package/types/core/editor.d.ts +34 -12
- package/types/core/section/constructor.d.ts +5 -638
- package/types/core/section/documentType.d.ts +12 -2
- package/types/core/section/options.d.ts +740 -0
- package/types/core/util/instanceCheck.d.ts +50 -0
- package/types/editorInjector/_core.d.ts +5 -5
- package/types/editorInjector/index.d.ts +2 -2
- package/types/events.d.ts +2 -0
- package/types/helper/converter.d.ts +9 -0
- package/types/helper/dom/domQuery.d.ts +5 -5
- package/types/helper/dom/domUtils.d.ts +8 -0
- package/types/helper/env.d.ts +6 -1
- package/types/helper/index.d.ts +4 -1
- package/types/index.d.ts +122 -120
- package/types/langs/_Lang.d.ts +194 -194
- package/types/modules/ColorPicker.d.ts +5 -1
- package/types/modules/Controller.d.ts +8 -4
- package/types/modules/Figure.d.ts +2 -1
- package/types/modules/HueSlider.d.ts +4 -1
- package/types/modules/SelectMenu.d.ts +1 -1
- package/types/plugins/command/blockquote.d.ts +1 -0
- package/types/plugins/command/list_bulleted.d.ts +1 -0
- package/types/plugins/command/list_numbered.d.ts +1 -0
- package/types/plugins/dropdown/align.d.ts +1 -0
- package/types/plugins/dropdown/backgroundColor.d.ts +1 -0
- package/types/plugins/dropdown/font.d.ts +1 -0
- package/types/plugins/dropdown/fontColor.d.ts +1 -0
- package/types/plugins/dropdown/formatBlock.d.ts +3 -2
- package/types/plugins/dropdown/lineHeight.d.ts +1 -0
- package/types/plugins/dropdown/list.d.ts +1 -0
- package/types/plugins/dropdown/table.d.ts +6 -0
- package/types/plugins/input/fontSize.d.ts +1 -0
- package/types/plugins/modal/drawing.d.ts +4 -0
- package/types/plugins/modal/link.d.ts +32 -15
- package/types/suneditor.d.ts +13 -9
- package/types/typedef.d.ts +8 -0
package/src/core/editor.js
CHANGED
|
@@ -1,1708 +1,1810 @@
|
|
|
1
|
-
import { env, converter, dom, numbers } from '../helper';
|
|
2
|
-
import Constructor, { InitOptions, UpdateButton, CreateShortcuts, CreateStatusbar
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import
|
|
6
|
-
import
|
|
7
|
-
import
|
|
8
|
-
import
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
import
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
import
|
|
19
|
-
import
|
|
20
|
-
import
|
|
21
|
-
import
|
|
22
|
-
import
|
|
23
|
-
import
|
|
24
|
-
import
|
|
25
|
-
import
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
/**
|
|
36
|
-
* @typedef {import('./section/
|
|
37
|
-
*/
|
|
38
|
-
|
|
39
|
-
/**
|
|
40
|
-
* @typedef {import('
|
|
41
|
-
*/
|
|
42
|
-
|
|
43
|
-
/**
|
|
44
|
-
* @
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
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
|
-
* @description Is
|
|
163
|
-
* @type {boolean}
|
|
164
|
-
*/
|
|
165
|
-
this.
|
|
166
|
-
|
|
167
|
-
/**
|
|
168
|
-
* @description Is
|
|
169
|
-
* @type {boolean}
|
|
170
|
-
*/
|
|
171
|
-
this.
|
|
172
|
-
|
|
173
|
-
/**
|
|
174
|
-
* @description Is balloon-always mode?
|
|
175
|
-
* @type {boolean}
|
|
176
|
-
*/
|
|
177
|
-
this.
|
|
178
|
-
|
|
179
|
-
/**
|
|
180
|
-
* @description Is
|
|
181
|
-
* @type {boolean}
|
|
182
|
-
*/
|
|
183
|
-
this.
|
|
184
|
-
|
|
185
|
-
/**
|
|
186
|
-
* @description Is subToolbar balloon-always mode?
|
|
187
|
-
* @type {boolean}
|
|
188
|
-
*/
|
|
189
|
-
this.
|
|
190
|
-
|
|
191
|
-
/**
|
|
192
|
-
* @description
|
|
193
|
-
* @type {
|
|
194
|
-
*/
|
|
195
|
-
this.
|
|
196
|
-
|
|
197
|
-
/**
|
|
198
|
-
* @description All command buttons map
|
|
199
|
-
* @type {Map<string, HTMLElement>}
|
|
200
|
-
*/
|
|
201
|
-
this.
|
|
202
|
-
|
|
203
|
-
/**
|
|
204
|
-
* @description
|
|
205
|
-
* @type {Map<string,
|
|
206
|
-
*/
|
|
207
|
-
this.
|
|
208
|
-
|
|
209
|
-
/**
|
|
210
|
-
* @description Shoutcuts
|
|
211
|
-
*
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
*
|
|
218
|
-
*
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
*
|
|
225
|
-
*
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
*
|
|
232
|
-
* @type {
|
|
233
|
-
*/
|
|
234
|
-
this.
|
|
235
|
-
|
|
236
|
-
/**
|
|
237
|
-
* @description
|
|
238
|
-
* @type {
|
|
239
|
-
*/
|
|
240
|
-
this.
|
|
241
|
-
|
|
242
|
-
/**
|
|
243
|
-
* @description Currently open "
|
|
244
|
-
* @type {
|
|
245
|
-
*/
|
|
246
|
-
this.
|
|
247
|
-
|
|
248
|
-
/**
|
|
249
|
-
* @description Currently open "Controller"
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
* @
|
|
256
|
-
*/
|
|
257
|
-
this.
|
|
258
|
-
|
|
259
|
-
/**
|
|
260
|
-
* @description
|
|
261
|
-
* @type {
|
|
262
|
-
*/
|
|
263
|
-
this.
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
this.
|
|
270
|
-
|
|
271
|
-
// ------
|
|
272
|
-
/** @description
|
|
273
|
-
this.
|
|
274
|
-
/** @description
|
|
275
|
-
this.
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
/** @description
|
|
279
|
-
this.
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
/** @description
|
|
283
|
-
this.
|
|
284
|
-
/** @description
|
|
285
|
-
this.
|
|
286
|
-
/** @description
|
|
287
|
-
this.
|
|
288
|
-
/** @description
|
|
289
|
-
this.
|
|
290
|
-
/** @description
|
|
291
|
-
this.
|
|
292
|
-
/** @description
|
|
293
|
-
this.
|
|
294
|
-
/** @description
|
|
295
|
-
this.
|
|
296
|
-
/** @description
|
|
297
|
-
this.
|
|
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
|
-
|
|
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
|
-
this.
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
if (
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
this.
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
this.
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
this.
|
|
596
|
-
break;
|
|
597
|
-
case '
|
|
598
|
-
this.
|
|
599
|
-
break;
|
|
600
|
-
case '
|
|
601
|
-
this.
|
|
602
|
-
break;
|
|
603
|
-
case '
|
|
604
|
-
this.
|
|
605
|
-
break;
|
|
606
|
-
case '
|
|
607
|
-
this.
|
|
608
|
-
break;
|
|
609
|
-
case '
|
|
610
|
-
this.
|
|
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
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
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
|
-
|
|
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
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
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
|
-
|
|
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
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
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
|
-
|
|
1070
|
-
/**
|
|
1071
|
-
* @
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
this.
|
|
1089
|
-
this.
|
|
1090
|
-
|
|
1091
|
-
|
|
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
|
-
|
|
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
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
:
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
//
|
|
1197
|
-
if (
|
|
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
|
-
* @private
|
|
1273
|
-
* @description
|
|
1274
|
-
* @param {
|
|
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
|
-
this.
|
|
1302
|
-
|
|
1303
|
-
this.
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
this.
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
|
|
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
|
-
|
|
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
|
-
this.
|
|
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
|
-
this.
|
|
1476
|
-
}
|
|
1477
|
-
},
|
|
1478
|
-
|
|
1479
|
-
/**
|
|
1480
|
-
* @private
|
|
1481
|
-
* @description
|
|
1482
|
-
*
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
converter.
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
},
|
|
1495
|
-
|
|
1496
|
-
/**
|
|
1497
|
-
* @private
|
|
1498
|
-
* @description
|
|
1499
|
-
* @param {
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
const
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
-
|
|
1512
|
-
|
|
1513
|
-
|
|
1514
|
-
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
|
|
1530
|
-
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
|
|
1584
|
-
|
|
1585
|
-
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
|
|
1599
|
-
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
|
|
1612
|
-
|
|
1613
|
-
|
|
1614
|
-
|
|
1615
|
-
|
|
1616
|
-
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
|
|
1622
|
-
|
|
1623
|
-
|
|
1624
|
-
|
|
1625
|
-
|
|
1626
|
-
|
|
1627
|
-
|
|
1628
|
-
|
|
1629
|
-
|
|
1630
|
-
|
|
1631
|
-
|
|
1632
|
-
|
|
1633
|
-
|
|
1634
|
-
this.
|
|
1635
|
-
|
|
1636
|
-
//
|
|
1637
|
-
this.
|
|
1638
|
-
|
|
1639
|
-
|
|
1640
|
-
|
|
1641
|
-
|
|
1642
|
-
|
|
1643
|
-
|
|
1644
|
-
this.
|
|
1645
|
-
|
|
1646
|
-
|
|
1647
|
-
|
|
1648
|
-
|
|
1649
|
-
|
|
1650
|
-
|
|
1651
|
-
|
|
1652
|
-
|
|
1653
|
-
|
|
1654
|
-
|
|
1655
|
-
|
|
1656
|
-
|
|
1657
|
-
|
|
1658
|
-
|
|
1659
|
-
|
|
1660
|
-
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
this.
|
|
1667
|
-
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
|
|
1671
|
-
|
|
1672
|
-
|
|
1673
|
-
|
|
1674
|
-
|
|
1675
|
-
|
|
1676
|
-
|
|
1677
|
-
|
|
1678
|
-
|
|
1679
|
-
|
|
1680
|
-
|
|
1681
|
-
|
|
1682
|
-
|
|
1683
|
-
|
|
1684
|
-
|
|
1685
|
-
|
|
1686
|
-
this.
|
|
1687
|
-
|
|
1688
|
-
|
|
1689
|
-
|
|
1690
|
-
|
|
1691
|
-
|
|
1692
|
-
|
|
1693
|
-
|
|
1694
|
-
|
|
1695
|
-
|
|
1696
|
-
|
|
1697
|
-
|
|
1698
|
-
|
|
1699
|
-
|
|
1700
|
-
|
|
1701
|
-
|
|
1702
|
-
|
|
1703
|
-
|
|
1704
|
-
|
|
1705
|
-
|
|
1706
|
-
|
|
1707
|
-
|
|
1708
|
-
|
|
1
|
+
import { env, converter, dom, numbers } from '../helper';
|
|
2
|
+
import Constructor, { InitOptions, UpdateButton, CreateShortcuts, CreateStatusbar } from './section/constructor';
|
|
3
|
+
import { OPTION_FRAME_FIXED_FLAG, OPTION_FIXED_FLAG } from './section/options';
|
|
4
|
+
import { UpdateStatusbarContext } from './section/context';
|
|
5
|
+
import { BASIC_COMMANDS, ACTIVE_EVENT_COMMANDS, SELECT_ALL, DIR_BTN_ACTIVE, SAVE, COPY_FORMAT, FONT_STYLE, PAGE_BREAK } from './section/actives';
|
|
6
|
+
import History from './base/history';
|
|
7
|
+
import EventManager from './base/eventManager';
|
|
8
|
+
import Events from '../events';
|
|
9
|
+
import DocumentType from './section/documentType';
|
|
10
|
+
|
|
11
|
+
// util
|
|
12
|
+
import InstanceCheck from './util/instanceCheck';
|
|
13
|
+
|
|
14
|
+
// class injector
|
|
15
|
+
import ClassInjector from '../editorInjector/_classes';
|
|
16
|
+
|
|
17
|
+
// classes
|
|
18
|
+
import Char from './class/char';
|
|
19
|
+
import Component from './class/component';
|
|
20
|
+
import Format from './class/format';
|
|
21
|
+
import HTML from './class/html';
|
|
22
|
+
import Menu from './class/menu';
|
|
23
|
+
import NodeTransform from './class/nodeTransform';
|
|
24
|
+
import Offset from './class/offset';
|
|
25
|
+
import Selection_ from './class/selection';
|
|
26
|
+
import Shortcuts from './class/shortcuts';
|
|
27
|
+
import Toolbar from './class/toolbar';
|
|
28
|
+
import UI from './class/ui';
|
|
29
|
+
import Viewer from './class/viewer';
|
|
30
|
+
|
|
31
|
+
const COMMAND_BUTTONS = '.se-menu-list .se-toolbar-btn[data-command]';
|
|
32
|
+
const DISABLE_BUTTONS_CODEVIEW = `${COMMAND_BUTTONS}:not([class~="se-code-view-enabled"]):not([data-type="MORE"])`;
|
|
33
|
+
const DISABLE_BUTTONS_CONTROLLER = `${COMMAND_BUTTONS}:not([class~="se-component-enabled"]):not([data-type="MORE"])`;
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* @typedef {import('./section/options').EditorInitOptions} EditorInitOptions_editor
|
|
37
|
+
*/
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* @typedef {import('./section/options').EditorFrameOptions} EditorFrameOptions_editor
|
|
41
|
+
*/
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* @typedef {import('../modules/Controller').ControllerInfo} ControllerInfo_editor
|
|
45
|
+
*/
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* @constructor
|
|
49
|
+
* @description SunEditor constructor function.
|
|
50
|
+
* @param {Array<{target: Element, key: *, options: EditorFrameOptions_editor}>} multiTargets Target element
|
|
51
|
+
* @param {EditorInitOptions_editor} options options
|
|
52
|
+
*/
|
|
53
|
+
function Editor(multiTargets, options) {
|
|
54
|
+
const _d = multiTargets[0].target.ownerDocument || env._d;
|
|
55
|
+
const _w = _d.defaultView || env._w;
|
|
56
|
+
const product = Constructor(multiTargets, options);
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* @description Frame root key array
|
|
60
|
+
* @type {Array<*>}
|
|
61
|
+
*/
|
|
62
|
+
this.rootKeys = product.rootKeys;
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* @description Frame root map
|
|
66
|
+
* @type {Map<*, __se__FrameContext>}
|
|
67
|
+
*/
|
|
68
|
+
this.frameRoots = product.frameRoots;
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* @description Editor context object
|
|
72
|
+
* @type {__se__Context}
|
|
73
|
+
*/
|
|
74
|
+
this.context = product.context;
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* @description Current focusing frame context
|
|
78
|
+
* @type {__se__FrameContext}
|
|
79
|
+
*/
|
|
80
|
+
this.frameContext = new Map();
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* @description Current focusing frame context options
|
|
84
|
+
* @type {__se__FrameOptions}
|
|
85
|
+
*/
|
|
86
|
+
this.frameOptions = new Map();
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* @description Document object
|
|
90
|
+
* @type {Document}
|
|
91
|
+
*/
|
|
92
|
+
this._d = _d;
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* @description Window object
|
|
96
|
+
* @type {Window}
|
|
97
|
+
*/
|
|
98
|
+
this._w = _w;
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* @description Controllers carrier
|
|
102
|
+
* @type {HTMLElement}
|
|
103
|
+
*/
|
|
104
|
+
this.carrierWrapper = product.carrierWrapper;
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* @description Editor options
|
|
108
|
+
* @type {Map<string, *>}
|
|
109
|
+
*/
|
|
110
|
+
this.options = product.options;
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* @description Plugins
|
|
114
|
+
* @type {Object<string, *>}
|
|
115
|
+
*/
|
|
116
|
+
this.plugins = product.plugins || {};
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* @description Events object, call by triggerEvent function
|
|
120
|
+
* @type {Object<string, *>}
|
|
121
|
+
*/
|
|
122
|
+
this.events = null;
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* @description Call the event function by injecting self: this.
|
|
126
|
+
* @type {(eventName: string, ...args: *) => Promise<*>}
|
|
127
|
+
*/
|
|
128
|
+
this.triggerEvent = null;
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* @description Default icons object
|
|
132
|
+
* @type {Object<string, string>}
|
|
133
|
+
*/
|
|
134
|
+
this.icons = product.icons;
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* @description loaded language
|
|
138
|
+
* @type {Object<string, *>}
|
|
139
|
+
*/
|
|
140
|
+
this.lang = product.lang;
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* @description Variables used internally in editor operation
|
|
144
|
+
* @type {__se__EditorStatus}
|
|
145
|
+
*/
|
|
146
|
+
this.status = {
|
|
147
|
+
hasFocus: false,
|
|
148
|
+
tabSize: 4,
|
|
149
|
+
indentSize: 25,
|
|
150
|
+
codeIndentSize: 2,
|
|
151
|
+
currentNodes: [],
|
|
152
|
+
currentNodesMap: [],
|
|
153
|
+
initViewportHeight: 0,
|
|
154
|
+
currentViewportHeight: 0,
|
|
155
|
+
onSelected: false,
|
|
156
|
+
rootKey: product.rootId,
|
|
157
|
+
_range: null,
|
|
158
|
+
_onMousedown: false
|
|
159
|
+
};
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* @description Is classic mode?
|
|
163
|
+
* @type {boolean}
|
|
164
|
+
*/
|
|
165
|
+
this.isClassic = false;
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* @description Is inline mode?
|
|
169
|
+
* @type {boolean}
|
|
170
|
+
*/
|
|
171
|
+
this.isInline = false;
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* @description Is balloon|balloon-always mode?
|
|
175
|
+
* @type {boolean}
|
|
176
|
+
*/
|
|
177
|
+
this.isBalloon = false;
|
|
178
|
+
|
|
179
|
+
/**
|
|
180
|
+
* @description Is balloon-always mode?
|
|
181
|
+
* @type {boolean}
|
|
182
|
+
*/
|
|
183
|
+
this.isBalloonAlways = false;
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
* @description Is subToolbar balloon|balloon-always mode?
|
|
187
|
+
* @type {boolean}
|
|
188
|
+
*/
|
|
189
|
+
this.isSubBalloon = false;
|
|
190
|
+
|
|
191
|
+
/**
|
|
192
|
+
* @description Is subToolbar balloon-always mode?
|
|
193
|
+
* @type {boolean}
|
|
194
|
+
*/
|
|
195
|
+
this.isSubBalloonAlways = false;
|
|
196
|
+
|
|
197
|
+
/**
|
|
198
|
+
* @description All command buttons map
|
|
199
|
+
* @type {Map<string, HTMLElement>}
|
|
200
|
+
*/
|
|
201
|
+
this.allCommandButtons = new Map();
|
|
202
|
+
|
|
203
|
+
/**
|
|
204
|
+
* @description All command buttons map
|
|
205
|
+
* @type {Map<string, HTMLElement>}
|
|
206
|
+
*/
|
|
207
|
+
this.subAllCommandButtons = new Map();
|
|
208
|
+
|
|
209
|
+
/**
|
|
210
|
+
* @description Shoutcuts key map
|
|
211
|
+
* @type {Map<string, *>}
|
|
212
|
+
*/
|
|
213
|
+
this.shortcutsKeyMap = new Map();
|
|
214
|
+
|
|
215
|
+
/**
|
|
216
|
+
* @description Shoutcuts reverse key array
|
|
217
|
+
* - An array of key codes generated with the reverseButtons option, used to reverse the action for a specific key combination.
|
|
218
|
+
* @type {Array<string>}
|
|
219
|
+
*/
|
|
220
|
+
this.reverseKeys = [];
|
|
221
|
+
|
|
222
|
+
/**
|
|
223
|
+
* @description A map with the plugin's buttons having an "active" method and the default command buttons with an "active" action.
|
|
224
|
+
* - Each button is contained in an array.
|
|
225
|
+
* @type {Map<string, Array<HTMLButtonElement>>}
|
|
226
|
+
*/
|
|
227
|
+
this.commandTargets = new Map();
|
|
228
|
+
|
|
229
|
+
/**
|
|
230
|
+
* @description Plugins array with "active" method.
|
|
231
|
+
* - "activeCommands" runs the "add" method when creating the editor.
|
|
232
|
+
* @type {Array<string>}
|
|
233
|
+
*/
|
|
234
|
+
this.activeCommands = null;
|
|
235
|
+
|
|
236
|
+
/**
|
|
237
|
+
* @description The selection node (selection.getNode()) to which the effect was last applied
|
|
238
|
+
* @type {Node|null}
|
|
239
|
+
*/
|
|
240
|
+
this.effectNode = null;
|
|
241
|
+
|
|
242
|
+
/**
|
|
243
|
+
* @description Currently open "Modal" instance
|
|
244
|
+
* @type {*}
|
|
245
|
+
*/
|
|
246
|
+
this.opendModal = null;
|
|
247
|
+
|
|
248
|
+
/**
|
|
249
|
+
* @description Currently open "Controller" info array
|
|
250
|
+
* @type {Array<ControllerInfo_editor>}
|
|
251
|
+
*/
|
|
252
|
+
this.opendControllers = [];
|
|
253
|
+
|
|
254
|
+
/**
|
|
255
|
+
* @description Currently open "Controller" caller plugin name
|
|
256
|
+
*/
|
|
257
|
+
this.currentControllerName = '';
|
|
258
|
+
|
|
259
|
+
/**
|
|
260
|
+
* @description Currently open "Browser" instance
|
|
261
|
+
* @type {*}
|
|
262
|
+
*/
|
|
263
|
+
this.opendBrowser = null;
|
|
264
|
+
|
|
265
|
+
/**
|
|
266
|
+
* @description Whether "SelectMenu" is open
|
|
267
|
+
* @type {boolean}
|
|
268
|
+
*/
|
|
269
|
+
this.selectMenuOn = false;
|
|
270
|
+
|
|
271
|
+
// ------ base ------
|
|
272
|
+
/** @description History class instance @type {ReturnType<typeof import('./base/history').default>} */
|
|
273
|
+
this.history = null;
|
|
274
|
+
/** @description EventManager class instance @type {import('./base/eventManager').default} */
|
|
275
|
+
this.eventManager = null;
|
|
276
|
+
|
|
277
|
+
// ----- util -----
|
|
278
|
+
/** @description iframe-safe instanceof check utility class @type {import('./util/instanceCheck').default} */
|
|
279
|
+
this.instanceCheck = null;
|
|
280
|
+
|
|
281
|
+
// ------ class ------
|
|
282
|
+
/** @description Toolbar class instance @type {import('./class/toolbar').default} */
|
|
283
|
+
this.toolbar = null;
|
|
284
|
+
/** @description Sub-Toolbar class instance @type {import('./class/toolbar').default|null} */
|
|
285
|
+
this.subToolbar = null;
|
|
286
|
+
/** @description Char class instance @type {import('./class/char').default} */
|
|
287
|
+
this.char = null;
|
|
288
|
+
/** @description Component class instance @type {import('./class/component').default} */
|
|
289
|
+
this.component = null;
|
|
290
|
+
/** @description Format class instance @type {import('./class/format').default} */
|
|
291
|
+
this.format = null;
|
|
292
|
+
/** @description HTML class instance @type {import('./class/html').default} */
|
|
293
|
+
this.html = null;
|
|
294
|
+
/** @description Menu class instance @type {import('./class/menu').default} */
|
|
295
|
+
this.menu = null;
|
|
296
|
+
/** @description NodeTransform class instance @type {import('./class/nodeTransform').default} */
|
|
297
|
+
this.nodeTransform = null;
|
|
298
|
+
/** @description Offset class instance @type {import('./class/offset').default} */
|
|
299
|
+
this.offset = null;
|
|
300
|
+
/** @description Selection class instance @type {import('./class/selection').default} */
|
|
301
|
+
this.selection = null;
|
|
302
|
+
/** @description Shortcuts class instance @type {import('./class/shortcuts').default} */
|
|
303
|
+
this.shortcuts = null;
|
|
304
|
+
/** @description UI class instance @type {import('./class/ui').default} */
|
|
305
|
+
this.ui = null;
|
|
306
|
+
/** @description Viewer class instance @type {import('./class/viewer').default} */
|
|
307
|
+
this.viewer = null;
|
|
308
|
+
|
|
309
|
+
// ------------------------------------------------------- private properties -------------------------------------------------------
|
|
310
|
+
/**
|
|
311
|
+
* @description Line breaker (top)
|
|
312
|
+
* @type {HTMLElement}
|
|
313
|
+
*/
|
|
314
|
+
this._lineBreaker_t = null;
|
|
315
|
+
|
|
316
|
+
/**
|
|
317
|
+
* @description Line breaker (bottom)
|
|
318
|
+
* @type {HTMLElement}
|
|
319
|
+
*/
|
|
320
|
+
this._lineBreaker_b = null;
|
|
321
|
+
|
|
322
|
+
/**
|
|
323
|
+
* @description Closest ShadowRoot to editor if found
|
|
324
|
+
* @type {ShadowRoot & { getSelection?: () => Selection }} - Chromium-based browsers (Chrome, Edge, etc.) has a getSelection method on the ShadowRoot
|
|
325
|
+
*/
|
|
326
|
+
this._shadowRoot = null;
|
|
327
|
+
|
|
328
|
+
/**
|
|
329
|
+
* @description Plugin call event map
|
|
330
|
+
* @type {Map<string, Array<((...args: *) => *) & { index: number }>>}
|
|
331
|
+
*/
|
|
332
|
+
this._onPluginEvents = null;
|
|
333
|
+
|
|
334
|
+
/**
|
|
335
|
+
* @description Copy format info
|
|
336
|
+
* - eventManager.__cacheStyleNodes copied
|
|
337
|
+
* @type {Array<Node>|null}
|
|
338
|
+
*/
|
|
339
|
+
this._onCopyFormatInfo = null;
|
|
340
|
+
|
|
341
|
+
/**
|
|
342
|
+
* @description Copy format init method
|
|
343
|
+
* @type {(...args: *) => *|null}
|
|
344
|
+
*/
|
|
345
|
+
this._onCopyFormatInitMethod = null;
|
|
346
|
+
|
|
347
|
+
/**
|
|
348
|
+
* @description Controller target's frame div (editor.frameContext.get('topArea'))
|
|
349
|
+
* @type {HTMLElement|null}
|
|
350
|
+
*/
|
|
351
|
+
this._controllerTargetContext = null;
|
|
352
|
+
|
|
353
|
+
/**
|
|
354
|
+
* @description List of buttons that are disabled when "controller" is opened
|
|
355
|
+
* @type {Array<HTMLButtonElement|HTMLInputElement>}
|
|
356
|
+
*/
|
|
357
|
+
this._controllerOnDisabledButtons = [];
|
|
358
|
+
|
|
359
|
+
/**
|
|
360
|
+
* @description List of buttons that are disabled when "codeView" mode opened
|
|
361
|
+
* @type {Array<HTMLButtonElement|HTMLInputElement>}
|
|
362
|
+
*/
|
|
363
|
+
this._codeViewDisabledButtons = [];
|
|
364
|
+
|
|
365
|
+
/**
|
|
366
|
+
* @description List of buttons to run plugins in the toolbar
|
|
367
|
+
* @type {Array<HTMLElement>}
|
|
368
|
+
*/
|
|
369
|
+
this._pluginCallButtons = product.pluginCallButtons;
|
|
370
|
+
|
|
371
|
+
/**
|
|
372
|
+
* @description List of buttons to run plugins in the Sub-Toolbar
|
|
373
|
+
* @type {Array<HTMLElement>}
|
|
374
|
+
*/
|
|
375
|
+
this._pluginCallButtons_sub = product.pluginCallButtons_sub;
|
|
376
|
+
|
|
377
|
+
/**
|
|
378
|
+
* @description Responsive Toolbar Button Structure array
|
|
379
|
+
* @type {Array<*>}
|
|
380
|
+
*/
|
|
381
|
+
this._responsiveButtons = product.responsiveButtons;
|
|
382
|
+
|
|
383
|
+
/**
|
|
384
|
+
* @description Responsive Sub-Toolbar Button Structure array
|
|
385
|
+
* @type {Array<*>}
|
|
386
|
+
*/
|
|
387
|
+
this._responsiveButtons_sub = product.responsiveButtons_sub;
|
|
388
|
+
|
|
389
|
+
/**
|
|
390
|
+
* @description Variable that controls the "blur" event in the editor of inline or balloon mode when the focus is moved to dropdown
|
|
391
|
+
* @type {boolean}
|
|
392
|
+
*/
|
|
393
|
+
this._notHideToolbar = false;
|
|
394
|
+
|
|
395
|
+
/**
|
|
396
|
+
* @description Variables for controlling blur events
|
|
397
|
+
* @type {boolean}
|
|
398
|
+
*/
|
|
399
|
+
this._preventBlur = false;
|
|
400
|
+
|
|
401
|
+
/**
|
|
402
|
+
* @description Variables for controlling focus events
|
|
403
|
+
* @type {boolean}
|
|
404
|
+
*/
|
|
405
|
+
this._preventFocus = false;
|
|
406
|
+
|
|
407
|
+
/**
|
|
408
|
+
* @description Variables for controlling selection change events
|
|
409
|
+
*/
|
|
410
|
+
this._preventSelection = false;
|
|
411
|
+
|
|
412
|
+
/**
|
|
413
|
+
* @description If true, initialize all indexes of image, video information
|
|
414
|
+
* @type {boolean}
|
|
415
|
+
*/
|
|
416
|
+
this._componentsInfoInit = true;
|
|
417
|
+
|
|
418
|
+
/**
|
|
419
|
+
* @description If true, reset all indexes of image, video information
|
|
420
|
+
* @type {boolean}
|
|
421
|
+
*/
|
|
422
|
+
this._componentsInfoReset = false;
|
|
423
|
+
|
|
424
|
+
/**
|
|
425
|
+
* @description plugin retainFormat info Map()
|
|
426
|
+
* @type {Map<string, { key: string, method: (...args: *) => * }>}
|
|
427
|
+
*/
|
|
428
|
+
this._MELInfo = null;
|
|
429
|
+
|
|
430
|
+
/**
|
|
431
|
+
* @description Properties for managing files in the "FileManager" module
|
|
432
|
+
* @type {Array<*>}
|
|
433
|
+
*/
|
|
434
|
+
this._fileInfoPluginsCheck = null;
|
|
435
|
+
|
|
436
|
+
/**
|
|
437
|
+
* @description Properties for managing files in the "FileManager" module
|
|
438
|
+
* @type {Array<*>}
|
|
439
|
+
*/
|
|
440
|
+
this._fileInfoPluginsReset = null;
|
|
441
|
+
|
|
442
|
+
/**
|
|
443
|
+
* @description Variables for file component management
|
|
444
|
+
* @type {Object<string, *>}
|
|
445
|
+
*/
|
|
446
|
+
this._fileManager = {
|
|
447
|
+
tags: null,
|
|
448
|
+
regExp: null,
|
|
449
|
+
pluginRegExp: null,
|
|
450
|
+
pluginMap: null
|
|
451
|
+
};
|
|
452
|
+
|
|
453
|
+
/**
|
|
454
|
+
* @description Variables for managing the components
|
|
455
|
+
* @type {Array<*>}
|
|
456
|
+
*/
|
|
457
|
+
this._componentManager = [];
|
|
458
|
+
|
|
459
|
+
/**
|
|
460
|
+
* @description Current Figure container.
|
|
461
|
+
* @type {HTMLElement|null}
|
|
462
|
+
*/
|
|
463
|
+
this._figureContainer = null;
|
|
464
|
+
|
|
465
|
+
/**
|
|
466
|
+
* @description Origin options
|
|
467
|
+
* @type {EditorInitOptions_editor}
|
|
468
|
+
*/
|
|
469
|
+
this._originOptions = options;
|
|
470
|
+
|
|
471
|
+
/** ----- Create editor ------------------------------------------------------------ */
|
|
472
|
+
this.__Create(options);
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
Editor.prototype = {
|
|
476
|
+
/**
|
|
477
|
+
* @description If the plugin is not added, add the plugin and call the 'add' function.
|
|
478
|
+
* - If the plugin is added call callBack function.
|
|
479
|
+
* @param {string} pluginName The name of the plugin to call
|
|
480
|
+
* @param {?Array<HTMLElement>} targets Plugin target button (This is not necessary if you have a button list when creating the editor)
|
|
481
|
+
* @param {?Object<string, *>} pluginOptions Plugin's options
|
|
482
|
+
*/
|
|
483
|
+
registerPlugin(pluginName, targets, pluginOptions) {
|
|
484
|
+
let plugin = this.plugins[pluginName];
|
|
485
|
+
if (!plugin) {
|
|
486
|
+
throw Error(`[SUNEDITOR.registerPlugin.fail] The called plugin does not exist or is in an invalid format. (pluginName: "${pluginName}")`);
|
|
487
|
+
} else if (typeof this.plugins[pluginName] === 'function') {
|
|
488
|
+
plugin = this.plugins[pluginName] = new this.plugins[pluginName](this, pluginOptions || {});
|
|
489
|
+
if (typeof plugin.init === 'function') plugin.init();
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
if (targets) {
|
|
493
|
+
for (let i = 0, len = targets.length; i < len; i++) {
|
|
494
|
+
UpdateButton(targets[i], plugin, this.icons, this.lang);
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
if (!this.activeCommands.includes(pluginName) && typeof this.plugins[pluginName].active === 'function') {
|
|
498
|
+
this.activeCommands.push(pluginName);
|
|
499
|
+
}
|
|
500
|
+
}
|
|
501
|
+
},
|
|
502
|
+
|
|
503
|
+
/**
|
|
504
|
+
* @description Run plugin calls and basic commands.
|
|
505
|
+
* @param {string} command Command string
|
|
506
|
+
* @param {string} type Display type string ('command', 'dropdown', 'modal', 'container')
|
|
507
|
+
* @param {?Node=} button The element of command button
|
|
508
|
+
*/
|
|
509
|
+
run(command, type, button) {
|
|
510
|
+
if (type) {
|
|
511
|
+
if (/more/i.test(type)) {
|
|
512
|
+
const toolbar = dom.query.getParentElement(button, '.se-toolbar');
|
|
513
|
+
const toolInst = dom.utils.hasClass(toolbar, 'se-toolbar-sub') ? this.subToolbar : this.toolbar;
|
|
514
|
+
if (button !== toolInst.currentMoreLayerActiveButton) {
|
|
515
|
+
const layer = toolbar.querySelector('.' + command);
|
|
516
|
+
if (layer) {
|
|
517
|
+
toolInst._moreLayerOn(button, layer);
|
|
518
|
+
toolInst._showBalloon();
|
|
519
|
+
toolInst._showInline();
|
|
520
|
+
}
|
|
521
|
+
dom.utils.addClass(button, 'on');
|
|
522
|
+
} else if (toolInst.currentMoreLayerActiveButton) {
|
|
523
|
+
toolInst._moreLayerOff();
|
|
524
|
+
toolInst._showBalloon();
|
|
525
|
+
toolInst._showInline();
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
this.viewer._resetFullScreenHeight();
|
|
529
|
+
return;
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
if (/container/.test(type) && (this.menu.targetMap[command] === null || button !== this.menu.currentContainerActiveButton)) {
|
|
533
|
+
this.menu.containerOn(button);
|
|
534
|
+
return;
|
|
535
|
+
}
|
|
536
|
+
|
|
537
|
+
if (this.frameContext.get('isReadOnly') && dom.utils.arrayIncludes(this._controllerOnDisabledButtons, button)) return;
|
|
538
|
+
if (/dropdown/.test(type) && (this.menu.targetMap[command] === null || button !== this.menu.currentDropdownActiveButton)) {
|
|
539
|
+
this.menu.dropdownOn(button);
|
|
540
|
+
return;
|
|
541
|
+
} else if (/modal/.test(type)) {
|
|
542
|
+
this.plugins[command].open(button);
|
|
543
|
+
return;
|
|
544
|
+
} else if (/command/.test(type)) {
|
|
545
|
+
this.plugins[command].action(button);
|
|
546
|
+
} else if (/browser/.test(type)) {
|
|
547
|
+
this.plugins[command].open(null);
|
|
548
|
+
} else if (/popup/.test(type)) {
|
|
549
|
+
this.plugins[command].show();
|
|
550
|
+
}
|
|
551
|
+
} else if (command) {
|
|
552
|
+
this.commandHandler(command, button);
|
|
553
|
+
}
|
|
554
|
+
|
|
555
|
+
if (/dropdown/.test(type)) {
|
|
556
|
+
this.menu.dropdownOff();
|
|
557
|
+
} else if (!/command/.test(type)) {
|
|
558
|
+
this.menu.dropdownOff();
|
|
559
|
+
this.menu.containerOff();
|
|
560
|
+
}
|
|
561
|
+
},
|
|
562
|
+
|
|
563
|
+
/**
|
|
564
|
+
* @description Execute default command of command button
|
|
565
|
+
* - (selectAll, codeView, fullScreen, indent, outdent, undo, redo, removeFormat, print, preview, showBlocks, save, bold, underline, italic, strike, subscript, superscript, copy, cut, paste)
|
|
566
|
+
* @param {string} command Property of command button (data-value)
|
|
567
|
+
* @param {?Node=} button Command button
|
|
568
|
+
* @returns {Promise<void>}
|
|
569
|
+
*/
|
|
570
|
+
async commandHandler(command, button) {
|
|
571
|
+
if (this.frameContext.get('isReadOnly') && !/copy|cut|selectAll|codeView|fullScreen|print|preview|showBlocks/.test(command)) return;
|
|
572
|
+
|
|
573
|
+
switch (command) {
|
|
574
|
+
case 'selectAll':
|
|
575
|
+
SELECT_ALL(this);
|
|
576
|
+
break;
|
|
577
|
+
case 'copy': {
|
|
578
|
+
const range = this.selection.getRange();
|
|
579
|
+
if (range.collapsed) break;
|
|
580
|
+
|
|
581
|
+
const container = dom.utils.createElement('div', null, range.cloneContents());
|
|
582
|
+
await this.html.copy(container.innerHTML);
|
|
583
|
+
|
|
584
|
+
break;
|
|
585
|
+
}
|
|
586
|
+
case 'newDocument':
|
|
587
|
+
this.html.set(`<${this.options.get('defaultLine')}><br></${this.options.get('defaultLine')}>`);
|
|
588
|
+
this.focus();
|
|
589
|
+
this.history.push(false);
|
|
590
|
+
break;
|
|
591
|
+
case 'codeView':
|
|
592
|
+
this.viewer.codeView(!this.frameContext.get('isCodeView'));
|
|
593
|
+
break;
|
|
594
|
+
case 'fullScreen':
|
|
595
|
+
this.viewer.fullScreen(!this.frameContext.get('isFullScreen'));
|
|
596
|
+
break;
|
|
597
|
+
case 'indent':
|
|
598
|
+
this.format.indent();
|
|
599
|
+
break;
|
|
600
|
+
case 'outdent':
|
|
601
|
+
this.format.outdent();
|
|
602
|
+
break;
|
|
603
|
+
case 'undo':
|
|
604
|
+
this.history.undo();
|
|
605
|
+
break;
|
|
606
|
+
case 'redo':
|
|
607
|
+
this.history.redo();
|
|
608
|
+
break;
|
|
609
|
+
case 'removeFormat':
|
|
610
|
+
this.format.removeInlineElement();
|
|
611
|
+
this.focus();
|
|
612
|
+
break;
|
|
613
|
+
case 'print':
|
|
614
|
+
this.viewer.print();
|
|
615
|
+
break;
|
|
616
|
+
case 'preview':
|
|
617
|
+
this.viewer.preview();
|
|
618
|
+
break;
|
|
619
|
+
case 'showBlocks':
|
|
620
|
+
this.viewer.showBlocks(!this.frameContext.get('isShowBlocks'));
|
|
621
|
+
break;
|
|
622
|
+
case 'dir':
|
|
623
|
+
this.setDir(this.options.get('_rtl') ? 'ltr' : 'rtl');
|
|
624
|
+
break;
|
|
625
|
+
case 'dir_ltr':
|
|
626
|
+
this.setDir('ltr');
|
|
627
|
+
break;
|
|
628
|
+
case 'dir_rtl':
|
|
629
|
+
this.setDir('rtl');
|
|
630
|
+
break;
|
|
631
|
+
case 'save':
|
|
632
|
+
await SAVE(this);
|
|
633
|
+
break;
|
|
634
|
+
case 'copyFormat':
|
|
635
|
+
COPY_FORMAT(this, button);
|
|
636
|
+
break;
|
|
637
|
+
case 'pageBreak':
|
|
638
|
+
PAGE_BREAK(this);
|
|
639
|
+
break;
|
|
640
|
+
case 'pageUp':
|
|
641
|
+
this.frameContext.get('documentType').pageUp();
|
|
642
|
+
break;
|
|
643
|
+
case 'pageDown':
|
|
644
|
+
this.frameContext.get('documentType').pageDown();
|
|
645
|
+
break;
|
|
646
|
+
default:
|
|
647
|
+
FONT_STYLE(this, command);
|
|
648
|
+
}
|
|
649
|
+
},
|
|
650
|
+
|
|
651
|
+
/**
|
|
652
|
+
* @description Execute "editor.run" with command button.
|
|
653
|
+
* @param {Node} target Command target
|
|
654
|
+
*/
|
|
655
|
+
runFromTarget(target) {
|
|
656
|
+
if (dom.check.isInputElement(target)) return;
|
|
657
|
+
|
|
658
|
+
const targetBtn = /** @type {HTMLButtonElement} */ (dom.query.getCommandTarget(target));
|
|
659
|
+
if (!targetBtn) return;
|
|
660
|
+
|
|
661
|
+
const command = targetBtn.getAttribute('data-command');
|
|
662
|
+
const type = targetBtn.getAttribute('data-type');
|
|
663
|
+
|
|
664
|
+
if (!command && !type) return;
|
|
665
|
+
if (targetBtn.disabled) return;
|
|
666
|
+
|
|
667
|
+
this.run(command, type, target);
|
|
668
|
+
},
|
|
669
|
+
|
|
670
|
+
/**
|
|
671
|
+
* @description It is executed by inserting the button of commandTargets as the argument value of the "f" function.
|
|
672
|
+
* - "func" is called as long as the button array's length.
|
|
673
|
+
* @param {string} cmd data-command
|
|
674
|
+
* @param {(...args: *) => *} func Function.
|
|
675
|
+
*/
|
|
676
|
+
applyCommandTargets(cmd, func) {
|
|
677
|
+
if (this.commandTargets.has(cmd)) {
|
|
678
|
+
this.commandTargets.get(cmd).forEach(func);
|
|
679
|
+
}
|
|
680
|
+
},
|
|
681
|
+
|
|
682
|
+
/**
|
|
683
|
+
* @description Execute a function by traversing all root targets.
|
|
684
|
+
* @param {(...args: *) => *} f Function
|
|
685
|
+
*/
|
|
686
|
+
applyFrameRoots(f) {
|
|
687
|
+
this.frameRoots.forEach(f);
|
|
688
|
+
},
|
|
689
|
+
|
|
690
|
+
/**
|
|
691
|
+
* @description Checks if the content of the editor is empty.
|
|
692
|
+
* - Display criteria for "placeholder".
|
|
693
|
+
* @param {?__se__FrameContext=} fc Frame context, if not present, currently selected frame context.
|
|
694
|
+
* @returns {boolean}
|
|
695
|
+
*/
|
|
696
|
+
isEmpty(fc) {
|
|
697
|
+
fc = fc || this.frameContext;
|
|
698
|
+
const wysiwyg = fc.get('wysiwyg');
|
|
699
|
+
return dom.check.isZeroWidth(wysiwyg.textContent) && !wysiwyg.querySelector(this.options.get('allowedEmptyTags')) && (wysiwyg.innerText.match(/\n/g) || '').length <= 1;
|
|
700
|
+
},
|
|
701
|
+
|
|
702
|
+
/**
|
|
703
|
+
* @description Set direction to "rtl" or "ltr".
|
|
704
|
+
* @param {string} dir "rtl" or "ltr"
|
|
705
|
+
*/
|
|
706
|
+
setDir(dir) {
|
|
707
|
+
const rtl = dir === 'rtl';
|
|
708
|
+
if (this.options.get('_rtl') === rtl) return;
|
|
709
|
+
|
|
710
|
+
try {
|
|
711
|
+
this.options.set('_rtl', rtl);
|
|
712
|
+
this.ui._offCurrentController();
|
|
713
|
+
|
|
714
|
+
const fc = this.frameContext;
|
|
715
|
+
const plugins = this.plugins;
|
|
716
|
+
for (const k in plugins) {
|
|
717
|
+
if (typeof plugins[k].setDir === 'function') plugins[k].setDir(dir);
|
|
718
|
+
}
|
|
719
|
+
|
|
720
|
+
const toolbarWrapper = this.context.get('toolbar._wrapper');
|
|
721
|
+
const statusbarWrapper = this.context.get('statusbar._wrapper');
|
|
722
|
+
if (rtl) {
|
|
723
|
+
this.applyFrameRoots((e) => {
|
|
724
|
+
dom.utils.addClass([e.get('topArea'), e.get('wysiwyg'), e.get('documentTypePageMirror')], 'se-rtl');
|
|
725
|
+
});
|
|
726
|
+
dom.utils.addClass([this.carrierWrapper, toolbarWrapper, statusbarWrapper], 'se-rtl');
|
|
727
|
+
} else {
|
|
728
|
+
this.applyFrameRoots((e) => {
|
|
729
|
+
dom.utils.removeClass([e.get('topArea'), e.get('wysiwyg'), e.get('documentTypePageMirror')], 'se-rtl');
|
|
730
|
+
});
|
|
731
|
+
dom.utils.removeClass([this.carrierWrapper, toolbarWrapper, statusbarWrapper], 'se-rtl');
|
|
732
|
+
}
|
|
733
|
+
|
|
734
|
+
const lineNodes = dom.query.getListChildren(fc.get('wysiwyg'), (current) => {
|
|
735
|
+
return this.format.isLine(current) && !!(current.style.marginRight || current.style.marginLeft || current.style.textAlign);
|
|
736
|
+
});
|
|
737
|
+
|
|
738
|
+
for (let i = 0, n, l, r; (n = lineNodes[i]); i++) {
|
|
739
|
+
n = lineNodes[i];
|
|
740
|
+
// indent margin
|
|
741
|
+
r = n.style.marginRight;
|
|
742
|
+
l = n.style.marginLeft;
|
|
743
|
+
if (r || l) {
|
|
744
|
+
n.style.marginRight = l;
|
|
745
|
+
n.style.marginLeft = r;
|
|
746
|
+
}
|
|
747
|
+
// text align
|
|
748
|
+
r = n.style.textAlign;
|
|
749
|
+
if (r === 'left') n.style.textAlign = 'right';
|
|
750
|
+
else if (r === 'right') n.style.textAlign = 'left';
|
|
751
|
+
}
|
|
752
|
+
|
|
753
|
+
DIR_BTN_ACTIVE(this, rtl);
|
|
754
|
+
|
|
755
|
+
// document type
|
|
756
|
+
if (fc.has('documentType-use-header')) {
|
|
757
|
+
if (rtl) fc.get('wrapper').appendChild(fc.get('documentTypeInner'));
|
|
758
|
+
else fc.get('wrapper').insertBefore(fc.get('documentTypeInner'), fc.get('wysiwygFrame'));
|
|
759
|
+
}
|
|
760
|
+
if (fc.has('documentType-use-page')) {
|
|
761
|
+
if (rtl) fc.get('wrapper').insertBefore(fc.get('documentTypePage'), fc.get('wysiwygFrame'));
|
|
762
|
+
else fc.get('wrapper').appendChild(fc.get('documentTypePage'));
|
|
763
|
+
}
|
|
764
|
+
|
|
765
|
+
if (this.isBalloon) this.toolbar._showBalloon();
|
|
766
|
+
else if (this.isSubBalloon) this.subToolbar._showBalloon();
|
|
767
|
+
} catch (e) {
|
|
768
|
+
this.options.set('_rtl', !rtl);
|
|
769
|
+
console.warn(`[SUNEDITOR.setDir.fail] ${e.toString()}`);
|
|
770
|
+
}
|
|
771
|
+
|
|
772
|
+
this.effectNode = null;
|
|
773
|
+
this.eventManager.applyTagEffect();
|
|
774
|
+
},
|
|
775
|
+
|
|
776
|
+
/**
|
|
777
|
+
* @description Add or reset option property (Editor is reloaded)
|
|
778
|
+
* @param {EditorInitOptions_editor} newOptions Options
|
|
779
|
+
*/
|
|
780
|
+
resetOptions(newOptions) {
|
|
781
|
+
this.viewer.codeView(false);
|
|
782
|
+
this.viewer.showBlocks(false);
|
|
783
|
+
|
|
784
|
+
const rootDiff = new Map();
|
|
785
|
+
const frameRoots = this.frameRoots;
|
|
786
|
+
const newRoots = [];
|
|
787
|
+
const newRootKeys = new Map();
|
|
788
|
+
|
|
789
|
+
// frame roots
|
|
790
|
+
const nRoot = {};
|
|
791
|
+
for (const k in newOptions) {
|
|
792
|
+
if (OPTION_FRAME_FIXED_FLAG[k] === undefined) continue;
|
|
793
|
+
nRoot[k] = newOptions[k];
|
|
794
|
+
delete newOptions[k];
|
|
795
|
+
}
|
|
796
|
+
for (const rootKey of frameRoots.keys()) {
|
|
797
|
+
newOptions[rootKey || ''] = { ...nRoot, ...newOptions[rootKey || ''] };
|
|
798
|
+
}
|
|
799
|
+
|
|
800
|
+
// check reoption validation
|
|
801
|
+
const newOptionKeys = Object.keys(newOptions);
|
|
802
|
+
CheckResetKeys(newOptionKeys, this.plugins, '');
|
|
803
|
+
if (newOptionKeys.length === 0) return;
|
|
804
|
+
|
|
805
|
+
if (frameRoots.size === 1) {
|
|
806
|
+
newOptionKeys.unshift(null);
|
|
807
|
+
}
|
|
808
|
+
|
|
809
|
+
// option merge
|
|
810
|
+
const _originOptions = [this._originOptions, newOptions].reduce((init, option) => {
|
|
811
|
+
for (const key in option) {
|
|
812
|
+
if (frameRoots.has(key || null)) {
|
|
813
|
+
RestoreFrameOptions(key, option, frameRoots, rootDiff, newRootKeys, newRoots);
|
|
814
|
+
} else {
|
|
815
|
+
init[key] = option[key];
|
|
816
|
+
}
|
|
817
|
+
}
|
|
818
|
+
return init;
|
|
819
|
+
}, {});
|
|
820
|
+
|
|
821
|
+
// init options
|
|
822
|
+
const options = this.options;
|
|
823
|
+
const newO = InitOptions(_originOptions, newRoots, this.plugins);
|
|
824
|
+
const newOptionMap = newO.o;
|
|
825
|
+
const newFrameMap = newO.frameMap;
|
|
826
|
+
/** --------- [root start] --------- */
|
|
827
|
+
for (let i = 0, len = newOptionKeys.length, k; i < len; i++) {
|
|
828
|
+
k = newOptionKeys[i] || null;
|
|
829
|
+
|
|
830
|
+
if (newRootKeys.has(k)) {
|
|
831
|
+
const diff = rootDiff.get(k);
|
|
832
|
+
const fc = frameRoots.get(k);
|
|
833
|
+
const originOptions = fc.get('options');
|
|
834
|
+
const newRootOptions = newFrameMap.get(k);
|
|
835
|
+
|
|
836
|
+
// --- set options : fc ---
|
|
837
|
+
fc.set('options', newRootOptions);
|
|
838
|
+
|
|
839
|
+
// statusbar-changed
|
|
840
|
+
if (diff.has('statusbar-changed')) {
|
|
841
|
+
// statusbar
|
|
842
|
+
dom.utils.removeItem(fc.get('statusbar'));
|
|
843
|
+
if (newRootOptions.get('statusbar')) {
|
|
844
|
+
const statusbar = CreateStatusbar(newRootOptions, null).statusbar;
|
|
845
|
+
fc.get('container').appendChild(statusbar);
|
|
846
|
+
UpdateStatusbarContext(statusbar, fc);
|
|
847
|
+
this.eventManager.__addStatusbarEvent(fc, newRootOptions);
|
|
848
|
+
} else {
|
|
849
|
+
this.eventManager.removeEvent(originOptions.get('__statusbarEvent'));
|
|
850
|
+
newRootOptions.set('__statusbarEvent', null);
|
|
851
|
+
UpdateStatusbarContext(null, fc);
|
|
852
|
+
}
|
|
853
|
+
// charCounter
|
|
854
|
+
if (fc.get('statusbar')) {
|
|
855
|
+
this.char.display(fc);
|
|
856
|
+
}
|
|
857
|
+
}
|
|
858
|
+
|
|
859
|
+
// iframe's options
|
|
860
|
+
if (diff.has('iframe_attributes')) {
|
|
861
|
+
const frame = fc.get('wysiwygFrame');
|
|
862
|
+
const originAttr = originOptions.get('iframe_attributes');
|
|
863
|
+
const newAttr = newRootOptions.get('iframe_attributes');
|
|
864
|
+
for (const origin_k in originAttr) frame.removeAttribute(origin_k, originAttr[origin_k]);
|
|
865
|
+
for (const new_k in newAttr) frame.setAttribute(new_k, newAttr[new_k]);
|
|
866
|
+
}
|
|
867
|
+
|
|
868
|
+
if (diff.has('iframe_cssFileName')) {
|
|
869
|
+
const docHead = fc.get('_wd').head;
|
|
870
|
+
const links = docHead.getElementsByTagName('link');
|
|
871
|
+
while (links[0]) docHead.removeChild(links[0]);
|
|
872
|
+
const parseDocument = new DOMParser().parseFromString(converter._setIframeStyleLinks(newRootOptions.get('iframe_cssFileName')), 'text/html');
|
|
873
|
+
const newLinks = parseDocument.head.children;
|
|
874
|
+
const sTag = docHead.querySelector('style');
|
|
875
|
+
while (newLinks[0]) docHead.insertBefore(newLinks[0], sTag);
|
|
876
|
+
}
|
|
877
|
+
|
|
878
|
+
if (diff.has('placeholder')) {
|
|
879
|
+
fc.get('placeholder').textContent = newRootOptions.get('placeholder');
|
|
880
|
+
}
|
|
881
|
+
|
|
882
|
+
// frame styles
|
|
883
|
+
this.ui.setEditorStyle(newRootOptions.get('editorStyle'), fc);
|
|
884
|
+
|
|
885
|
+
// frame attributes
|
|
886
|
+
const frame = fc.get('wysiwyg');
|
|
887
|
+
const originAttr = originOptions.get('editableFrameAttributes');
|
|
888
|
+
const newAttr = newRootOptions.get('editableFrameAttributes');
|
|
889
|
+
for (const origin_k in originAttr) frame.removeAttribute(origin_k, originAttr[origin_k]);
|
|
890
|
+
for (const new_k in newAttr) frame.setAttribute(new_k, newAttr[new_k]);
|
|
891
|
+
|
|
892
|
+
continue;
|
|
893
|
+
}
|
|
894
|
+
/** --------- [root end] --------- */
|
|
895
|
+
|
|
896
|
+
// --- set options ---
|
|
897
|
+
options.set(k, newOptionMap.get(k));
|
|
898
|
+
|
|
899
|
+
/** Options that require a function call */
|
|
900
|
+
switch (k) {
|
|
901
|
+
case 'theme': {
|
|
902
|
+
this.ui.setTheme(options.get('theme'));
|
|
903
|
+
break;
|
|
904
|
+
}
|
|
905
|
+
case 'events': {
|
|
906
|
+
const events = options.get('events');
|
|
907
|
+
for (const name in events) {
|
|
908
|
+
this.events[name] = events[name];
|
|
909
|
+
}
|
|
910
|
+
break;
|
|
911
|
+
}
|
|
912
|
+
case 'autoStyleify': {
|
|
913
|
+
this.html.__resetAutoStyleify(options.get('autoStyleify'));
|
|
914
|
+
break;
|
|
915
|
+
}
|
|
916
|
+
case 'textDirection': {
|
|
917
|
+
this.setDir(options.get('_rtl') ? 'ltr' : 'rtl');
|
|
918
|
+
break;
|
|
919
|
+
}
|
|
920
|
+
case 'historyStackDelayTime': {
|
|
921
|
+
this.history.resetDelayTime(options.get('historyStackDelayTime'));
|
|
922
|
+
break;
|
|
923
|
+
}
|
|
924
|
+
case 'defaultLineBreakFormat': {
|
|
925
|
+
this.format.__resetBrLineBreak(options.get('defaultLineBreakFormat'));
|
|
926
|
+
}
|
|
927
|
+
}
|
|
928
|
+
}
|
|
929
|
+
|
|
930
|
+
/** apply options */
|
|
931
|
+
// _origin
|
|
932
|
+
this._originOptions = _originOptions;
|
|
933
|
+
|
|
934
|
+
// --- [toolbar] ---
|
|
935
|
+
const toolbar = this.context.get('toolbar.main');
|
|
936
|
+
// width
|
|
937
|
+
if (/inline|balloon/i.test(options.get('mode')) && newOptionKeys.includes('toolbar_width')) {
|
|
938
|
+
toolbar.style.width = options.get('toolbar_width');
|
|
939
|
+
}
|
|
940
|
+
// hide
|
|
941
|
+
if (options.get('toolbar_hide')) {
|
|
942
|
+
toolbar.style.display = 'none';
|
|
943
|
+
} else {
|
|
944
|
+
toolbar.style.display = '';
|
|
945
|
+
}
|
|
946
|
+
// shortcuts hint
|
|
947
|
+
if (options.get('shortcutsHint')) {
|
|
948
|
+
dom.utils.removeClass(toolbar, 'se-shortcut-hide');
|
|
949
|
+
} else {
|
|
950
|
+
dom.utils.addClass(toolbar, 'se-shortcut-hide');
|
|
951
|
+
}
|
|
952
|
+
|
|
953
|
+
this.effectNode = null;
|
|
954
|
+
this._setFrameInfo(this.frameRoots.get(this.status.rootKey));
|
|
955
|
+
},
|
|
956
|
+
|
|
957
|
+
/**
|
|
958
|
+
* @description Change the current root index.
|
|
959
|
+
* @param {*} rootKey
|
|
960
|
+
*/
|
|
961
|
+
changeFrameContext(rootKey) {
|
|
962
|
+
if (rootKey === this.status.rootKey) return;
|
|
963
|
+
|
|
964
|
+
this.status.rootKey = rootKey;
|
|
965
|
+
this._setFrameInfo(this.frameRoots.get(rootKey));
|
|
966
|
+
this.toolbar._resetSticky();
|
|
967
|
+
},
|
|
968
|
+
|
|
969
|
+
/**
|
|
970
|
+
* @description Sets a CSS variable on the root element of the editor.
|
|
971
|
+
* If the editor is using an iframe or multi root applies it to all iframe roots instead.
|
|
972
|
+
* @param {string} name - The CSS variable name (e.g. `--se-color-primary`)
|
|
973
|
+
* @param {string} value - The CSS variable value
|
|
974
|
+
*/
|
|
975
|
+
setRootCssVar(name, value) {
|
|
976
|
+
if (this.frameOptions.get('iframe')) {
|
|
977
|
+
this.applyFrameRoots((root) => {
|
|
978
|
+
root.get('_wd').documentElement.style.setProperty(name, value);
|
|
979
|
+
});
|
|
980
|
+
} else {
|
|
981
|
+
this._d.documentElement.style.setProperty(name, value);
|
|
982
|
+
}
|
|
983
|
+
},
|
|
984
|
+
|
|
985
|
+
/**
|
|
986
|
+
* @description javascript execCommand
|
|
987
|
+
* @param {string} command javascript execCommand function property
|
|
988
|
+
* @param {boolean=} showDefaultUI javascript execCommand function property
|
|
989
|
+
* @param {string=} value javascript execCommand function property
|
|
990
|
+
*/
|
|
991
|
+
execCommand(command, showDefaultUI, value) {
|
|
992
|
+
this.frameContext.get('_wd').execCommand(command, showDefaultUI, command === 'formatBlock' ? '<' + value + '>' : value);
|
|
993
|
+
this.history.push(true);
|
|
994
|
+
},
|
|
995
|
+
|
|
996
|
+
/**
|
|
997
|
+
* @description Focus to wysiwyg area
|
|
998
|
+
* @param {*} rootKey Root index
|
|
999
|
+
*/
|
|
1000
|
+
focus(rootKey) {
|
|
1001
|
+
if (rootKey) this.changeFrameContext(rootKey);
|
|
1002
|
+
if (this.frameContext.get('wysiwygFrame').style.display === 'none') return;
|
|
1003
|
+
this._preventBlur = false;
|
|
1004
|
+
|
|
1005
|
+
if (this.frameOptions.get('iframe') || !this.frameContext.get('wysiwyg').contains(this.selection.getNode())) {
|
|
1006
|
+
this._nativeFocus();
|
|
1007
|
+
} else {
|
|
1008
|
+
try {
|
|
1009
|
+
const range = this.selection.getRange();
|
|
1010
|
+
if (range.startContainer === range.endContainer && dom.check.isWysiwygFrame(range.startContainer)) {
|
|
1011
|
+
const currentNode = /** @type {HTMLElement} */ (range.commonAncestorContainer).children[range.startOffset];
|
|
1012
|
+
if (!this.format.isLine(currentNode) && !this.component.is(currentNode)) {
|
|
1013
|
+
const br = dom.utils.createElement('BR');
|
|
1014
|
+
const format = dom.utils.createElement(this.options.get('defaultLine'), null, br);
|
|
1015
|
+
this.frameContext.get('wysiwyg').insertBefore(format, currentNode);
|
|
1016
|
+
this.selection.setRange(br, 0, br, 0);
|
|
1017
|
+
return;
|
|
1018
|
+
}
|
|
1019
|
+
}
|
|
1020
|
+
this.selection.setRange(range.startContainer, range.startOffset, range.endContainer, range.endOffset);
|
|
1021
|
+
} catch (e) {
|
|
1022
|
+
console.warn('[SUNEDITOR.focus.warn] ', e);
|
|
1023
|
+
this._nativeFocus();
|
|
1024
|
+
}
|
|
1025
|
+
}
|
|
1026
|
+
|
|
1027
|
+
if (this.isBalloon) this.eventManager._toggleToolbarBalloon();
|
|
1028
|
+
},
|
|
1029
|
+
|
|
1030
|
+
/**
|
|
1031
|
+
* @description If "focusEl" is a component, then that component is selected; if it is a format element, the last text is selected
|
|
1032
|
+
* - If "focusEdge" is null, then selected last element
|
|
1033
|
+
* @param {?Node=} focusEl Focus element
|
|
1034
|
+
*/
|
|
1035
|
+
focusEdge(focusEl) {
|
|
1036
|
+
this._preventBlur = false;
|
|
1037
|
+
if (!focusEl) focusEl = this.frameContext.get('wysiwyg').lastElementChild;
|
|
1038
|
+
|
|
1039
|
+
const fileComponentInfo = this.component.get(focusEl);
|
|
1040
|
+
if (fileComponentInfo) {
|
|
1041
|
+
this.component.select(fileComponentInfo.target, fileComponentInfo.pluginName);
|
|
1042
|
+
} else if (focusEl) {
|
|
1043
|
+
if (focusEl.nodeType !== 3) {
|
|
1044
|
+
focusEl = dom.query.getEdgeChild(
|
|
1045
|
+
focusEl,
|
|
1046
|
+
function (current) {
|
|
1047
|
+
return current.childNodes.length === 0 || current.nodeType === 3;
|
|
1048
|
+
},
|
|
1049
|
+
true
|
|
1050
|
+
);
|
|
1051
|
+
}
|
|
1052
|
+
if (!focusEl) this._nativeFocus();
|
|
1053
|
+
else this.selection.setRange(focusEl, focusEl.textContent.length, focusEl, focusEl.textContent.length);
|
|
1054
|
+
} else {
|
|
1055
|
+
this.focus();
|
|
1056
|
+
}
|
|
1057
|
+
},
|
|
1058
|
+
|
|
1059
|
+
/**
|
|
1060
|
+
* @description Focusout to wysiwyg area (.blur())
|
|
1061
|
+
*/
|
|
1062
|
+
blur() {
|
|
1063
|
+
if (this.frameOptions.get('iframe')) {
|
|
1064
|
+
this.frameContext.get('wysiwygFrame').blur();
|
|
1065
|
+
} else {
|
|
1066
|
+
this.frameContext.get('wysiwyg').blur();
|
|
1067
|
+
}
|
|
1068
|
+
},
|
|
1069
|
+
|
|
1070
|
+
/**
|
|
1071
|
+
* @description Destroy the suneditor
|
|
1072
|
+
*/
|
|
1073
|
+
destroy() {
|
|
1074
|
+
/** remove history */
|
|
1075
|
+
this.history.destroy();
|
|
1076
|
+
|
|
1077
|
+
/** remove event listeners */
|
|
1078
|
+
this.eventManager._removeAllEvents();
|
|
1079
|
+
|
|
1080
|
+
/** destroy external library */
|
|
1081
|
+
if (this.options.get('codeMirror6Editor')) {
|
|
1082
|
+
this.options.get('codeMirror6Editor').destroy();
|
|
1083
|
+
}
|
|
1084
|
+
|
|
1085
|
+
/** remove element */
|
|
1086
|
+
dom.utils.removeItem(this.carrierWrapper);
|
|
1087
|
+
dom.utils.removeItem(this.context.get('toolbar._wrapper'));
|
|
1088
|
+
dom.utils.removeItem(this.context.get('toolbar.sub._wrapper'));
|
|
1089
|
+
dom.utils.removeItem(this.context.get('statusbar._wrapper'));
|
|
1090
|
+
this.applyFrameRoots((e) => {
|
|
1091
|
+
dom.utils.removeItem(e.get('topArea'));
|
|
1092
|
+
e.get('options').clear();
|
|
1093
|
+
e.clear();
|
|
1094
|
+
});
|
|
1095
|
+
|
|
1096
|
+
/** remove object reference */
|
|
1097
|
+
this.options.clear();
|
|
1098
|
+
this.context.clear();
|
|
1099
|
+
|
|
1100
|
+
let obj = this.plugins;
|
|
1101
|
+
for (const k in obj) {
|
|
1102
|
+
const p = obj[k];
|
|
1103
|
+
if (typeof p._destroy === 'function') p._destroy();
|
|
1104
|
+
for (const pk in p) {
|
|
1105
|
+
delete p[pk];
|
|
1106
|
+
}
|
|
1107
|
+
delete obj[k];
|
|
1108
|
+
}
|
|
1109
|
+
obj = this.events;
|
|
1110
|
+
for (const k in obj) {
|
|
1111
|
+
delete obj[k];
|
|
1112
|
+
}
|
|
1113
|
+
|
|
1114
|
+
obj = ['eventManager', 'instanceCheck', 'char', 'component', 'format', 'html', 'menu', 'nodeTransform', 'offset', 'selection', 'shortcuts', 'toolbar', 'ui', 'viewer'];
|
|
1115
|
+
for (let i = 0, len = obj.length, c; i < len; i++) {
|
|
1116
|
+
c = this[obj[i]];
|
|
1117
|
+
for (const k in c) {
|
|
1118
|
+
delete c[k];
|
|
1119
|
+
}
|
|
1120
|
+
}
|
|
1121
|
+
obj = this.subToolbar;
|
|
1122
|
+
if (obj) {
|
|
1123
|
+
for (const k in obj) {
|
|
1124
|
+
delete obj[k];
|
|
1125
|
+
}
|
|
1126
|
+
}
|
|
1127
|
+
|
|
1128
|
+
obj = null;
|
|
1129
|
+
for (const k in this) {
|
|
1130
|
+
delete this[k];
|
|
1131
|
+
}
|
|
1132
|
+
|
|
1133
|
+
return null;
|
|
1134
|
+
},
|
|
1135
|
+
|
|
1136
|
+
/** ----- private methods ----------------------------------------------------------------------------------------------------------------------------- */
|
|
1137
|
+
/**
|
|
1138
|
+
* @private
|
|
1139
|
+
* @description Set frameContext, frameOptions
|
|
1140
|
+
* @param {__se__FrameContext} rt Root target[key] FrameContext
|
|
1141
|
+
*/
|
|
1142
|
+
_setFrameInfo(rt) {
|
|
1143
|
+
this.frameContext = rt;
|
|
1144
|
+
this.frameOptions = rt.get('options');
|
|
1145
|
+
rt.set('_editorHeight', rt.get('wysiwygFrame').offsetHeight);
|
|
1146
|
+
this._lineBreaker_t = rt.get('lineBreaker_t');
|
|
1147
|
+
this._lineBreaker_b = rt.get('lineBreaker_b');
|
|
1148
|
+
},
|
|
1149
|
+
|
|
1150
|
+
/**
|
|
1151
|
+
* @private
|
|
1152
|
+
* @description Focus to wysiwyg area using "native focus function"
|
|
1153
|
+
*/
|
|
1154
|
+
_nativeFocus() {
|
|
1155
|
+
this.selection.__focus();
|
|
1156
|
+
this.selection._init();
|
|
1157
|
+
},
|
|
1158
|
+
|
|
1159
|
+
/**
|
|
1160
|
+
* @private
|
|
1161
|
+
* @description Check the components such as image and video and modify them according to the format.
|
|
1162
|
+
* @param {boolean} loaded If true, the component is loaded.
|
|
1163
|
+
*/
|
|
1164
|
+
_checkComponents(loaded) {
|
|
1165
|
+
for (let i = 0, len = this._fileInfoPluginsCheck.length; i < len; i++) {
|
|
1166
|
+
this._fileInfoPluginsCheck[i](loaded);
|
|
1167
|
+
}
|
|
1168
|
+
},
|
|
1169
|
+
|
|
1170
|
+
/**
|
|
1171
|
+
* @private
|
|
1172
|
+
* @description Initialize the information of the components.
|
|
1173
|
+
*/
|
|
1174
|
+
_resetComponents() {
|
|
1175
|
+
for (let i = 0, len = this._fileInfoPluginsReset.length; i < len; i++) {
|
|
1176
|
+
this._fileInfoPluginsReset[i]();
|
|
1177
|
+
}
|
|
1178
|
+
},
|
|
1179
|
+
|
|
1180
|
+
/**
|
|
1181
|
+
* @private
|
|
1182
|
+
* @description Initializ wysiwyg area (Only called from core._init)
|
|
1183
|
+
* @param {__se__FrameContext} e frameContext
|
|
1184
|
+
* @param {string} value initial html string
|
|
1185
|
+
*/
|
|
1186
|
+
_initWysiwygArea(e, value) {
|
|
1187
|
+
// set content
|
|
1188
|
+
e.get('wysiwyg').innerHTML =
|
|
1189
|
+
this.html.clean(typeof value === 'string' ? value : (/^TEXTAREA$/i.test(e.get('originElement').nodeName) ? e.get('originElement').value : e.get('originElement').innerHTML) || '', {
|
|
1190
|
+
forceFormat: true,
|
|
1191
|
+
whitelist: null,
|
|
1192
|
+
blacklist: null,
|
|
1193
|
+
_freeCodeViewMode: this.options.get('freeCodeViewMode')
|
|
1194
|
+
}) || '<' + this.options.get('defaultLine') + '><br></' + this.options.get('defaultLine') + '>';
|
|
1195
|
+
|
|
1196
|
+
// char counter
|
|
1197
|
+
if (e.has('charCounter')) e.get('charCounter').textContent = this.char.getLength();
|
|
1198
|
+
|
|
1199
|
+
// document type init
|
|
1200
|
+
if (this.options.get('type') === 'document') {
|
|
1201
|
+
e.set('documentType', new DocumentType(this, e));
|
|
1202
|
+
if (e.get('documentType').useHeader) {
|
|
1203
|
+
e.set('documentType-use-header', true);
|
|
1204
|
+
}
|
|
1205
|
+
if (e.get('documentType').usePage) {
|
|
1206
|
+
e.set('documentType-use-page', true);
|
|
1207
|
+
e.get('documentTypePageMirror').innerHTML = e.get('wysiwyg').innerHTML;
|
|
1208
|
+
}
|
|
1209
|
+
}
|
|
1210
|
+
},
|
|
1211
|
+
|
|
1212
|
+
/**
|
|
1213
|
+
* @private
|
|
1214
|
+
* @description Called when there are changes to tags in the wysiwyg region.
|
|
1215
|
+
* @param {__se__FrameContext} fc - Frame context object
|
|
1216
|
+
*/
|
|
1217
|
+
_resourcesStateChange(fc) {
|
|
1218
|
+
this._iframeAutoHeight(fc);
|
|
1219
|
+
this._checkPlaceholder(fc);
|
|
1220
|
+
// document type page
|
|
1221
|
+
if (fc.has('documentType-use-page') && fc.get('options').get('height') !== 'auto') {
|
|
1222
|
+
fc.get('documentTypePageMirror').innerHTML = fc.get('wysiwyg').innerHTML;
|
|
1223
|
+
fc.get('documentType').rePage(true);
|
|
1224
|
+
}
|
|
1225
|
+
},
|
|
1226
|
+
|
|
1227
|
+
/**
|
|
1228
|
+
* @private
|
|
1229
|
+
* @description Modify the height value of the iframe when the height of the iframe is automatic.
|
|
1230
|
+
* @param {__se__FrameContext} fc - Frame context object
|
|
1231
|
+
*/
|
|
1232
|
+
_iframeAutoHeight(fc) {
|
|
1233
|
+
const autoFrame = fc.get('_iframeAuto');
|
|
1234
|
+
|
|
1235
|
+
if (autoFrame) {
|
|
1236
|
+
this._w.setTimeout(() => {
|
|
1237
|
+
const h = autoFrame.offsetHeight;
|
|
1238
|
+
fc.get('wysiwygFrame').style.height = h + 'px';
|
|
1239
|
+
if (!env.isResizeObserverSupported) this.__callResizeFunction(fc, h, null);
|
|
1240
|
+
}, 0);
|
|
1241
|
+
} else if (!env.isResizeObserverSupported) {
|
|
1242
|
+
this.__callResizeFunction(fc, fc.get('wysiwygFrame').offsetHeight, null);
|
|
1243
|
+
}
|
|
1244
|
+
},
|
|
1245
|
+
|
|
1246
|
+
/**
|
|
1247
|
+
* @private
|
|
1248
|
+
* @description Call the "onResizeEditor" event
|
|
1249
|
+
* @param {__se__FrameContext} fc - Frame context object
|
|
1250
|
+
* @param {number} h - Height value
|
|
1251
|
+
* @param {ResizeObserverEntry} resizeObserverEntry - ResizeObserverEntry object
|
|
1252
|
+
*/
|
|
1253
|
+
__callResizeFunction(fc, h, resizeObserverEntry) {
|
|
1254
|
+
h =
|
|
1255
|
+
h === -1
|
|
1256
|
+
? resizeObserverEntry?.borderBoxSize && resizeObserverEntry.borderBoxSize[0]
|
|
1257
|
+
? resizeObserverEntry.borderBoxSize[0].blockSize
|
|
1258
|
+
: resizeObserverEntry.contentRect.height + numbers.get(fc.get('wwComputedStyle').getPropertyValue('padding-left')) + numbers.get(fc.get('wwComputedStyle').getPropertyValue('padding-right'))
|
|
1259
|
+
: h;
|
|
1260
|
+
if (fc.get('_editorHeight') !== h) {
|
|
1261
|
+
this.triggerEvent('onResizeEditor', { height: h, prevHeight: fc.get('_editorHeight'), frameContext: fc, observerEntry: resizeObserverEntry });
|
|
1262
|
+
fc.set('_editorHeight', h);
|
|
1263
|
+
}
|
|
1264
|
+
|
|
1265
|
+
// document type page
|
|
1266
|
+
if (fc.has('documentType-use-page')) {
|
|
1267
|
+
fc.get('documentType').resizePage();
|
|
1268
|
+
}
|
|
1269
|
+
},
|
|
1270
|
+
|
|
1271
|
+
/**
|
|
1272
|
+
* @private
|
|
1273
|
+
* @description Set display property when there is placeholder.
|
|
1274
|
+
* @param {?__se__FrameContext=} fc - Frame context object, If null fc is this.frameContext
|
|
1275
|
+
*/
|
|
1276
|
+
_checkPlaceholder(fc) {
|
|
1277
|
+
fc = fc || this.frameContext;
|
|
1278
|
+
const placeholder = fc.get('placeholder');
|
|
1279
|
+
|
|
1280
|
+
if (placeholder) {
|
|
1281
|
+
if (fc.get('isCodeView')) {
|
|
1282
|
+
placeholder.style.display = 'none';
|
|
1283
|
+
return;
|
|
1284
|
+
}
|
|
1285
|
+
|
|
1286
|
+
if (this.isEmpty(fc)) {
|
|
1287
|
+
placeholder.style.display = 'block';
|
|
1288
|
+
} else {
|
|
1289
|
+
placeholder.style.display = 'none';
|
|
1290
|
+
}
|
|
1291
|
+
}
|
|
1292
|
+
},
|
|
1293
|
+
|
|
1294
|
+
/**
|
|
1295
|
+
* @private
|
|
1296
|
+
* @description Initializ editor
|
|
1297
|
+
* @param {EditorInitOptions_editor} options Options
|
|
1298
|
+
*/
|
|
1299
|
+
__editorInit(options) {
|
|
1300
|
+
this.status.initViewportHeight = this._w.visualViewport.height;
|
|
1301
|
+
this.eventManager.__setViewportSize();
|
|
1302
|
+
|
|
1303
|
+
this.applyFrameRoots((e) => {
|
|
1304
|
+
this.__setEditorParams(e);
|
|
1305
|
+
});
|
|
1306
|
+
|
|
1307
|
+
// initialize core and add event listeners
|
|
1308
|
+
this._setFrameInfo(this.frameRoots.get(this.status.rootKey));
|
|
1309
|
+
this.__init(options);
|
|
1310
|
+
for (const v of this._onPluginEvents.values()) {
|
|
1311
|
+
v.sort((a, b) => a.index - b.index);
|
|
1312
|
+
}
|
|
1313
|
+
|
|
1314
|
+
this.applyFrameRoots((e) => {
|
|
1315
|
+
this.eventManager._addFrameEvents(e);
|
|
1316
|
+
this._initWysiwygArea(e, e.get('options').get('value'));
|
|
1317
|
+
if (e.get('options').get('iframe') && e.get('options').get('height') === 'auto') {
|
|
1318
|
+
this.__callResizeFunction(e, e.get('wysiwygFrame').offsetHeight, null);
|
|
1319
|
+
}
|
|
1320
|
+
});
|
|
1321
|
+
|
|
1322
|
+
this.eventManager.__eventDoc = null;
|
|
1323
|
+
this._componentsInfoInit = false;
|
|
1324
|
+
this._componentsInfoReset = false;
|
|
1325
|
+
this._checkComponents(true);
|
|
1326
|
+
|
|
1327
|
+
this._w.setTimeout(() => {
|
|
1328
|
+
// toolbar visibility
|
|
1329
|
+
this.context.get('toolbar.main').style.visibility = '';
|
|
1330
|
+
// roots
|
|
1331
|
+
this.applyFrameRoots((e) => {
|
|
1332
|
+
if (typeof this._resourcesStateChange !== 'function') return;
|
|
1333
|
+
// observer
|
|
1334
|
+
if (this.eventManager._wwFrameObserver) this.eventManager._wwFrameObserver.observe(e.get('wysiwygFrame'));
|
|
1335
|
+
if (this.eventManager._toolbarObserver) this.eventManager._toolbarObserver.observe(e.get('_toolbarShadow'));
|
|
1336
|
+
// resource state
|
|
1337
|
+
this._resourcesStateChange(e);
|
|
1338
|
+
});
|
|
1339
|
+
// history reset
|
|
1340
|
+
this.history.reset();
|
|
1341
|
+
// user event
|
|
1342
|
+
this.triggerEvent('onload', {});
|
|
1343
|
+
}, 0);
|
|
1344
|
+
},
|
|
1345
|
+
|
|
1346
|
+
/**
|
|
1347
|
+
* @private
|
|
1348
|
+
* @description Initializ core variable
|
|
1349
|
+
* @param {EditorInitOptions_editor} options Options
|
|
1350
|
+
*/
|
|
1351
|
+
__init(options) {
|
|
1352
|
+
// file components
|
|
1353
|
+
this._fileInfoPluginsCheck = [];
|
|
1354
|
+
this._fileInfoPluginsReset = [];
|
|
1355
|
+
|
|
1356
|
+
// text components
|
|
1357
|
+
this._MELInfo = new Map();
|
|
1358
|
+
|
|
1359
|
+
// Command and file plugins registration
|
|
1360
|
+
this.activeCommands = ACTIVE_EVENT_COMMANDS;
|
|
1361
|
+
this._onPluginEvents = new Map([
|
|
1362
|
+
['onMouseMove', []],
|
|
1363
|
+
['onMouseLeave', []],
|
|
1364
|
+
['onMouseDown', []],
|
|
1365
|
+
['onMouseUp', []],
|
|
1366
|
+
['onScroll', []],
|
|
1367
|
+
['onClick', []],
|
|
1368
|
+
['onInput', []],
|
|
1369
|
+
['onKeyDown', []],
|
|
1370
|
+
['onKeyUp', []],
|
|
1371
|
+
['onFocus', []],
|
|
1372
|
+
['onBlur', []],
|
|
1373
|
+
['onPaste', []],
|
|
1374
|
+
['onFilePasteAndDrop', []]
|
|
1375
|
+
]);
|
|
1376
|
+
this._fileManager.tags = [];
|
|
1377
|
+
this._fileManager.pluginMap = {};
|
|
1378
|
+
this._fileManager.tagAttrs = {};
|
|
1379
|
+
|
|
1380
|
+
const plugins = this.plugins;
|
|
1381
|
+
const filePluginRegExp = [];
|
|
1382
|
+
let plugin;
|
|
1383
|
+
for (const key in plugins) {
|
|
1384
|
+
this.registerPlugin(key, this._pluginCallButtons[key], options[key]);
|
|
1385
|
+
this.registerPlugin(key, this._pluginCallButtons_sub[key], options[key]);
|
|
1386
|
+
plugin = this.plugins[key];
|
|
1387
|
+
|
|
1388
|
+
// Filemanager
|
|
1389
|
+
if (typeof plugin.__fileManagement === 'object') {
|
|
1390
|
+
const fm = plugin.__fileManagement;
|
|
1391
|
+
this._fileInfoPluginsCheck.push(fm._checkInfo.bind(fm));
|
|
1392
|
+
this._fileInfoPluginsReset.push(fm._resetInfo.bind(fm));
|
|
1393
|
+
if (Array.isArray(fm.tagNames)) {
|
|
1394
|
+
const tagNames = fm.tagNames;
|
|
1395
|
+
this._fileManager.tags = this._fileManager.tags.concat(tagNames);
|
|
1396
|
+
filePluginRegExp.push(key);
|
|
1397
|
+
for (let tag = 0, tLen = tagNames.length, t; tag < tLen; tag++) {
|
|
1398
|
+
t = tagNames[tag].toLowerCase();
|
|
1399
|
+
this._fileManager.pluginMap[t] = key;
|
|
1400
|
+
if (fm.tagAttrs) {
|
|
1401
|
+
this._fileManager.tagAttrs[t] = fm.tagAttrs;
|
|
1402
|
+
}
|
|
1403
|
+
}
|
|
1404
|
+
}
|
|
1405
|
+
}
|
|
1406
|
+
|
|
1407
|
+
// Not file component
|
|
1408
|
+
if (typeof plugin.constructor.component === 'function') {
|
|
1409
|
+
this._componentManager.push(
|
|
1410
|
+
function (launcher, element) {
|
|
1411
|
+
if (!element || !(element = launcher.component?.call(this, element))) return null;
|
|
1412
|
+
return {
|
|
1413
|
+
target: element,
|
|
1414
|
+
pluginName: launcher.key,
|
|
1415
|
+
options: launcher.options
|
|
1416
|
+
};
|
|
1417
|
+
}.bind(plugin, plugin.constructor)
|
|
1418
|
+
);
|
|
1419
|
+
}
|
|
1420
|
+
|
|
1421
|
+
// plugin event
|
|
1422
|
+
const pluginOptions = plugin.constructor.options || {};
|
|
1423
|
+
this._onPluginEvents.forEach((v, k) => {
|
|
1424
|
+
if (typeof plugin[k] === 'function') {
|
|
1425
|
+
const f = plugin[k].bind(plugin);
|
|
1426
|
+
f.index = pluginOptions[`eventIndex_${k}`] || pluginOptions.eventIndex || 0;
|
|
1427
|
+
v.push(f);
|
|
1428
|
+
}
|
|
1429
|
+
});
|
|
1430
|
+
|
|
1431
|
+
// plugin maintain
|
|
1432
|
+
if (plugin.retainFormat) {
|
|
1433
|
+
const info = plugin.retainFormat();
|
|
1434
|
+
this._MELInfo.set(info.query, { key: plugin.constructor.key, method: info.method });
|
|
1435
|
+
}
|
|
1436
|
+
}
|
|
1437
|
+
|
|
1438
|
+
if (this.options.get('buttons').has('pageBreak') || this.options.get('buttons_sub')?.has('pageBreak')) {
|
|
1439
|
+
this._componentManager.push((element) => {
|
|
1440
|
+
if (!element || !dom.utils.hasClass(element, 'se-page-break')) return null;
|
|
1441
|
+
return {
|
|
1442
|
+
target: element,
|
|
1443
|
+
launcher: {
|
|
1444
|
+
destroy: (target) => {
|
|
1445
|
+
const focusEl = target.previousElementSibling || target.nextElementSibling;
|
|
1446
|
+
dom.utils.removeItem(target);
|
|
1447
|
+
// focus
|
|
1448
|
+
this.focusEdge(focusEl);
|
|
1449
|
+
this.history.push(false);
|
|
1450
|
+
}
|
|
1451
|
+
}
|
|
1452
|
+
};
|
|
1453
|
+
});
|
|
1454
|
+
}
|
|
1455
|
+
|
|
1456
|
+
this._fileManager.regExp = new RegExp(`^(${this._fileManager.tags.join('|') || '\\^'})$`, 'i');
|
|
1457
|
+
this._fileManager.pluginRegExp = new RegExp(`^(${filePluginRegExp.length === 0 ? '\\^' : filePluginRegExp.join('|')})$`, 'i');
|
|
1458
|
+
|
|
1459
|
+
delete this._pluginCallButtons;
|
|
1460
|
+
delete this._pluginCallButtons_sub;
|
|
1461
|
+
|
|
1462
|
+
this.__cachingButtons();
|
|
1463
|
+
this.__cachingShortcuts();
|
|
1464
|
+
},
|
|
1465
|
+
|
|
1466
|
+
/**
|
|
1467
|
+
* @private
|
|
1468
|
+
* @description Caching basic buttons to use
|
|
1469
|
+
*/
|
|
1470
|
+
__cachingButtons() {
|
|
1471
|
+
const ctx = this.context;
|
|
1472
|
+
this.__setDisabledButtons();
|
|
1473
|
+
this.__saveCommandButtons(this.allCommandButtons, ctx.get('toolbar.buttonTray'));
|
|
1474
|
+
if (this.options.has('_subMode')) {
|
|
1475
|
+
this.__saveCommandButtons(this.subAllCommandButtons, ctx.get('toolbar.sub.buttonTray'));
|
|
1476
|
+
}
|
|
1477
|
+
},
|
|
1478
|
+
|
|
1479
|
+
/**
|
|
1480
|
+
* @private
|
|
1481
|
+
* @description Set the disabled button list
|
|
1482
|
+
* - this._codeViewDisabledButtons, this._controllerOnDisabledButtons
|
|
1483
|
+
*/
|
|
1484
|
+
__setDisabledButtons() {
|
|
1485
|
+
const ctx = this.context;
|
|
1486
|
+
|
|
1487
|
+
this._codeViewDisabledButtons = converter.nodeListToArray(ctx.get('toolbar.buttonTray').querySelectorAll(DISABLE_BUTTONS_CODEVIEW));
|
|
1488
|
+
this._controllerOnDisabledButtons = converter.nodeListToArray(ctx.get('toolbar.buttonTray').querySelectorAll(DISABLE_BUTTONS_CONTROLLER));
|
|
1489
|
+
|
|
1490
|
+
if (this.options.has('_subMode')) {
|
|
1491
|
+
this._codeViewDisabledButtons = this._codeViewDisabledButtons.concat(converter.nodeListToArray(ctx.get('toolbar.sub.buttonTray').querySelectorAll(DISABLE_BUTTONS_CODEVIEW)));
|
|
1492
|
+
this._controllerOnDisabledButtons = this._controllerOnDisabledButtons.concat(converter.nodeListToArray(ctx.get('toolbar.sub.buttonTray').querySelectorAll(DISABLE_BUTTONS_CONTROLLER)));
|
|
1493
|
+
}
|
|
1494
|
+
},
|
|
1495
|
+
|
|
1496
|
+
/**
|
|
1497
|
+
* @private
|
|
1498
|
+
* @description Save the current buttons
|
|
1499
|
+
* @param {Map<string, Element>} cmdButtons Command button map
|
|
1500
|
+
* @param {Element} tray Button tray
|
|
1501
|
+
*/
|
|
1502
|
+
__saveCommandButtons(cmdButtons, tray) {
|
|
1503
|
+
const currentButtons = tray.querySelectorAll(COMMAND_BUTTONS);
|
|
1504
|
+
const shortcuts = this.options.get('shortcuts');
|
|
1505
|
+
const reverseCommandArray = this.options.get('_reverseCommandArray');
|
|
1506
|
+
const keyMap = this.shortcutsKeyMap;
|
|
1507
|
+
const reverseKeys = this.reverseKeys;
|
|
1508
|
+
|
|
1509
|
+
for (let i = 0, len = currentButtons.length, e, c; i < len; i++) {
|
|
1510
|
+
e = /** @type {HTMLButtonElement} */ (currentButtons[i]);
|
|
1511
|
+
c = e.getAttribute('data-command');
|
|
1512
|
+
// command set
|
|
1513
|
+
cmdButtons.set(c, e);
|
|
1514
|
+
this.__setCommandTargets(c, e);
|
|
1515
|
+
// shortcuts
|
|
1516
|
+
CreateShortcuts(c, e, shortcuts[c], keyMap, reverseCommandArray, reverseKeys);
|
|
1517
|
+
}
|
|
1518
|
+
},
|
|
1519
|
+
|
|
1520
|
+
/**
|
|
1521
|
+
* @private
|
|
1522
|
+
* @description Caches custom(starts with "_") shortcut keys for commands.
|
|
1523
|
+
*/
|
|
1524
|
+
__cachingShortcuts() {
|
|
1525
|
+
const shortcuts = this.options.get('shortcuts');
|
|
1526
|
+
const reverseCommandArray = this.options.get('_reverseCommandArray');
|
|
1527
|
+
const keyMap = this.shortcutsKeyMap;
|
|
1528
|
+
const reverseKeys = this.reverseKeys;
|
|
1529
|
+
for (const key of Object.keys(shortcuts)) {
|
|
1530
|
+
if (!key.startsWith('_')) continue;
|
|
1531
|
+
CreateShortcuts('', null, shortcuts[key], keyMap, reverseCommandArray, reverseKeys);
|
|
1532
|
+
}
|
|
1533
|
+
},
|
|
1534
|
+
|
|
1535
|
+
/**
|
|
1536
|
+
* @private
|
|
1537
|
+
* @description Sets command target elements.
|
|
1538
|
+
* @param {string} cmd - The command identifier.
|
|
1539
|
+
* @param {HTMLButtonElement} target - The associated command button.
|
|
1540
|
+
*/
|
|
1541
|
+
__setCommandTargets(cmd, target) {
|
|
1542
|
+
if (!cmd || !target) return;
|
|
1543
|
+
|
|
1544
|
+
const isBasicCmd = BASIC_COMMANDS.includes(cmd);
|
|
1545
|
+
if (!isBasicCmd && !this.plugins[cmd]) return;
|
|
1546
|
+
|
|
1547
|
+
if (!this.commandTargets.get(cmd)) {
|
|
1548
|
+
this.commandTargets.set(cmd, [target]);
|
|
1549
|
+
} else if (!this.commandTargets.get(cmd).includes(target)) {
|
|
1550
|
+
this.commandTargets.get(cmd).push(target);
|
|
1551
|
+
}
|
|
1552
|
+
},
|
|
1553
|
+
|
|
1554
|
+
/**
|
|
1555
|
+
* @private
|
|
1556
|
+
* @description Configures the document properties of an iframe editor.
|
|
1557
|
+
* @param {HTMLIFrameElement} frame - The editor iframe.
|
|
1558
|
+
* @param {Map<string, *>} originOptions - The original options.
|
|
1559
|
+
* @param {__se__FrameOptions} targetOptions - The new options.
|
|
1560
|
+
*/
|
|
1561
|
+
__setIframeDocument(frame, originOptions, targetOptions) {
|
|
1562
|
+
frame.setAttribute('scrolling', 'auto');
|
|
1563
|
+
frame.contentDocument.head.innerHTML =
|
|
1564
|
+
'<meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">' +
|
|
1565
|
+
converter._setIframeStyleLinks(targetOptions.get('iframe_cssFileName')) +
|
|
1566
|
+
converter._setAutoHeightStyle(targetOptions.get('height'));
|
|
1567
|
+
frame.contentDocument.body.className = originOptions.get('_editableClass');
|
|
1568
|
+
frame.contentDocument.body.setAttribute('contenteditable', 'true');
|
|
1569
|
+
},
|
|
1570
|
+
|
|
1571
|
+
/**
|
|
1572
|
+
* @private
|
|
1573
|
+
* @description Set the FrameContext parameters and options
|
|
1574
|
+
* @param {__se__FrameContext} e - Frame context object
|
|
1575
|
+
*/
|
|
1576
|
+
__setEditorParams(e) {
|
|
1577
|
+
const frameOptions = e.get('options');
|
|
1578
|
+
const _w = this._w;
|
|
1579
|
+
|
|
1580
|
+
e.set('wwComputedStyle', _w.getComputedStyle(e.get('wysiwyg')));
|
|
1581
|
+
|
|
1582
|
+
if (!frameOptions.get('iframe') && typeof ShadowRoot === 'function') {
|
|
1583
|
+
let child = e.get('wysiwygFrame');
|
|
1584
|
+
while (child) {
|
|
1585
|
+
if (child.shadowRoot) {
|
|
1586
|
+
this._shadowRoot = child.shadowRoot;
|
|
1587
|
+
break;
|
|
1588
|
+
} else if (child instanceof ShadowRoot) {
|
|
1589
|
+
this._shadowRoot = child;
|
|
1590
|
+
break;
|
|
1591
|
+
}
|
|
1592
|
+
child = child.parentNode;
|
|
1593
|
+
}
|
|
1594
|
+
}
|
|
1595
|
+
|
|
1596
|
+
// init, validate
|
|
1597
|
+
if (frameOptions.get('iframe')) {
|
|
1598
|
+
e.set('_ww', e.get('wysiwygFrame').contentWindow);
|
|
1599
|
+
e.set('_wd', e.get('wysiwygFrame').contentDocument);
|
|
1600
|
+
e.set('wysiwyg', e.get('_wd').body);
|
|
1601
|
+
// e.get('wysiwyg').className += ' ' + options.get('_editableClass');
|
|
1602
|
+
if (frameOptions.get('_defaultStyles').editor) e.get('wysiwyg').style.cssText = frameOptions.get('_defaultStyles').editor;
|
|
1603
|
+
if (frameOptions.get('height') === 'auto') e.set('_iframeAuto', e.get('_wd').body);
|
|
1604
|
+
} else {
|
|
1605
|
+
e.set('_ww', _w);
|
|
1606
|
+
e.set('_wd', this._d);
|
|
1607
|
+
}
|
|
1608
|
+
|
|
1609
|
+
// wisywig attributes
|
|
1610
|
+
const attr = frameOptions.get('editableFrameAttributes');
|
|
1611
|
+
for (const k in attr) {
|
|
1612
|
+
e.get('wysiwyg').setAttribute(k, attr[k]);
|
|
1613
|
+
}
|
|
1614
|
+
},
|
|
1615
|
+
|
|
1616
|
+
/**
|
|
1617
|
+
* @private
|
|
1618
|
+
* @description Registers and initializes editor classes.
|
|
1619
|
+
*/
|
|
1620
|
+
__registerClass() {
|
|
1621
|
+
// use events
|
|
1622
|
+
this.events = { ...Events, ...this.options.get('events') };
|
|
1623
|
+
this.triggerEvent = async (eventName, eventData) => {
|
|
1624
|
+
// [iframe] wysiwyg is disabled, the event is not called.
|
|
1625
|
+
if (eventData?.frameContext?.get('wysiwyg').getAttribute('contenteditable') === 'false') return false;
|
|
1626
|
+
const eventHandler = this.events[eventName];
|
|
1627
|
+
if (typeof eventHandler === 'function') {
|
|
1628
|
+
return await eventHandler({ editor: this, ...eventData });
|
|
1629
|
+
}
|
|
1630
|
+
return env.NO_EVENT;
|
|
1631
|
+
};
|
|
1632
|
+
|
|
1633
|
+
// history function
|
|
1634
|
+
this.history = History(this);
|
|
1635
|
+
|
|
1636
|
+
// eventManager
|
|
1637
|
+
this.eventManager = new EventManager(this);
|
|
1638
|
+
|
|
1639
|
+
// util
|
|
1640
|
+
this.instanceCheck = new InstanceCheck(this);
|
|
1641
|
+
|
|
1642
|
+
// main classes
|
|
1643
|
+
this.offset = new Offset(this);
|
|
1644
|
+
this.shortcuts = new Shortcuts(this);
|
|
1645
|
+
this.toolbar = new Toolbar(this, { keyName: 'toolbar', balloon: this.isBalloon, balloonAlways: this.isBalloonAlways, inline: this.isInline, res: this._responsiveButtons });
|
|
1646
|
+
if (this.options.has('_subMode')) {
|
|
1647
|
+
this.subToolbar = new Toolbar(this, {
|
|
1648
|
+
keyName: 'toolbar.sub',
|
|
1649
|
+
balloon: this.isSubBalloon,
|
|
1650
|
+
balloonAlways: this.isSubBalloonAlways,
|
|
1651
|
+
inline: false,
|
|
1652
|
+
res: this._responsiveButtons_sub
|
|
1653
|
+
});
|
|
1654
|
+
}
|
|
1655
|
+
this.selection = new Selection_(this);
|
|
1656
|
+
this.html = new HTML(this);
|
|
1657
|
+
this.nodeTransform = new NodeTransform(this);
|
|
1658
|
+
this.component = new Component(this);
|
|
1659
|
+
this.format = new Format(this);
|
|
1660
|
+
this.menu = new Menu(this);
|
|
1661
|
+
this.char = new Char(this);
|
|
1662
|
+
this.ui = new UI(this);
|
|
1663
|
+
this.viewer = new Viewer(this);
|
|
1664
|
+
|
|
1665
|
+
// register classes to the eventManager
|
|
1666
|
+
ClassInjector.call(this.eventManager, this);
|
|
1667
|
+
// register main classes
|
|
1668
|
+
ClassInjector.call(this.char, this);
|
|
1669
|
+
ClassInjector.call(this.component, this);
|
|
1670
|
+
ClassInjector.call(this.format, this);
|
|
1671
|
+
ClassInjector.call(this.html, this);
|
|
1672
|
+
ClassInjector.call(this.menu, this);
|
|
1673
|
+
ClassInjector.call(this.nodeTransform, this);
|
|
1674
|
+
ClassInjector.call(this.offset, this);
|
|
1675
|
+
ClassInjector.call(this.selection, this);
|
|
1676
|
+
ClassInjector.call(this.shortcuts, this);
|
|
1677
|
+
ClassInjector.call(this.toolbar, this);
|
|
1678
|
+
ClassInjector.call(this.ui, this);
|
|
1679
|
+
ClassInjector.call(this.viewer, this);
|
|
1680
|
+
if (this.options.has('_subMode')) ClassInjector.call(this.subToolbar, this);
|
|
1681
|
+
|
|
1682
|
+
// delete self reference
|
|
1683
|
+
delete this.eventManager['eventManager'];
|
|
1684
|
+
delete this.char['char'];
|
|
1685
|
+
delete this.component['component'];
|
|
1686
|
+
delete this.format['format'];
|
|
1687
|
+
delete this.html['html'];
|
|
1688
|
+
delete this.menu['menu'];
|
|
1689
|
+
delete this.nodeTransform['nodeTransform'];
|
|
1690
|
+
delete this.offset['offset'];
|
|
1691
|
+
delete this.selection['selection'];
|
|
1692
|
+
delete this.shortcuts['shortcuts'];
|
|
1693
|
+
delete this.toolbar['toolbar'];
|
|
1694
|
+
delete this.ui['ui'];
|
|
1695
|
+
delete this.viewer['viewer'];
|
|
1696
|
+
if (this.subToolbar) delete this.subToolbar['subToolbar'];
|
|
1697
|
+
|
|
1698
|
+
this._responsiveButtons = this._responsiveButtons_sub = null;
|
|
1699
|
+
},
|
|
1700
|
+
|
|
1701
|
+
/**
|
|
1702
|
+
* @private
|
|
1703
|
+
* @description Creates the editor instance and initializes components.
|
|
1704
|
+
* @param {EditorInitOptions_editor} originOptions - The initial editor options.
|
|
1705
|
+
* @returns {Promise<void>}
|
|
1706
|
+
*/
|
|
1707
|
+
async __Create(originOptions) {
|
|
1708
|
+
// set modes
|
|
1709
|
+
this.isInline = /inline/i.test(this.options.get('mode'));
|
|
1710
|
+
this.isBalloon = /balloon/i.test(this.options.get('mode'));
|
|
1711
|
+
this.isBalloonAlways = /balloon-always/i.test(this.options.get('mode'));
|
|
1712
|
+
this.isClassic = /classic/i.test(this.options.get('mode'));
|
|
1713
|
+
// set subToolbar modes
|
|
1714
|
+
this.isSubBalloon = /balloon/i.test(this.options.get('_subMode'));
|
|
1715
|
+
this.isSubBalloonAlways = /balloon-always/i.test(this.options.get('_subMode'));
|
|
1716
|
+
|
|
1717
|
+
// register class
|
|
1718
|
+
this.__registerClass();
|
|
1719
|
+
|
|
1720
|
+
// common events
|
|
1721
|
+
this.eventManager._addCommonEvents();
|
|
1722
|
+
|
|
1723
|
+
// init
|
|
1724
|
+
const iframePromises = [];
|
|
1725
|
+
this.applyFrameRoots((e) => {
|
|
1726
|
+
const o = e.get('originElement');
|
|
1727
|
+
const t = e.get('topArea');
|
|
1728
|
+
o.style.display = 'none';
|
|
1729
|
+
t.style.display = 'block';
|
|
1730
|
+
o.parentNode.insertBefore(t, o.nextElementSibling);
|
|
1731
|
+
|
|
1732
|
+
if (e.get('options').get('iframe')) {
|
|
1733
|
+
const iframeLoaded = new Promise((resolve) => {
|
|
1734
|
+
this.eventManager.addEvent(e.get('wysiwygFrame'), 'load', ({ target }) => {
|
|
1735
|
+
this.__setIframeDocument(target, this.options, e.get('options'));
|
|
1736
|
+
resolve();
|
|
1737
|
+
});
|
|
1738
|
+
});
|
|
1739
|
+
iframePromises.push(iframeLoaded);
|
|
1740
|
+
}
|
|
1741
|
+
});
|
|
1742
|
+
|
|
1743
|
+
this.applyFrameRoots((e) => {
|
|
1744
|
+
e.get('wrapper').appendChild(e.get('wysiwygFrame'));
|
|
1745
|
+
|
|
1746
|
+
// document type
|
|
1747
|
+
if (e.get('documentTypeInner')) {
|
|
1748
|
+
if (this.options.get('_rtl')) e.get('wrapper').appendChild(e.get('documentTypeInner'));
|
|
1749
|
+
else e.get('wrapper').insertBefore(e.get('documentTypeInner'), e.get('wysiwygFrame'));
|
|
1750
|
+
}
|
|
1751
|
+
if (e.get('documentTypePage')) {
|
|
1752
|
+
if (this.options.get('_rtl')) e.get('wrapper').insertBefore(e.get('documentTypePage'), e.get('wysiwygFrame'));
|
|
1753
|
+
else e.get('wrapper').appendChild(e.get('documentTypePage'));
|
|
1754
|
+
// page mirror
|
|
1755
|
+
e.get('wrapper').appendChild(e.get('documentTypePageMirror'));
|
|
1756
|
+
}
|
|
1757
|
+
});
|
|
1758
|
+
|
|
1759
|
+
if (iframePromises.length > 0) {
|
|
1760
|
+
await Promise.all(iframePromises);
|
|
1761
|
+
}
|
|
1762
|
+
|
|
1763
|
+
this.__editorInit(originOptions);
|
|
1764
|
+
},
|
|
1765
|
+
|
|
1766
|
+
Constructor: Editor
|
|
1767
|
+
};
|
|
1768
|
+
|
|
1769
|
+
function RestoreFrameOptions(key, option, frameRoots, rootDiff, newRootKeys, newRoots) {
|
|
1770
|
+
const nro = option[key];
|
|
1771
|
+
const newKeys = Object.keys(nro);
|
|
1772
|
+
CheckResetKeys(newKeys, null, key + '.');
|
|
1773
|
+
if (newKeys.length === 0) return false;
|
|
1774
|
+
|
|
1775
|
+
const rootKey = key || null;
|
|
1776
|
+
rootDiff.set(rootKey, new Map());
|
|
1777
|
+
|
|
1778
|
+
const o = frameRoots.get(rootKey).get('options').get('_origin');
|
|
1779
|
+
const no = {};
|
|
1780
|
+
const hasOwn = Object.prototype.hasOwnProperty;
|
|
1781
|
+
for (const rk in nro) {
|
|
1782
|
+
if (!hasOwn.call(OPTION_FRAME_FIXED_FLAG, rk)) continue;
|
|
1783
|
+
const roV = nro[rk];
|
|
1784
|
+
if (!newKeys.includes(rk) || o[rk] === roV) continue;
|
|
1785
|
+
rootDiff.get(rootKey).set(GetResetDiffKey(rk), true);
|
|
1786
|
+
no[rk] = roV;
|
|
1787
|
+
}
|
|
1788
|
+
|
|
1789
|
+
const newO = { ...o, ...no };
|
|
1790
|
+
newRootKeys.set(rootKey, new Map(Object.entries(newO)));
|
|
1791
|
+
newRoots.push({ key: rootKey, options: newO });
|
|
1792
|
+
}
|
|
1793
|
+
|
|
1794
|
+
function GetResetDiffKey(key) {
|
|
1795
|
+
if (/^statusbar|^charCounter/.test(key)) return 'statusbar-changed';
|
|
1796
|
+
return key;
|
|
1797
|
+
}
|
|
1798
|
+
|
|
1799
|
+
function CheckResetKeys(keys, plugins, root) {
|
|
1800
|
+
for (let i = 0, len = keys.length, k; i < len; i++) {
|
|
1801
|
+
k = keys[i];
|
|
1802
|
+
if (OPTION_FIXED_FLAG[k] === 'fixed' || OPTION_FRAME_FIXED_FLAG[k] === 'fixed' || (plugins && plugins[k])) {
|
|
1803
|
+
console.warn(`[SUNEDITOR.warn.resetOptions] The "[${root + k}]" option cannot be changed after the editor is created.`);
|
|
1804
|
+
keys.splice(i--, 1);
|
|
1805
|
+
len--;
|
|
1806
|
+
}
|
|
1807
|
+
}
|
|
1808
|
+
}
|
|
1809
|
+
|
|
1810
|
+
export default Editor;
|