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