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,39 +3,85 @@
|
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
5
|
import CoreInjector from '../../editorInjector/_core';
|
|
6
|
-
import {
|
|
6
|
+
import { dom, env, numbers, unicode, keyCodeMap, converter } from '../../helper';
|
|
7
7
|
import { Figure, _DragHandle } from '../../modules';
|
|
8
8
|
|
|
9
9
|
const { _w, ON_OVER_COMPONENT, isMobile } = env;
|
|
10
10
|
const DIR_KEYCODE = /^(3[7-9]|40)$/;
|
|
11
11
|
const DIR_UP_KEYCODE = /^3[7-8]$/;
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
/**
|
|
14
|
+
* @typedef {Omit<Component & Partial<__se__EditorInjector>, 'component'>} ComponentThis
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* @constructor
|
|
19
|
+
* @this {ComponentThis}
|
|
20
|
+
* @description Class for managing components such as images and tables that are not in line format
|
|
21
|
+
* @param {__se__EditorCore} editor - The root editor instance
|
|
22
|
+
*/
|
|
23
|
+
function Component(editor) {
|
|
14
24
|
CoreInjector.call(this, editor);
|
|
15
25
|
|
|
16
|
-
|
|
26
|
+
/**
|
|
27
|
+
* @description The current component information, used copy, cut, and keydown events
|
|
28
|
+
* @type {__se__ComponentInfo}
|
|
29
|
+
*/
|
|
17
30
|
this.info = null;
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* @description Component is selected
|
|
34
|
+
* @type {boolean}
|
|
35
|
+
*/
|
|
18
36
|
this.isSelected = false;
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* @description Currently selected component target
|
|
40
|
+
* @type {Node|null}
|
|
41
|
+
*/
|
|
19
42
|
this.currentTarget = null;
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* @description Currently selected component plugin instance
|
|
46
|
+
* @type {*}
|
|
47
|
+
*/
|
|
20
48
|
this.currentPlugin = null;
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* @description Currently selected component plugin name
|
|
52
|
+
* @type {*}
|
|
53
|
+
*/
|
|
21
54
|
this.currentPluginName = '';
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* @description Currently selected component information
|
|
58
|
+
* @type {__se__ComponentInfo|null}
|
|
59
|
+
*/
|
|
22
60
|
this.currentInfo = null;
|
|
61
|
+
|
|
62
|
+
/** @type {Object<string, (...args: *) => *>} */
|
|
23
63
|
this.__globalEvents = {
|
|
24
64
|
copy: OnCopy_component.bind(this),
|
|
25
65
|
cut: OnCut_component.bind(this),
|
|
26
66
|
keydown: OnKeyDown_component.bind(this),
|
|
27
67
|
mousedown: CloseListener_mousedown.bind(this)
|
|
28
68
|
};
|
|
69
|
+
/** @type {__se__GlobalEventInfo|void} */
|
|
29
70
|
this._bindClose_copy = null;
|
|
71
|
+
/** @type {__se__GlobalEventInfo|void} */
|
|
30
72
|
this._bindClose_cut = null;
|
|
73
|
+
/** @type {__se__GlobalEventInfo|void} */
|
|
31
74
|
this._bindClose_keydown = null;
|
|
75
|
+
/** @type {__se__GlobalEventInfo|void} */
|
|
32
76
|
this._bindClose_mousedown = null;
|
|
77
|
+
/** @type {__se__GlobalEventInfo|void} */
|
|
33
78
|
this._bindClose_touchstart = null;
|
|
79
|
+
/** @type {boolean} */
|
|
34
80
|
this.__selectionSelected = false;
|
|
35
81
|
|
|
36
82
|
this.editor.applyFrameRoots((e) => {
|
|
37
83
|
// drag
|
|
38
|
-
const dragHandle =
|
|
84
|
+
const dragHandle = dom.utils.createElement('DIV', { class: 'se-drag-handle', draggable: 'true' }, this.icons.selection);
|
|
39
85
|
e.get('wrapper').appendChild(dragHandle);
|
|
40
86
|
this.eventManager.addEvent(dragHandle, 'mouseenter', OnDragEnter.bind(this));
|
|
41
87
|
this.eventManager.addEvent(dragHandle, 'mouseleave', OnDragLeave.bind(this));
|
|
@@ -43,19 +89,22 @@ const Component = function (editor) {
|
|
|
43
89
|
this.eventManager.addEvent(dragHandle, 'dragend', OnDragEnd.bind(this));
|
|
44
90
|
this.eventManager.addEvent(dragHandle, 'click', OnDragClick.bind(this));
|
|
45
91
|
});
|
|
46
|
-
}
|
|
92
|
+
}
|
|
47
93
|
|
|
48
94
|
Component.prototype = {
|
|
49
95
|
/**
|
|
50
|
-
* @
|
|
51
|
-
*
|
|
52
|
-
*
|
|
53
|
-
* @param {
|
|
54
|
-
* @param {
|
|
55
|
-
* @
|
|
96
|
+
* @this {ComponentThis}
|
|
97
|
+
* @description Inserts an element and returns it. (Used for elements: table, hr, image, video)
|
|
98
|
+
* - If "element" is "HR", inserts and returns the new line.
|
|
99
|
+
* @param {Node} element Element to be inserted
|
|
100
|
+
* @param {Object} [options] Options
|
|
101
|
+
* @param {boolean} [options.skipCharCount=false] If true, it will be inserted even if "frameOptions.get('charCounter_max')" is exceeded.
|
|
102
|
+
* @param {boolean} [options.skipSelection=false] If true, do not automatically select the inserted component.
|
|
103
|
+
* @param {boolean} [options.skipHistory=false] If true, do not push to history.
|
|
104
|
+
* @returns {HTMLElement} The inserted element or new line (for HR)
|
|
56
105
|
*/
|
|
57
|
-
insert(element,
|
|
58
|
-
if (this.editor.frameContext.get('isReadOnly') || (!
|
|
106
|
+
insert(element, { skipCharCount, skipSelection, skipHistory } = {}) {
|
|
107
|
+
if (this.editor.frameContext.get('isReadOnly') || (!skipCharCount && !this.char.check(element))) {
|
|
59
108
|
return null;
|
|
60
109
|
}
|
|
61
110
|
|
|
@@ -66,45 +115,51 @@ Component.prototype = {
|
|
|
66
115
|
let oNode = null;
|
|
67
116
|
let formatEl = this.format.getLine(selectionNode, null);
|
|
68
117
|
|
|
69
|
-
if (
|
|
70
|
-
this.html.insertNode(element, isInline ? null : selectionNode === formatEl ? null : r.container.nextSibling, true);
|
|
71
|
-
if (!isInline && !element.nextSibling) element.parentNode.appendChild(
|
|
118
|
+
if (dom.check.isListCell(formatEl)) {
|
|
119
|
+
this.html.insertNode(element, { afterNode: isInline ? null : selectionNode === formatEl ? null : r.container.nextSibling, skipCharCount: true });
|
|
120
|
+
if (!isInline && !element.nextSibling) element.parentNode.appendChild(dom.utils.createElement('BR'));
|
|
72
121
|
} else {
|
|
73
|
-
if (this.selection.getRange().collapsed && (r.container.nodeType === 3 ||
|
|
74
|
-
const depthFormat =
|
|
75
|
-
oNode = this.nodeTransform.split(r.container, r.offset, !depthFormat ? 0 :
|
|
76
|
-
if (oNode) formatEl = oNode.previousSibling;
|
|
122
|
+
if (!isInline && this.selection.getRange().collapsed && (r.container.nodeType === 3 || dom.check.isBreak(r.container))) {
|
|
123
|
+
const depthFormat = dom.query.getParentElement(r.container, this.format.isBlock.bind(this.format));
|
|
124
|
+
oNode = this.nodeTransform.split(r.container, r.offset, !depthFormat ? 0 : dom.query.getNodeDepth(depthFormat) + 1);
|
|
125
|
+
if (oNode) formatEl = /** @type {HTMLElement} */ (oNode.previousSibling);
|
|
77
126
|
}
|
|
78
|
-
this.html.insertNode(element, isInline ? null : this.format.isBlock(formatEl) ? null : formatEl, true);
|
|
79
|
-
if (!isInline && formatEl &&
|
|
127
|
+
this.html.insertNode(element, { afterNode: isInline ? null : this.format.isBlock(formatEl) ? null : formatEl, skipCharCount: true });
|
|
128
|
+
if (!isInline && formatEl && dom.check.isZeroWidth(formatEl)) dom.utils.removeItem(formatEl);
|
|
80
129
|
}
|
|
81
130
|
|
|
82
131
|
if (isInline) {
|
|
83
|
-
const empty =
|
|
132
|
+
const empty = dom.utils.createTextNode(unicode.zeroWidthSpace);
|
|
84
133
|
element.parentNode.insertBefore(empty, element.nextSibling);
|
|
85
134
|
}
|
|
86
135
|
|
|
87
|
-
this.history.push(false);
|
|
136
|
+
if (!skipHistory) this.history.push(false);
|
|
88
137
|
|
|
89
|
-
if (!
|
|
138
|
+
if (!skipSelection) {
|
|
90
139
|
this.selection.setRange(element, 0, element, 0);
|
|
91
140
|
const fileComponentInfo = this.get(element);
|
|
92
141
|
if (fileComponentInfo) {
|
|
93
142
|
this.select(fileComponentInfo.target, fileComponentInfo.pluginName);
|
|
94
143
|
} else if (oNode) {
|
|
95
|
-
oNode =
|
|
144
|
+
oNode = dom.query.getEdgeChildNodes(oNode, null).sc || oNode;
|
|
96
145
|
this.selection.setRange(oNode, 0, oNode, 0);
|
|
97
146
|
}
|
|
98
147
|
}
|
|
99
148
|
|
|
100
|
-
|
|
149
|
+
// document type
|
|
150
|
+
if (this.editor.frameContext.has('documentType-use-header')) {
|
|
151
|
+
this.editor.frameContext.get('documentType').reHeader();
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
return /** @type {HTMLElement} */ (oNode || element);
|
|
101
155
|
},
|
|
102
156
|
|
|
103
157
|
/**
|
|
158
|
+
* @this {ComponentThis}
|
|
104
159
|
* @description Gets the file component and that plugin name
|
|
105
|
-
* return: {target, component, pluginName} | null
|
|
106
|
-
* @param {
|
|
107
|
-
* @returns {
|
|
160
|
+
* - return: {target, component, pluginName} | null
|
|
161
|
+
* @param {Node} element Target element (figure tag, component div, file tag)
|
|
162
|
+
* @returns {__se__ComponentInfo|null}
|
|
108
163
|
*/
|
|
109
164
|
get(element) {
|
|
110
165
|
if (!element) return null;
|
|
@@ -113,10 +168,11 @@ Component.prototype = {
|
|
|
113
168
|
let pluginName = '';
|
|
114
169
|
let options = {};
|
|
115
170
|
let isFile = false;
|
|
171
|
+
let launcher = null;
|
|
116
172
|
|
|
117
173
|
if (this.is(element)) {
|
|
118
|
-
if (
|
|
119
|
-
if (/^FIGURE$/i.test(element.nodeName)) element = element.firstElementChild;
|
|
174
|
+
if (dom.utils.hasClass(element, 'se-component') && !dom.utils.hasClass(element, 'se-inline-component')) element = /** @type {HTMLElement} */ (element).firstElementChild || element;
|
|
175
|
+
if (/^FIGURE$/i.test(element.nodeName)) element = /** @type {HTMLElement} */ (element).firstElementChild;
|
|
120
176
|
if (!element) return null;
|
|
121
177
|
|
|
122
178
|
const comp = this.editor._componentManager.map((f) => f(element)).find((e) => e);
|
|
@@ -124,6 +180,7 @@ Component.prototype = {
|
|
|
124
180
|
target = comp.target;
|
|
125
181
|
pluginName = comp.pluginName;
|
|
126
182
|
options = comp.options;
|
|
183
|
+
launcher = comp.launcher;
|
|
127
184
|
}
|
|
128
185
|
|
|
129
186
|
if (!target && element.nodeName) {
|
|
@@ -135,6 +192,7 @@ Component.prototype = {
|
|
|
135
192
|
target = comp.target;
|
|
136
193
|
pluginName = comp.pluginName;
|
|
137
194
|
options = comp.options;
|
|
195
|
+
launcher = comp.launcher;
|
|
138
196
|
}
|
|
139
197
|
|
|
140
198
|
if (!target) {
|
|
@@ -142,31 +200,40 @@ Component.prototype = {
|
|
|
142
200
|
}
|
|
143
201
|
|
|
144
202
|
const figureInfo = Figure.GetContainer(target);
|
|
203
|
+
const container = figureInfo.container || figureInfo.cover || target;
|
|
145
204
|
return (this.info = {
|
|
146
205
|
target,
|
|
147
206
|
pluginName,
|
|
148
207
|
options,
|
|
149
|
-
container:
|
|
208
|
+
container: container,
|
|
150
209
|
cover: figureInfo.cover,
|
|
210
|
+
inlineCover: figureInfo.inlineCover,
|
|
151
211
|
caption: figureInfo.caption,
|
|
152
|
-
isFile
|
|
212
|
+
isFile,
|
|
213
|
+
launcher,
|
|
214
|
+
isInputType: dom.utils.hasClass(container, 'se-input-component')
|
|
153
215
|
});
|
|
154
216
|
},
|
|
155
217
|
|
|
156
218
|
/**
|
|
157
|
-
* @
|
|
158
|
-
* @
|
|
159
|
-
* @param {
|
|
219
|
+
* @this {ComponentThis}
|
|
220
|
+
* @description The component(media, file component, table, etc) is selected and the resizing module is called.
|
|
221
|
+
* @param {Node} element Target element
|
|
222
|
+
* @param {string} pluginName The plugin name for the selected target.
|
|
223
|
+
* @param {Object} [options] Options
|
|
224
|
+
* @param {boolean} [options.isInput=false] Whether the target is an input component.(table)
|
|
160
225
|
*/
|
|
161
|
-
select(element, pluginName, isInput) {
|
|
226
|
+
select(element, pluginName, { isInput = false } = {}) {
|
|
162
227
|
const info = this.get(element);
|
|
163
|
-
if (!info ||
|
|
228
|
+
if (!info || dom.check.isUneditable(dom.query.getParentElement(element, this.is.bind(this))) || dom.check.isUneditable(element)) return false;
|
|
164
229
|
|
|
165
|
-
const plugin = this.plugins[pluginName];
|
|
230
|
+
const plugin = info.launcher || this.plugins[pluginName];
|
|
166
231
|
if (!plugin) return;
|
|
167
232
|
|
|
168
233
|
if (!isInput && _DragHandle.get('__overInfo') !== ON_OVER_COMPONENT) {
|
|
169
|
-
this.editor.
|
|
234
|
+
if (this.editor.status._onMousedown) return;
|
|
235
|
+
|
|
236
|
+
this.editor._preventBlur = true;
|
|
170
237
|
this.__selectionSelected = true;
|
|
171
238
|
if (this.isInline(info.container)) {
|
|
172
239
|
this.selection.setRange(info.container, 0, info.container, 0);
|
|
@@ -182,7 +249,8 @@ Component.prototype = {
|
|
|
182
249
|
let isNonFigureComponent;
|
|
183
250
|
if (typeof plugin.select === 'function') isNonFigureComponent = plugin.select(element);
|
|
184
251
|
|
|
185
|
-
|
|
252
|
+
const isBreakComponent = dom.utils.hasClass(info.target, 'se-component-line-break');
|
|
253
|
+
if (isBreakComponent || (!isNonFigureComponent && !dom.utils.hasClass(info.container, 'se-inline-component'))) this._setComponentLineBreaker(/** @type {HTMLElement} */ (info.container || info.cover || element));
|
|
186
254
|
|
|
187
255
|
this.currentTarget = element;
|
|
188
256
|
this.currentPlugin = plugin;
|
|
@@ -197,31 +265,32 @@ Component.prototype = {
|
|
|
197
265
|
if (__overInfo !== ON_OVER_COMPONENT) this.__addGlobalEvent();
|
|
198
266
|
if (!info.isFile) this.__addNotFileGlobalEvent();
|
|
199
267
|
}, 0);
|
|
200
|
-
domUtils.addClass(info.container, 'se-component-selected');
|
|
201
268
|
|
|
202
|
-
|
|
203
|
-
|
|
269
|
+
converter.debounce(() => {
|
|
270
|
+
dom.utils.addClass(info.container, 'se-component-selected');
|
|
271
|
+
}, 0)();
|
|
204
272
|
|
|
273
|
+
if (!isBreakComponent && __overInfo !== ON_OVER_COMPONENT) {
|
|
205
274
|
// set zero width space
|
|
206
275
|
if (!this.isInline(info.container)) return;
|
|
207
276
|
|
|
208
277
|
const oNode = info.container;
|
|
209
278
|
let zeroWidth = null;
|
|
210
|
-
if (!oNode.previousSibling ||
|
|
211
|
-
zeroWidth =
|
|
279
|
+
if (!oNode.previousSibling || dom.check.isBreak(oNode.previousSibling)) {
|
|
280
|
+
zeroWidth = dom.utils.createTextNode(unicode.zeroWidthSpace);
|
|
212
281
|
oNode.parentNode.insertBefore(zeroWidth, oNode);
|
|
213
282
|
}
|
|
214
283
|
|
|
215
|
-
if (!oNode.nextSibling ||
|
|
216
|
-
zeroWidth =
|
|
284
|
+
if (!oNode.nextSibling || dom.check.isBreak(oNode.nextSibling)) {
|
|
285
|
+
zeroWidth = dom.utils.createTextNode(unicode.zeroWidthSpace);
|
|
217
286
|
oNode.parentNode.insertBefore(zeroWidth, oNode.nextSibling);
|
|
218
287
|
}
|
|
219
288
|
|
|
220
|
-
this.editor.status.
|
|
221
|
-
} else if (!
|
|
289
|
+
this.editor.status.onSelected = true;
|
|
290
|
+
} else if (isBreakComponent || !dom.utils.hasClass(info.container, 'se-input-component')) {
|
|
222
291
|
const dragHandle = this.editor.frameContext.get('wrapper').querySelector('.se-drag-handle');
|
|
223
|
-
|
|
224
|
-
this.
|
|
292
|
+
dom.utils.addClass(dragHandle, 'se-drag-handle-full');
|
|
293
|
+
this.ui._visibleControllers(false, false);
|
|
225
294
|
|
|
226
295
|
const sizeTarget = info.caption ? info.target : info.cover || info.container || info.target;
|
|
227
296
|
const w = sizeTarget.offsetWidth;
|
|
@@ -242,32 +311,40 @@ Component.prototype = {
|
|
|
242
311
|
}
|
|
243
312
|
},
|
|
244
313
|
|
|
314
|
+
/**
|
|
315
|
+
* @this {ComponentThis}
|
|
316
|
+
* @description Deselects the selected component.
|
|
317
|
+
*/
|
|
245
318
|
deselect() {
|
|
246
|
-
|
|
319
|
+
_w.setTimeout(() => {
|
|
320
|
+
this.editor.status.onSelected = false;
|
|
321
|
+
}, 0);
|
|
247
322
|
this.__deselect();
|
|
248
|
-
|
|
323
|
+
this.ui.setControllerOnDisabledButtons(false);
|
|
249
324
|
},
|
|
250
325
|
|
|
251
326
|
/**
|
|
327
|
+
* @this {ComponentThis}
|
|
252
328
|
* @description Determines if the specified node is a block component (e.g., img, iframe, video, audio, table) with the class "se-component"
|
|
253
|
-
* or a direct FIGURE node. This function checks if the node itself is a component
|
|
254
|
-
* or if it belongs to any components identified by the component manager.
|
|
329
|
+
* - or a direct FIGURE node. This function checks if the node itself is a component
|
|
330
|
+
* - or if it belongs to any components identified by the component manager.
|
|
255
331
|
* @param {Node} element The DOM node to check.
|
|
256
332
|
* @returns {boolean} True if the node is a block component or part of it, otherwise false.
|
|
257
333
|
*/
|
|
258
334
|
is(element) {
|
|
259
335
|
if (!element) return false;
|
|
260
336
|
|
|
261
|
-
if (/^FIGURE$/i.test(element.nodeName) ||
|
|
337
|
+
if (/^FIGURE$/i.test(element.nodeName) || dom.utils.hasClass(element, 'se-component')) return true;
|
|
262
338
|
if (this.editor._componentManager.find((f) => f(element))) return true;
|
|
263
339
|
|
|
264
340
|
return false;
|
|
265
341
|
},
|
|
266
342
|
|
|
267
343
|
/**
|
|
344
|
+
* @this {ComponentThis}
|
|
268
345
|
* @description Checks if the given node is an inline component (class "se-inline-component").
|
|
269
|
-
* If the node is a FIGURE, it checks the parent element instead.
|
|
270
|
-
* It also verifies whether the node is part of an inline component recognized by the component manager.
|
|
346
|
+
* - If the node is a FIGURE, it checks the parent element instead.
|
|
347
|
+
* - It also verifies whether the node is part of an inline component recognized by the component manager.
|
|
271
348
|
* @param {Node} element The DOM node to check.
|
|
272
349
|
* @returns {boolean} True if the node is an inline component or part of it, otherwise false.
|
|
273
350
|
*/
|
|
@@ -275,18 +352,19 @@ Component.prototype = {
|
|
|
275
352
|
if (!element) return false;
|
|
276
353
|
|
|
277
354
|
if (/^FIGURE$/i.test(element.nodeName)) element = element.parentElement;
|
|
278
|
-
if (
|
|
355
|
+
if (dom.utils.hasClass(element, 'se-inline-component')) return true;
|
|
279
356
|
|
|
280
357
|
const container = this.editor._componentManager.find((f) => f(element));
|
|
281
|
-
if (container &&
|
|
358
|
+
if (container && dom.utils.hasClass(element, 'se-inline-component')) return true;
|
|
282
359
|
|
|
283
360
|
return false;
|
|
284
361
|
},
|
|
285
362
|
|
|
286
363
|
/**
|
|
364
|
+
* @this {ComponentThis}
|
|
287
365
|
* @description Checks if the specified node qualifies as a basic component within the editor.
|
|
288
|
-
* This function verifies whether the node is recognized as a component by the `is` function, while also ensuring that it is not an inline component as determined by the `isInline` function.
|
|
289
|
-
* This is used to identify block-level elements or standalone components that are not part of the inline component classification.
|
|
366
|
+
* - This function verifies whether the node is recognized as a component by the `is` function, while also ensuring that it is not an inline component as determined by the `isInline` function.
|
|
367
|
+
* - This is used to identify block-level elements or standalone components that are not part of the inline component classification.
|
|
290
368
|
* @param {Node} element The DOM node to check.
|
|
291
369
|
* @returns {boolean} True if the node is a basic (non-inline) component, otherwise false.
|
|
292
370
|
*/
|
|
@@ -294,17 +372,60 @@ Component.prototype = {
|
|
|
294
372
|
return this.is(element) && !this.isInline(element);
|
|
295
373
|
},
|
|
296
374
|
|
|
375
|
+
/**
|
|
376
|
+
* @this {ComponentThis}
|
|
377
|
+
* @description Copies the specified component node to the clipboard.
|
|
378
|
+
* - This function is different from the one called when the user presses the "Ctrl + C" key combination.
|
|
379
|
+
* @param {Node} container The DOM node to check.
|
|
380
|
+
*/
|
|
381
|
+
copy(container) {
|
|
382
|
+
const cloneContainer = /** @type {HTMLElement} */ (dom.utils.clone(container, true));
|
|
383
|
+
|
|
384
|
+
// remove selected class
|
|
385
|
+
dom.utils.removeClass(cloneContainer, 'se-component-selected');
|
|
386
|
+
dom.utils.removeClass(cloneContainer.querySelectorAll('.se-figure-selected'), 'se-figure-selected');
|
|
387
|
+
dom.utils.removeClass(cloneContainer.querySelectorAll('.se-selected-table-cell'), 'se-selected-table-cell');
|
|
388
|
+
dom.utils.removeClass(cloneContainer.querySelector('.se-selected-cell-focus'), 'se-selected-cell-focus');
|
|
389
|
+
|
|
390
|
+
// copy to clipboard
|
|
391
|
+
this.html.copy(cloneContainer);
|
|
392
|
+
|
|
393
|
+
// copy effect
|
|
394
|
+
dom.utils.flashClass(container, 'se-copy');
|
|
395
|
+
},
|
|
396
|
+
|
|
397
|
+
/**
|
|
398
|
+
* @private
|
|
399
|
+
* @this {ComponentThis}
|
|
400
|
+
* @description Checks if the given element is a file component by matching its tag name against the file manager's regular expressions.
|
|
401
|
+
* - It also verifies whether the element has the required attributes based on the tag type.
|
|
402
|
+
* @param {Node} element The element to check.
|
|
403
|
+
* @returns {boolean} Returns true if the element is a file component, otherwise false.
|
|
404
|
+
*/
|
|
297
405
|
__isFiles(element) {
|
|
298
406
|
const nodeName = element.nodeName.toLowerCase();
|
|
299
|
-
return this.editor._fileManager.regExp.test(nodeName) && (!this.editor._fileManager.tagAttrs[nodeName] || this.editor._fileManager.tagAttrs[nodeName]?.every((v) => element.hasAttribute(v)));
|
|
407
|
+
return this.editor._fileManager.regExp.test(nodeName) && (!this.editor._fileManager.tagAttrs[nodeName] || this.editor._fileManager.tagAttrs[nodeName]?.every((v) => /** @type {HTMLElement} */ (element).hasAttribute(v)));
|
|
300
408
|
},
|
|
301
409
|
|
|
410
|
+
/**
|
|
411
|
+
* @private
|
|
412
|
+
* @this {ComponentThis}
|
|
413
|
+
* @description Deselects the currently selected component, removing any selection effects and associated event listeners.
|
|
414
|
+
* - This method resets the selection state and hides UI elements related to the component selection.
|
|
415
|
+
*/
|
|
302
416
|
__deselect() {
|
|
303
|
-
this.editor.
|
|
417
|
+
this.editor._preventBlur = false;
|
|
304
418
|
_DragHandle.set('__overInfo', null);
|
|
305
|
-
this._removeDragEvent(
|
|
306
|
-
|
|
307
|
-
|
|
419
|
+
this._removeDragEvent();
|
|
420
|
+
|
|
421
|
+
if (this.currentInfo) {
|
|
422
|
+
const infoContainer = this.currentInfo.container;
|
|
423
|
+
const infoCover = this.currentInfo.cover;
|
|
424
|
+
converter.debounce(() => {
|
|
425
|
+
dom.utils.removeClass(infoContainer, 'se-component-selected');
|
|
426
|
+
dom.utils.removeClass(infoCover, 'se-figure-over-selected');
|
|
427
|
+
}, 0)();
|
|
428
|
+
}
|
|
308
429
|
|
|
309
430
|
const { frameContext } = this.editor;
|
|
310
431
|
frameContext.get('lineBreaker_t').style.display = frameContext.get('lineBreaker_b').style.display = 'none';
|
|
@@ -319,47 +440,58 @@ Component.prototype = {
|
|
|
319
440
|
this.currentPluginName = '';
|
|
320
441
|
this.currentInfo = null;
|
|
321
442
|
this.__removeGlobalEvent();
|
|
322
|
-
this.
|
|
443
|
+
this.ui.__offControllers();
|
|
323
444
|
},
|
|
324
445
|
|
|
325
446
|
/**
|
|
326
|
-
* @description Set line breaker of component
|
|
327
|
-
* @param {Element} element Element tag
|
|
328
447
|
* @private
|
|
448
|
+
* @this {ComponentThis}
|
|
449
|
+
* @description Set line breaker of component
|
|
450
|
+
* @param {HTMLElement} element Element tag
|
|
329
451
|
*/
|
|
330
452
|
_setComponentLineBreaker(element) {
|
|
453
|
+
const _overInfo = _DragHandle.get('__overInfo') === ON_OVER_COMPONENT;
|
|
331
454
|
this.eventManager._lineBreakComp = null;
|
|
332
455
|
const info = this.get(element);
|
|
333
456
|
if (!info) return;
|
|
334
457
|
|
|
335
458
|
const fc = this.editor.frameContext;
|
|
336
459
|
const container = info.container;
|
|
337
|
-
const isNonSelected =
|
|
460
|
+
const isNonSelected = dom.utils.hasClass(container, 'se-flex-component');
|
|
338
461
|
const lb_t = fc.get('lineBreaker_t');
|
|
339
462
|
const lb_b = fc.get('lineBreaker_b');
|
|
340
463
|
const t_style = lb_t.style;
|
|
341
464
|
const b_style = lb_b.style;
|
|
342
465
|
const offsetTarget = container.offsetWidth < element.offsetWidth ? container : element;
|
|
343
466
|
const target = this.editor._figureContainer?.style.display === 'block' ? this.editor._figureContainer : offsetTarget;
|
|
344
|
-
const isList =
|
|
467
|
+
const isList = dom.check.isListCell(container.parentNode);
|
|
345
468
|
|
|
346
469
|
// top
|
|
347
470
|
let componentTop, w;
|
|
348
471
|
const isRtl = this.options.get('_rtl');
|
|
349
472
|
const dir = isRtl ? ['right', 'left'] : ['left', 'right'];
|
|
350
|
-
const top = offsetTarget
|
|
351
|
-
const
|
|
473
|
+
const { top, left, right, scrollX, scrollY } = this.offset.getLocal(offsetTarget);
|
|
474
|
+
const sideOffset = isRtl ? right : left;
|
|
352
475
|
|
|
353
476
|
if (isList ? !container.previousSibling : !this.format.isLine(container.previousElementSibling)) {
|
|
354
|
-
const
|
|
477
|
+
const cStyle = _w.getComputedStyle(lb_t);
|
|
478
|
+
const cH = numbers.get(cStyle.height, 1);
|
|
479
|
+
const cW = numbers.get(cStyle.width, 1);
|
|
480
|
+
|
|
355
481
|
this.eventManager._lineBreakComp = container;
|
|
356
482
|
componentTop = top;
|
|
357
483
|
w = target.offsetWidth / 2 / 2;
|
|
358
|
-
|
|
359
|
-
t_style
|
|
484
|
+
|
|
485
|
+
t_style.top = componentTop - scrollY - cH / 2 + 'px';
|
|
486
|
+
t_style[dir[0]] = (isNonSelected ? sideOffset - cW / 2 : sideOffset + w) + 'px';
|
|
360
487
|
t_style[dir[1]] = '';
|
|
488
|
+
|
|
361
489
|
lb_t.setAttribute('data-offset', scrollY + ',' + scrollX);
|
|
490
|
+
if (_overInfo) dom.utils.removeClass(lb_t, 'se-on-selected');
|
|
491
|
+
else dom.utils.addClass(lb_t, 'se-on-selected');
|
|
492
|
+
|
|
362
493
|
t_style.display = 'block';
|
|
494
|
+
t_style.visibility = '';
|
|
363
495
|
} else {
|
|
364
496
|
t_style.display = 'none';
|
|
365
497
|
}
|
|
@@ -367,8 +499,8 @@ Component.prototype = {
|
|
|
367
499
|
// bottom
|
|
368
500
|
if (isList ? !container.nextSibling : !this.format.isLine(container.nextElementSibling)) {
|
|
369
501
|
const cStyle = _w.getComputedStyle(lb_b);
|
|
370
|
-
const
|
|
371
|
-
const
|
|
502
|
+
const cH = numbers.get(cStyle.height, 1);
|
|
503
|
+
const cW = numbers.get(cStyle.width, 1);
|
|
372
504
|
|
|
373
505
|
if (!componentTop) {
|
|
374
506
|
this.eventManager._lineBreakComp = container;
|
|
@@ -376,18 +508,26 @@ Component.prototype = {
|
|
|
376
508
|
w = target.offsetWidth / 2 / 2;
|
|
377
509
|
}
|
|
378
510
|
|
|
379
|
-
b_style.top = componentTop + target.offsetHeight - scrollY -
|
|
380
|
-
b_style
|
|
381
|
-
b_style
|
|
511
|
+
b_style.top = componentTop + target.offsetHeight - scrollY - cH / 2 + 'px';
|
|
512
|
+
b_style[dir[0]] = sideOffset + target.offsetWidth - (isNonSelected ? 0 : w) - (isNonSelected ? cW / 2 : cW) + 'px';
|
|
513
|
+
b_style[dir[1]] = '';
|
|
514
|
+
|
|
515
|
+
lb_b.setAttribute('data-offset', scrollY + ',' + dir[0] + ',' + scrollX);
|
|
516
|
+
if (_overInfo) dom.utils.removeClass(lb_b, 'se-on-selected');
|
|
517
|
+
else dom.utils.addClass(lb_b, 'se-on-selected');
|
|
382
518
|
|
|
383
|
-
const bDir = 'left';
|
|
384
|
-
lb_b.setAttribute('data-offset', scrollY + ',' + bDir + ',' + scrollX);
|
|
385
519
|
b_style.display = 'block';
|
|
520
|
+
b_style.visibility = '';
|
|
386
521
|
} else {
|
|
387
522
|
b_style.display = 'none';
|
|
388
523
|
}
|
|
389
524
|
},
|
|
390
525
|
|
|
526
|
+
/**
|
|
527
|
+
* @private
|
|
528
|
+
* @this {ComponentThis}
|
|
529
|
+
* @description Adds global event listeners for component interactions such as copy, cut, and keydown events.
|
|
530
|
+
*/
|
|
391
531
|
__addGlobalEvent() {
|
|
392
532
|
this.__removeGlobalEvent();
|
|
393
533
|
this._bindClose_copy = this.eventManager.addGlobalEvent('copy', this.__globalEvents.copy);
|
|
@@ -395,6 +535,11 @@ Component.prototype = {
|
|
|
395
535
|
this._bindClose_keydown = this.eventManager.addGlobalEvent('keydown', this.__globalEvents.keydown);
|
|
396
536
|
},
|
|
397
537
|
|
|
538
|
+
/**
|
|
539
|
+
* @private
|
|
540
|
+
* @this {ComponentThis}
|
|
541
|
+
* @description Removes global event listeners that were previously added for component interactions.
|
|
542
|
+
*/
|
|
398
543
|
__removeGlobalEvent() {
|
|
399
544
|
this.__removeNotFileGlobalEvent();
|
|
400
545
|
if (this._bindClose_copy) this._bindClose_copy = this.eventManager.removeGlobalEvent(this._bindClose_copy);
|
|
@@ -402,23 +547,38 @@ Component.prototype = {
|
|
|
402
547
|
if (this._bindClose_keydown) this._bindClose_keydown = this.eventManager.removeGlobalEvent(this._bindClose_keydown);
|
|
403
548
|
},
|
|
404
549
|
|
|
550
|
+
/**
|
|
551
|
+
* @private
|
|
552
|
+
* @this {ComponentThis}
|
|
553
|
+
* @description Adds global event listeners for non-file-related interactions such as mouse and touch events.
|
|
554
|
+
*/
|
|
405
555
|
__addNotFileGlobalEvent() {
|
|
406
556
|
this.__removeNotFileGlobalEvent();
|
|
407
557
|
if (!isMobile) this._bindClose_mousedown = this.eventManager.addGlobalEvent('mousedown', this.__globalEvents.mousedown, true);
|
|
408
558
|
else this._bindClose_touchstart = this.eventManager.addGlobalEvent('touchstart', this.__globalEvents.mousedown, true);
|
|
409
559
|
},
|
|
410
560
|
|
|
561
|
+
/**
|
|
562
|
+
* @private
|
|
563
|
+
* @this {ComponentThis}
|
|
564
|
+
* @description Removes global event listeners related to non-file interactions.
|
|
565
|
+
*/
|
|
411
566
|
__removeNotFileGlobalEvent() {
|
|
412
567
|
if (this._bindClose_mousedown) this._bindClose_mousedown = this.eventManager.removeGlobalEvent(this._bindClose_mousedown);
|
|
413
568
|
if (this._bindClose_touchstart) this._bindClose_touchstart = this.eventManager.removeGlobalEvent(this._bindClose_touchstart);
|
|
414
569
|
},
|
|
415
570
|
|
|
571
|
+
/**
|
|
572
|
+
* @private
|
|
573
|
+
* @this {ComponentThis}
|
|
574
|
+
* @description Removes drag-related events and resets drag-related states.
|
|
575
|
+
*/
|
|
416
576
|
_removeDragEvent() {
|
|
417
|
-
this.carrierWrapper.querySelector('.se-drag-cursor').style.left = '-10000px';
|
|
577
|
+
/** @type {HTMLElement} */ (this.carrierWrapper.querySelector('.se-drag-cursor')).style.left = '-10000px';
|
|
418
578
|
if (_DragHandle.get('__dragHandler')) _DragHandle.get('__dragHandler').style.display = 'none';
|
|
419
579
|
|
|
420
|
-
|
|
421
|
-
|
|
580
|
+
dom.utils.removeClass([_DragHandle.get('__dragHandler'), _DragHandle.get('__dragContainer')], 'se-dragging');
|
|
581
|
+
dom.utils.removeClass([_DragHandle.get('__dragCover'), _DragHandle.get('__dragContainer')], 'se-drag-over');
|
|
422
582
|
|
|
423
583
|
_DragHandle.set('__figureInst', null);
|
|
424
584
|
_DragHandle.set('__dragInst', null);
|
|
@@ -432,18 +592,28 @@ Component.prototype = {
|
|
|
432
592
|
constructor: Component
|
|
433
593
|
};
|
|
434
594
|
|
|
595
|
+
/**
|
|
596
|
+
* @this {ComponentThis}
|
|
597
|
+
*/
|
|
435
598
|
function OnDragEnter() {
|
|
436
|
-
this.editor.
|
|
437
|
-
this.
|
|
438
|
-
|
|
599
|
+
this.editor._preventBlur = true;
|
|
600
|
+
this.ui._visibleControllers(false, dom.utils.hasClass(_DragHandle.get('__dragHandler'), 'se-drag-handle-full'));
|
|
601
|
+
dom.utils.addClass(_DragHandle.get('__dragCover') || _DragHandle.get('__dragContainer'), 'se-drag-over');
|
|
439
602
|
}
|
|
440
603
|
|
|
604
|
+
/**
|
|
605
|
+
* @this {ComponentThis}
|
|
606
|
+
*/
|
|
441
607
|
function OnDragLeave() {
|
|
442
|
-
this.editor.
|
|
443
|
-
if (!
|
|
444
|
-
|
|
608
|
+
this.editor._preventBlur = false;
|
|
609
|
+
if (!dom.utils.hasClass(_DragHandle.get('__dragHandler'), 'se-drag-handle-full')) this.ui._visibleControllers(true, true);
|
|
610
|
+
dom.utils.removeClass([_DragHandle.get('__dragCover'), _DragHandle.get('__dragContainer')], 'se-drag-over');
|
|
445
611
|
}
|
|
446
612
|
|
|
613
|
+
/**
|
|
614
|
+
* @this {ComponentThis}
|
|
615
|
+
* @param {DragEvent} e - Drag event
|
|
616
|
+
*/
|
|
447
617
|
function OnDragStart(e) {
|
|
448
618
|
const cover = _DragHandle.get('__dragCover') || _DragHandle.get('__dragContainer');
|
|
449
619
|
|
|
@@ -452,29 +622,44 @@ function OnDragStart(e) {
|
|
|
452
622
|
return;
|
|
453
623
|
}
|
|
454
624
|
|
|
455
|
-
this.editor.
|
|
456
|
-
|
|
457
|
-
|
|
625
|
+
this.editor._preventBlur = false;
|
|
626
|
+
dom.utils.addClass(_DragHandle.get('__dragHandler'), 'se-dragging');
|
|
627
|
+
dom.utils.addClass(_DragHandle.get('__dragContainer'), 'se-dragging');
|
|
458
628
|
e.dataTransfer.setDragImage(cover, this.options.get('_rtl') ? cover.offsetWidth : -5, -5);
|
|
459
629
|
}
|
|
460
630
|
|
|
631
|
+
/**
|
|
632
|
+
* @this {ComponentThis}
|
|
633
|
+
*/
|
|
461
634
|
function OnDragEnd() {
|
|
462
|
-
this.editor.
|
|
463
|
-
|
|
635
|
+
this.editor._preventBlur = false;
|
|
636
|
+
dom.utils.removeClass([_DragHandle.get('__dragHandler'), _DragHandle.get('__dragContainer')], 'se-dragging');
|
|
464
637
|
this._removeDragEvent();
|
|
465
638
|
}
|
|
466
639
|
|
|
467
|
-
|
|
468
|
-
|
|
640
|
+
/**
|
|
641
|
+
* @this {ComponentThis}
|
|
642
|
+
* @param {MouseEvent} e - Mouse event
|
|
643
|
+
*/
|
|
644
|
+
function OnDragClick(e) {
|
|
645
|
+
const target = dom.query.getEventTarget(e);
|
|
646
|
+
if (!dom.utils.hasClass(target, 'se-drag-handle-full')) return;
|
|
647
|
+
|
|
469
648
|
const dragInst = _DragHandle.get('__dragInst');
|
|
470
|
-
this.
|
|
649
|
+
this._removeDragEvent();
|
|
650
|
+
this.select(dragInst.currentTarget, dragInst.currentPluginName);
|
|
471
651
|
}
|
|
472
652
|
|
|
473
|
-
|
|
653
|
+
/**
|
|
654
|
+
* @this {ComponentThis}
|
|
655
|
+
* @param {MouseEvent} e - Mouse event
|
|
656
|
+
*/
|
|
657
|
+
function CloseListener_mousedown(e) {
|
|
658
|
+
const target = dom.query.getEventTarget(e);
|
|
474
659
|
if (
|
|
475
660
|
this.currentTarget?.contains(target) ||
|
|
476
|
-
|
|
477
|
-
|
|
661
|
+
dom.query.getParentElement(target, '.se-controller') ||
|
|
662
|
+
dom.utils.hasClass(target, 'se-drag-handle') ||
|
|
478
663
|
(this.currentPluginName === this.editor.currentControllerName && this.editor.opendControllers.some(({ form }) => form.contains(target)))
|
|
479
664
|
) {
|
|
480
665
|
return;
|
|
@@ -482,39 +667,58 @@ function CloseListener_mousedown({ target }) {
|
|
|
482
667
|
this.deselect();
|
|
483
668
|
}
|
|
484
669
|
|
|
670
|
+
/**
|
|
671
|
+
* @this {ComponentThis}
|
|
672
|
+
* @param {ClipboardEvent} e - Event object
|
|
673
|
+
*/
|
|
485
674
|
function OnCopy_component(e) {
|
|
486
|
-
|
|
675
|
+
const target = dom.query.getEventTarget(e);
|
|
676
|
+
if (dom.check.isInputElement(target) && dom.query.getParentElement(target, '.se-modal')) return;
|
|
487
677
|
|
|
488
678
|
const info = this.info;
|
|
489
679
|
if (!info) return;
|
|
490
680
|
|
|
491
|
-
|
|
492
|
-
|
|
681
|
+
const cloneContainer = info.container.cloneNode(true);
|
|
682
|
+
dom.utils.removeClass(cloneContainer, 'se-component-selected');
|
|
683
|
+
|
|
684
|
+
if (typeof this.plugins[info.pluginName]?.onCopyComponent !== 'function' || this.plugins[info.pluginName].onCopyComponent({ event: e, cloneContainer, info }) === false) {
|
|
685
|
+
SetClipboardComponent(e, cloneContainer, e.clipboardData);
|
|
686
|
+
}
|
|
687
|
+
|
|
493
688
|
// copy effect
|
|
494
|
-
|
|
495
|
-
domUtils.removeClass(info.container, 'se-copy');
|
|
496
|
-
}, 120);
|
|
689
|
+
dom.utils.flashClass(info.container, 'se-copy');
|
|
497
690
|
}
|
|
498
691
|
|
|
692
|
+
/**
|
|
693
|
+
* @this {ComponentThis}
|
|
694
|
+
* @param {ClipboardEvent} e - Event object
|
|
695
|
+
*/
|
|
499
696
|
function OnCut_component(e) {
|
|
500
697
|
const info = this.info;
|
|
501
698
|
if (!info) return;
|
|
502
699
|
|
|
503
|
-
|
|
700
|
+
const cloneContainer = info.container.cloneNode(true);
|
|
701
|
+
dom.utils.removeClass(cloneContainer, 'se-component-selected');
|
|
702
|
+
|
|
703
|
+
SetClipboardComponent(e, cloneContainer, e.clipboardData);
|
|
504
704
|
this.deselect();
|
|
505
|
-
|
|
705
|
+
dom.utils.removeItem(info.container);
|
|
506
706
|
}
|
|
507
707
|
|
|
508
|
-
|
|
708
|
+
/**
|
|
709
|
+
* @this {ComponentThis}
|
|
710
|
+
* @param {KeyboardEvent} e - Event object
|
|
711
|
+
*/
|
|
712
|
+
async function OnKeyDown_component(e) {
|
|
509
713
|
if (this.editor.selectMenuOn) return;
|
|
510
714
|
|
|
511
|
-
const keyCode = e.
|
|
512
|
-
const ctrl =
|
|
715
|
+
const keyCode = e.code;
|
|
716
|
+
const ctrl = keyCodeMap.isCtrl(e);
|
|
513
717
|
|
|
514
718
|
// redo, undo
|
|
515
719
|
if (ctrl) {
|
|
516
|
-
if (keyCode !==
|
|
517
|
-
const info = this.editor.shortcutsKeyMap.get(keyCode + (e.shiftKey ? 1000 :
|
|
720
|
+
if (keyCode !== 'ControlRight' && keyCode !== 'ControlLeft') {
|
|
721
|
+
const info = this.editor.shortcutsKeyMap.get(keyCode + (e.shiftKey ? '1000' : ''));
|
|
518
722
|
if (/^(redo|undo)$/.test(info?.c)) {
|
|
519
723
|
e.preventDefault();
|
|
520
724
|
e.stopPropagation();
|
|
@@ -525,11 +729,11 @@ function OnKeyDown_component(e) {
|
|
|
525
729
|
}
|
|
526
730
|
|
|
527
731
|
// backspace key, delete key
|
|
528
|
-
if (keyCode
|
|
732
|
+
if (keyCodeMap.isRemoveKey(keyCode)) {
|
|
529
733
|
e.preventDefault();
|
|
530
734
|
e.stopPropagation();
|
|
531
735
|
if (typeof this.currentPlugin?.destroy === 'function') {
|
|
532
|
-
this.currentPlugin.destroy(this.currentTarget);
|
|
736
|
+
await this.currentPlugin.destroy(this.currentTarget);
|
|
533
737
|
this.deselect();
|
|
534
738
|
this.editor.focus();
|
|
535
739
|
return;
|
|
@@ -537,16 +741,16 @@ function OnKeyDown_component(e) {
|
|
|
537
741
|
}
|
|
538
742
|
|
|
539
743
|
// enter key
|
|
540
|
-
if (keyCode
|
|
744
|
+
if (keyCodeMap.isEnter(keyCode)) {
|
|
541
745
|
e.preventDefault();
|
|
542
746
|
const compContext = this.currentInfo || this.get(this.currentTarget);
|
|
543
747
|
const container = compContext.container || compContext.target;
|
|
544
748
|
const sibling = container.previousElementSibling || container.nextElementSibling;
|
|
545
749
|
let newEl = null;
|
|
546
|
-
if (
|
|
547
|
-
newEl =
|
|
750
|
+
if (dom.check.isListCell(container.parentNode)) {
|
|
751
|
+
newEl = dom.utils.createElement('BR');
|
|
548
752
|
} else {
|
|
549
|
-
newEl =
|
|
753
|
+
newEl = dom.utils.createElement(this.format.isLine(sibling) ? sibling.nodeName : this.options.get('defaultLine'), null, '<br>');
|
|
550
754
|
}
|
|
551
755
|
|
|
552
756
|
const pluginName = this.currentPluginName;
|
|
@@ -567,21 +771,22 @@ function OnKeyDown_component(e) {
|
|
|
567
771
|
let offset = 1;
|
|
568
772
|
if (isInline) {
|
|
569
773
|
switch (keyCode) {
|
|
570
|
-
case
|
|
774
|
+
case 'ArrowLeft': // left
|
|
571
775
|
el = container.previousSibling;
|
|
572
776
|
offset = el?.nodeType === 3 ? el.textContent.length : 1;
|
|
573
777
|
break;
|
|
574
|
-
case
|
|
778
|
+
case 'ArrowRight': // right
|
|
575
779
|
el = container.nextSibling;
|
|
780
|
+
offset = 0;
|
|
576
781
|
break;
|
|
577
|
-
case
|
|
782
|
+
case 'ArrowUp': {
|
|
578
783
|
// up
|
|
579
784
|
const line = this.format.getLine(container, null);
|
|
580
785
|
el = line?.previousElementSibling;
|
|
581
786
|
offset = 0;
|
|
582
787
|
break;
|
|
583
788
|
}
|
|
584
|
-
case
|
|
789
|
+
case 'ArrowDown': {
|
|
585
790
|
// down
|
|
586
791
|
const line = this.format.getLine(container, null);
|
|
587
792
|
el = line?.nextElementSibling;
|
|
@@ -607,16 +812,21 @@ function OnKeyDown_component(e) {
|
|
|
607
812
|
e.preventDefault();
|
|
608
813
|
this.select(elComp.target, elComp.pluginName);
|
|
609
814
|
} else {
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
815
|
+
try {
|
|
816
|
+
this.editor._preventBlur = true;
|
|
817
|
+
e.stopPropagation();
|
|
818
|
+
e.preventDefault();
|
|
819
|
+
this.selection.setRange(el, offset, el, offset);
|
|
820
|
+
} finally {
|
|
821
|
+
this.editor._preventBlur = false;
|
|
822
|
+
}
|
|
613
823
|
}
|
|
614
824
|
|
|
615
825
|
return;
|
|
616
826
|
}
|
|
617
827
|
|
|
618
828
|
// ESC
|
|
619
|
-
if (keyCode
|
|
829
|
+
if (keyCodeMap.isEsc(keyCode)) {
|
|
620
830
|
this.deselect();
|
|
621
831
|
return;
|
|
622
832
|
}
|
|
@@ -625,10 +835,8 @@ function OnKeyDown_component(e) {
|
|
|
625
835
|
function SetClipboardComponent(e, container, clipboardData) {
|
|
626
836
|
e.preventDefault();
|
|
627
837
|
e.stopPropagation();
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
pasteContainer.querySelectorAll('.se-figure-selected').forEach((el) => domUtils.removeClass(el, 'se-figure-selected'));
|
|
631
|
-
clipboardData.setData('text/html', pasteContainer.outerHTML);
|
|
838
|
+
container.querySelectorAll('.se-figure-selected').forEach((el) => dom.utils.removeClass(el, 'se-figure-selected'));
|
|
839
|
+
clipboardData.setData('text/html', container.outerHTML);
|
|
632
840
|
}
|
|
633
841
|
|
|
634
842
|
export default Component;
|