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