suneditor 2.46.2 → 3.0.0-alpha.10

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.
Files changed (290) hide show
  1. package/.eslintignore +7 -0
  2. package/.eslintrc.json +64 -0
  3. package/CONTRIBUTING.md +36 -0
  4. package/LICENSE.txt +1 -1
  5. package/README.md +11 -1560
  6. package/dist/suneditor.min.css +1 -0
  7. package/dist/suneditor.min.js +1 -2
  8. package/package.json +97 -70
  9. package/src/assets/icons/_default.js +194 -0
  10. package/src/assets/suneditor-contents.css +643 -0
  11. package/src/assets/suneditor.css +3394 -0
  12. package/src/core/base/eventHandlers/handler_toolbar.js +114 -0
  13. package/src/core/base/eventHandlers/handler_ww_clipboard.js +37 -0
  14. package/src/core/base/eventHandlers/handler_ww_dragDrop.js +74 -0
  15. package/src/core/base/eventHandlers/handler_ww_key_input.js +1002 -0
  16. package/src/core/base/eventHandlers/handler_ww_mouse.js +147 -0
  17. package/src/core/base/eventManager.js +1156 -0
  18. package/src/core/base/events.js +320 -0
  19. package/src/core/base/history.js +301 -0
  20. package/src/core/class/char.js +147 -0
  21. package/src/core/class/component.js +639 -0
  22. package/src/core/class/format.js +3258 -0
  23. package/src/core/class/html.js +1710 -0
  24. package/src/core/class/menu.js +260 -0
  25. package/src/core/class/nodeTransform.js +405 -0
  26. package/src/core/class/notice.js +42 -0
  27. package/src/core/class/offset.js +575 -0
  28. package/src/core/class/selection.js +511 -0
  29. package/src/core/class/shortcuts.js +38 -0
  30. package/src/core/class/toolbar.js +440 -0
  31. package/src/core/class/viewer.js +646 -0
  32. package/src/core/editor.js +1601 -0
  33. package/src/core/section/actives.js +145 -0
  34. package/src/core/section/constructor.js +1252 -0
  35. package/src/core/section/context.js +97 -0
  36. package/src/editorInjector/_classes.js +22 -0
  37. package/src/editorInjector/_core.js +28 -0
  38. package/src/editorInjector/index.js +13 -0
  39. package/src/helper/converter.js +388 -0
  40. package/src/helper/domUtils.js +1177 -0
  41. package/src/helper/env.js +250 -0
  42. package/src/helper/index.js +19 -0
  43. package/src/helper/numbers.js +68 -0
  44. package/src/helper/unicode.js +43 -0
  45. package/src/langs/ckb.js +161 -0
  46. package/src/langs/cs.js +161 -0
  47. package/src/langs/da.js +161 -0
  48. package/src/langs/de.js +162 -0
  49. package/src/langs/en.js +210 -0
  50. package/src/langs/es.js +162 -0
  51. package/src/langs/fa.js +159 -0
  52. package/src/langs/fr.js +161 -0
  53. package/src/langs/he.js +162 -0
  54. package/src/{lang → langs}/index.js +0 -2
  55. package/src/langs/it.js +162 -0
  56. package/src/langs/ja.js +162 -0
  57. package/src/langs/ko.js +210 -0
  58. package/src/langs/lv.js +162 -0
  59. package/src/langs/nl.js +162 -0
  60. package/src/langs/pl.js +162 -0
  61. package/src/langs/pt_br.js +162 -0
  62. package/src/langs/ro.js +162 -0
  63. package/src/langs/ru.js +162 -0
  64. package/src/langs/se.js +162 -0
  65. package/src/langs/tr.js +159 -0
  66. package/src/langs/ua.js +162 -0
  67. package/src/langs/ur.js +162 -0
  68. package/src/langs/zh_cn.js +162 -0
  69. package/src/modules/ApiManager.js +168 -0
  70. package/src/modules/ColorPicker.js +302 -0
  71. package/src/modules/Controller.js +323 -0
  72. package/src/modules/Figure.js +1176 -0
  73. package/src/modules/FileBrowser.js +271 -0
  74. package/src/modules/FileManager.js +307 -0
  75. package/src/modules/HueSlider.js +513 -0
  76. package/src/modules/Modal.js +177 -0
  77. package/src/modules/ModalAnchorEditor.js +494 -0
  78. package/src/modules/SelectMenu.js +447 -0
  79. package/src/modules/_DragHandle.js +16 -0
  80. package/src/modules/index.js +14 -0
  81. package/src/plugins/command/blockquote.js +47 -47
  82. package/src/plugins/command/exportPdf.js +168 -0
  83. package/src/plugins/command/fileUpload.js +389 -0
  84. package/src/plugins/command/list_bulleted.js +112 -0
  85. package/src/plugins/command/list_numbered.js +115 -0
  86. package/src/plugins/dropdown/align.js +143 -0
  87. package/src/plugins/dropdown/backgroundColor.js +90 -0
  88. package/src/plugins/dropdown/font.js +113 -0
  89. package/src/plugins/dropdown/fontColor.js +90 -0
  90. package/src/plugins/dropdown/formatBlock.js +141 -0
  91. package/src/plugins/dropdown/hr.js +111 -0
  92. package/src/plugins/dropdown/layout.js +72 -0
  93. package/src/plugins/dropdown/lineHeight.js +114 -0
  94. package/src/plugins/dropdown/list.js +107 -0
  95. package/src/plugins/dropdown/paragraphStyle.js +117 -0
  96. package/src/plugins/dropdown/table.js +2810 -0
  97. package/src/plugins/dropdown/template.js +71 -0
  98. package/src/plugins/dropdown/textStyle.js +137 -0
  99. package/src/plugins/field/mention.js +181 -0
  100. package/src/plugins/fileBrowser/imageGallery.js +76 -59
  101. package/src/plugins/index.js +86 -24
  102. package/src/plugins/input/fontSize.js +357 -0
  103. package/src/plugins/modal/audio.js +492 -0
  104. package/src/plugins/modal/image.js +1064 -0
  105. package/src/plugins/modal/link.js +211 -0
  106. package/src/plugins/modal/math.js +363 -0
  107. package/src/plugins/modal/video.js +870 -0
  108. package/src/suneditor.js +62 -67
  109. package/src/themes/test.css +61 -0
  110. package/typings/CommandPlugin.d.ts +8 -0
  111. package/typings/DialogPlugin.d.ts +20 -0
  112. package/typings/FileBrowserPlugin.d.ts +30 -0
  113. package/typings/Lang.d.ts +124 -0
  114. package/typings/Module.d.ts +15 -0
  115. package/typings/Plugin.d.ts +42 -0
  116. package/typings/SubmenuPlugin.d.ts +8 -0
  117. package/typings/_classes.d.ts +17 -0
  118. package/typings/_colorPicker.d.ts +60 -0
  119. package/typings/_core.d.ts +55 -0
  120. package/typings/align.d.ts +5 -0
  121. package/{src/plugins/dialog → typings}/audio.d.ts +1 -1
  122. package/typings/backgroundColor.d.ts +5 -0
  123. package/{src/plugins/command → typings}/blockquote.d.ts +1 -1
  124. package/typings/char.d.ts +39 -0
  125. package/typings/component.d.ts +38 -0
  126. package/typings/context.d.ts +39 -0
  127. package/typings/converter.d.ts +33 -0
  128. package/typings/dialog.d.ts +28 -0
  129. package/typings/domUtils.d.ts +361 -0
  130. package/typings/editor.d.ts +7 -0
  131. package/typings/editor.ts +542 -0
  132. package/typings/env.d.ts +70 -0
  133. package/typings/eventManager.d.ts +37 -0
  134. package/typings/events.d.ts +262 -0
  135. package/typings/fileBrowser.d.ts +42 -0
  136. package/typings/fileManager.d.ts +67 -0
  137. package/typings/font.d.ts +5 -0
  138. package/typings/fontColor.d.ts +5 -0
  139. package/typings/fontSize.d.ts +5 -0
  140. package/typings/format.d.ts +191 -0
  141. package/typings/formatBlock.d.ts +5 -0
  142. package/typings/history.d.ts +48 -0
  143. package/typings/horizontalRule.d.ts +5 -0
  144. package/{src/plugins/dialog → typings}/image.d.ts +1 -1
  145. package/{src/plugins/fileBrowser → typings}/imageGallery.d.ts +1 -1
  146. package/typings/index.d.ts +21 -0
  147. package/{src/plugins/modules/index.d.ts → typings/index.modules.d.ts} +3 -3
  148. package/typings/index.plugins.d.ts +58 -0
  149. package/typings/lineHeight.d.ts +5 -0
  150. package/{src/plugins/dialog → typings}/link.d.ts +1 -1
  151. package/typings/list.d.ts +5 -0
  152. package/{src/plugins/dialog → typings}/math.d.ts +1 -1
  153. package/typings/mediaContainer.d.ts +25 -0
  154. package/typings/node.d.ts +57 -0
  155. package/typings/notice.d.ts +16 -0
  156. package/typings/numbers.d.ts +29 -0
  157. package/typings/offset.d.ts +24 -0
  158. package/typings/options.d.ts +589 -0
  159. package/typings/paragraphStyle.d.ts +5 -0
  160. package/typings/resizing.d.ts +141 -0
  161. package/typings/selection.d.ts +94 -0
  162. package/typings/shortcuts.d.ts +13 -0
  163. package/typings/suneditor.d.ts +9 -0
  164. package/typings/table.d.ts +5 -0
  165. package/typings/template.d.ts +5 -0
  166. package/typings/textStyle.d.ts +5 -0
  167. package/typings/toolbar.d.ts +32 -0
  168. package/typings/unicode.d.ts +25 -0
  169. package/{src/plugins/dialog → typings}/video.d.ts +1 -1
  170. package/dist/css/suneditor.min.css +0 -1
  171. package/src/assets/css/suneditor-contents.css +0 -562
  172. package/src/assets/css/suneditor.css +0 -566
  173. package/src/assets/defaultIcons.js +0 -103
  174. package/src/lang/Lang.d.ts +0 -144
  175. package/src/lang/ckb.d.ts +0 -5
  176. package/src/lang/ckb.js +0 -188
  177. package/src/lang/cs.d.ts +0 -5
  178. package/src/lang/cs.js +0 -188
  179. package/src/lang/da.d.ts +0 -5
  180. package/src/lang/da.js +0 -191
  181. package/src/lang/de.d.ts +0 -5
  182. package/src/lang/de.js +0 -188
  183. package/src/lang/en.d.ts +0 -5
  184. package/src/lang/en.js +0 -188
  185. package/src/lang/es.d.ts +0 -5
  186. package/src/lang/es.js +0 -188
  187. package/src/lang/fa.d.ts +0 -5
  188. package/src/lang/fa.js +0 -188
  189. package/src/lang/fr.d.ts +0 -5
  190. package/src/lang/fr.js +0 -188
  191. package/src/lang/he.d.ts +0 -5
  192. package/src/lang/he.js +0 -188
  193. package/src/lang/index.d.ts +0 -23
  194. package/src/lang/it.d.ts +0 -5
  195. package/src/lang/it.js +0 -188
  196. package/src/lang/ja.d.ts +0 -5
  197. package/src/lang/ja.js +0 -188
  198. package/src/lang/ko.d.ts +0 -5
  199. package/src/lang/ko.js +0 -188
  200. package/src/lang/lv.d.ts +0 -5
  201. package/src/lang/lv.js +0 -188
  202. package/src/lang/nl.d.ts +0 -5
  203. package/src/lang/nl.js +0 -188
  204. package/src/lang/pl.d.ts +0 -5
  205. package/src/lang/pl.js +0 -188
  206. package/src/lang/pt_br.d.ts +0 -5
  207. package/src/lang/pt_br.js +0 -189
  208. package/src/lang/ro.d.ts +0 -5
  209. package/src/lang/ro.js +0 -188
  210. package/src/lang/ru.d.ts +0 -5
  211. package/src/lang/ru.js +0 -188
  212. package/src/lang/se.d.ts +0 -5
  213. package/src/lang/se.js +0 -191
  214. package/src/lang/tr.d.ts +0 -5
  215. package/src/lang/tr.js +0 -191
  216. package/src/lang/ua.d.ts +0 -5
  217. package/src/lang/ua.js +0 -188
  218. package/src/lang/ur.d.ts +0 -5
  219. package/src/lang/ur.js +0 -188
  220. package/src/lang/zh_cn.d.ts +0 -5
  221. package/src/lang/zh_cn.js +0 -187
  222. package/src/lib/constructor.js +0 -954
  223. package/src/lib/context.d.ts +0 -42
  224. package/src/lib/context.js +0 -71
  225. package/src/lib/core.d.ts +0 -1135
  226. package/src/lib/core.js +0 -9395
  227. package/src/lib/history.d.ts +0 -48
  228. package/src/lib/history.js +0 -219
  229. package/src/lib/util.d.ts +0 -678
  230. package/src/lib/util.js +0 -2131
  231. package/src/options.d.ts +0 -608
  232. package/src/plugins/CommandPlugin.d.ts +0 -8
  233. package/src/plugins/DialogPlugin.d.ts +0 -20
  234. package/src/plugins/FileBrowserPlugin.d.ts +0 -30
  235. package/src/plugins/Module.d.ts +0 -15
  236. package/src/plugins/Plugin.d.ts +0 -42
  237. package/src/plugins/SubmenuPlugin.d.ts +0 -8
  238. package/src/plugins/dialog/audio.js +0 -559
  239. package/src/plugins/dialog/image.js +0 -1126
  240. package/src/plugins/dialog/link.js +0 -223
  241. package/src/plugins/dialog/math.js +0 -295
  242. package/src/plugins/dialog/mention.js +0 -242
  243. package/src/plugins/dialog/video.js +0 -979
  244. package/src/plugins/index.d.ts +0 -79
  245. package/src/plugins/modules/_anchor.js +0 -461
  246. package/src/plugins/modules/_colorPicker.d.ts +0 -60
  247. package/src/plugins/modules/_colorPicker.js +0 -201
  248. package/src/plugins/modules/_notice.d.ts +0 -21
  249. package/src/plugins/modules/_notice.js +0 -72
  250. package/src/plugins/modules/_selectMenu.js +0 -119
  251. package/src/plugins/modules/component.d.ts +0 -25
  252. package/src/plugins/modules/component.js +0 -81
  253. package/src/plugins/modules/dialog.d.ts +0 -28
  254. package/src/plugins/modules/dialog.js +0 -175
  255. package/src/plugins/modules/fileBrowser.d.ts +0 -42
  256. package/src/plugins/modules/fileBrowser.js +0 -374
  257. package/src/plugins/modules/fileManager.d.ts +0 -67
  258. package/src/plugins/modules/fileManager.js +0 -326
  259. package/src/plugins/modules/index.js +0 -9
  260. package/src/plugins/modules/resizing.d.ts +0 -154
  261. package/src/plugins/modules/resizing.js +0 -903
  262. package/src/plugins/submenu/align.d.ts +0 -5
  263. package/src/plugins/submenu/align.js +0 -160
  264. package/src/plugins/submenu/font.d.ts +0 -5
  265. package/src/plugins/submenu/font.js +0 -123
  266. package/src/plugins/submenu/fontColor.d.ts +0 -5
  267. package/src/plugins/submenu/fontColor.js +0 -101
  268. package/src/plugins/submenu/fontSize.d.ts +0 -5
  269. package/src/plugins/submenu/fontSize.js +0 -112
  270. package/src/plugins/submenu/formatBlock.d.ts +0 -5
  271. package/src/plugins/submenu/formatBlock.js +0 -273
  272. package/src/plugins/submenu/hiliteColor.d.ts +0 -5
  273. package/src/plugins/submenu/hiliteColor.js +0 -102
  274. package/src/plugins/submenu/horizontalRule.d.ts +0 -5
  275. package/src/plugins/submenu/horizontalRule.js +0 -98
  276. package/src/plugins/submenu/lineHeight.d.ts +0 -5
  277. package/src/plugins/submenu/lineHeight.js +0 -104
  278. package/src/plugins/submenu/list.d.ts +0 -5
  279. package/src/plugins/submenu/list.js +0 -456
  280. package/src/plugins/submenu/paragraphStyle.d.ts +0 -5
  281. package/src/plugins/submenu/paragraphStyle.js +0 -135
  282. package/src/plugins/submenu/table.d.ts +0 -5
  283. package/src/plugins/submenu/table.js +0 -1431
  284. package/src/plugins/submenu/template.d.ts +0 -5
  285. package/src/plugins/submenu/template.js +0 -72
  286. package/src/plugins/submenu/textStyle.d.ts +0 -5
  287. package/src/plugins/submenu/textStyle.js +0 -167
  288. package/src/suneditor.d.ts +0 -9
  289. package/src/suneditor_build.js +0 -18
  290. /package/{src/plugins/dialog → typings}/mention.d.ts +0 -0
@@ -0,0 +1,1156 @@
1
+ /**
2
+ * @fileoverview eventManager class
3
+ */
4
+
5
+ import CoreInjector from '../../editorInjector/_core';
6
+ import { domUtils, unicode, numbers, env, converter } from '../../helper';
7
+ import { _DragHandle } from '../../modules';
8
+
9
+ // event handlers
10
+ import { ButtonsHandler, OnClick_menuTray, OnClick_toolbar } from './eventHandlers/handler_toolbar';
11
+ import { OnMouseDown_wysiwyg, OnMouseUp_wysiwyg, OnClick_wysiwyg, OnMouseMove_wysiwyg, OnMouseLeave_wysiwyg } from './eventHandlers/handler_ww_mouse';
12
+ import { OnInput_wysiwyg, OnKeyDown_wysiwyg, OnKeyUp_wysiwyg } from './eventHandlers/handler_ww_key_input';
13
+ import { OnPaste_wysiwyg, OnCopy_wysiwyg, OnCut_wysiwyg } from './eventHandlers/handler_ww_clipboard';
14
+ import { OnDragOver_wysiwyg, OnDragEnd_wysiwyg, OnDrop_wysiwyg } from './eventHandlers/handler_ww_dragDrop';
15
+
16
+ const { _w, ON_OVER_COMPONENT, isMobile } = env;
17
+
18
+ const EventManager = function (editor) {
19
+ CoreInjector.call(this, editor);
20
+ this._events = [];
21
+ this._onButtonsCheck = new RegExp(`^(${Object.keys(editor.options.get('_defaultStyleTagMap')).join('|')})$`, 'i');
22
+ this._onShortcutKey = false;
23
+ this.isComposing = false; // Old browsers: When there is no 'e.isComposing' in the keyup event.
24
+ this._balloonDelay = null;
25
+ this._wwFrameObserver = null;
26
+ this._toolbarObserver = null;
27
+ this._lineBreakDir = null;
28
+ this._lineBreakComp = null;
29
+ this._formatAttrsTemp = null;
30
+ this._resizeClientY = 0;
31
+ this.__resize_editor = null;
32
+ this.__close_move = null;
33
+ this.__geckoActiveEvent = null;
34
+ this.__scrollparents = [];
35
+ this.__cacheStyleNodes = [];
36
+ this.__selectionSyncEvent = null;
37
+ // input plugins
38
+ this._inputFocus = false;
39
+ this.__inputPlugin = null;
40
+ this.__inputBlurEvent = null;
41
+ this.__inputKeyEvent = null;
42
+ // viewport
43
+ this._vitualKeyboardHeight = 0;
44
+ this.__focusTemp = this.carrierWrapper.querySelector('.__se__focus__temp__');
45
+ this.__retainTimer = null;
46
+ this.__eventDoc = null;
47
+ this.__secopy = null;
48
+ // this.__scrollID = '';
49
+ };
50
+
51
+ EventManager.prototype = {
52
+ /**
53
+ * @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 {Element|Array.<Element>} target Target element
56
+ * @param {string} type Event type
57
+ * @param {Function} listener Event handler
58
+ * @param {boolean|undefined} useCapture Event useCapture option
59
+ * @return {boolean}
60
+ */
61
+ addEvent(target, type, listener, useCapture) {
62
+ if (!target) return false;
63
+ if (!numbers.is(target.length) || target.nodeName || (!Array.isArray(target) && target.length < 1)) target = [target];
64
+ if (target.length === 0) return false;
65
+
66
+ const len = target.length;
67
+ for (let i = 0; i < len; i++) {
68
+ target[i].addEventListener(type, listener, useCapture);
69
+ this._events.push({
70
+ target: target[i],
71
+ type: type,
72
+ handler: listener,
73
+ useCapture: useCapture
74
+ });
75
+ }
76
+
77
+ return {
78
+ target: len > 1 ? target : target[0],
79
+ type: type,
80
+ listener,
81
+ handler: listener,
82
+ useCapture: useCapture
83
+ };
84
+ },
85
+
86
+ /**
87
+ * @description Remove event
88
+ * @param {object} params { target, type, listener, useCapture } = this.addEvent()
89
+ * @returns {null}
90
+ */
91
+ removeEvent(params) {
92
+ if (!params) return;
93
+
94
+ let target = params.target;
95
+ const type = params.type;
96
+ const listener = params.listener;
97
+ const useCapture = params.useCapture;
98
+
99
+ if (!target) return false;
100
+ if (!numbers.is(target.length) || target.nodeName || (!Array.isArray(target) && target.length < 1)) target = [target];
101
+ if (target.length === 0) return false;
102
+
103
+ for (let i = 0, len = target.length; i < len; i++) {
104
+ target[i].removeEventListener(type, listener, useCapture);
105
+ }
106
+
107
+ return null;
108
+ },
109
+
110
+ /**
111
+ * @description Add an event to document.
112
+ * When created as an Iframe, the same event is added to the document in the Iframe.
113
+ * @param {string} type Event type
114
+ * @param {Function} listener Event listener
115
+ * @param {boolean|undefined} useCapture Use event capture
116
+ * @return {type, listener, useCapture}
117
+ */
118
+ addGlobalEvent(type, listener, useCapture) {
119
+ if (this.editor.frameOptions.get('iframe')) {
120
+ this.editor.frameContext.get('_ww').addEventListener(type, listener, useCapture);
121
+ }
122
+ this._w.addEventListener(type, listener, useCapture);
123
+ return {
124
+ type: type,
125
+ listener: listener,
126
+ useCapture: useCapture
127
+ };
128
+ },
129
+
130
+ /**
131
+ * @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|object} type Event type
134
+ * @param {Function} listener Event listener
135
+ * @param {boolean|undefined} useCapture Use event capture
136
+ */
137
+ removeGlobalEvent(type, listener, useCapture) {
138
+ if (!type) return;
139
+
140
+ if (typeof type === 'object') {
141
+ listener = type.listener;
142
+ useCapture = type.useCapture;
143
+ type = type.type;
144
+ }
145
+ if (this.editor.frameOptions.get('iframe')) {
146
+ this.editor.frameContext.get('_ww').removeEventListener(type, listener, useCapture);
147
+ }
148
+ this._w.removeEventListener(type, listener, useCapture);
149
+ },
150
+
151
+ /**
152
+ * @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|null} selectionNode selectionNode
155
+ * @returns {Node|undefined} selectionNode
156
+ */
157
+ applyTagEffect(selectionNode) {
158
+ selectionNode = selectionNode || this.selection.getNode();
159
+ if (selectionNode === this.editor.effectNode) return;
160
+ this.editor.effectNode = selectionNode;
161
+
162
+ const marginDir = this.options.get('_rtl') ? 'marginRight' : 'marginLeft';
163
+ const plugins = this.plugins;
164
+ const commandTargets = this.editor.commandTargets;
165
+ const classOnCheck = this._onButtonsCheck;
166
+ const styleCommand = this.options.get('_styleCommandMap');
167
+ const commandMapNodes = [];
168
+ const currentNodes = [];
169
+
170
+ const styleTags = this.options.get('_textStyleTags');
171
+ const styleNodes = [];
172
+
173
+ const activeCommands = this.editor.activeCommands;
174
+ const cLen = activeCommands.length;
175
+ let nodeName = '';
176
+
177
+ if (this.component.is(selectionNode) && !this.component.__selectionSelected) {
178
+ const component = this.component.get(selectionNode);
179
+ this.component.select(component.target, component.pluginName, false);
180
+ return;
181
+ }
182
+
183
+ while (selectionNode.firstChild) {
184
+ selectionNode = selectionNode.firstChild;
185
+ }
186
+
187
+ const fc = this.editor.frameContext;
188
+ const notReadonly = !fc.get('isReadOnly');
189
+ for (let element = selectionNode; !domUtils.isWysiwygFrame(element); element = element.parentNode) {
190
+ if (!element) break;
191
+ if (element.nodeType !== 1 || domUtils.isBreak(element)) continue;
192
+ if (this._isNonFocusNode(element)) {
193
+ this.editor.blur();
194
+ return;
195
+ }
196
+
197
+ nodeName = element.nodeName.toLowerCase();
198
+ currentNodes.push(nodeName);
199
+ if (styleTags.includes(nodeName) && !this.format.isLine(nodeName)) styleNodes.push(element);
200
+
201
+ /* Active plugins */
202
+ if (notReadonly) {
203
+ for (let c = 0, name; c < cLen; c++) {
204
+ name = activeCommands[c];
205
+ if (
206
+ !commandMapNodes.includes(name) &&
207
+ commandTargets.get(name) &&
208
+ commandTargets.get(name).filter((e) => {
209
+ return plugins[name]?.active(element, e);
210
+ }).length > 0
211
+ ) {
212
+ commandMapNodes.push(name);
213
+ }
214
+ }
215
+ }
216
+
217
+ /** indent, outdent */
218
+ if (this.format.isLine(element)) {
219
+ /* Outdent */
220
+ if (!commandMapNodes.includes('outdent') && commandTargets.has('outdent') && (domUtils.isListCell(element) || (element.style[marginDir] && numbers.get(element.style[marginDir], 0) > 0))) {
221
+ if (
222
+ commandTargets.get('outdent').filter((e) => {
223
+ if (domUtils.isImportantDisabled(e)) return false;
224
+ e.removeAttribute('disabled');
225
+ return true;
226
+ }).length > 0
227
+ ) {
228
+ commandMapNodes.push('outdent');
229
+ }
230
+ }
231
+ /* Indent */
232
+ if (!commandMapNodes.includes('indent') && commandTargets.has('indent')) {
233
+ const indentDisable = domUtils.isListCell(element) && !element.previousElementSibling;
234
+ if (
235
+ commandTargets.get('indent').filter((e) => {
236
+ if (domUtils.isImportantDisabled(e)) return false;
237
+ if (indentDisable) {
238
+ e.setAttribute('disabled', true);
239
+ } else {
240
+ e.removeAttribute('disabled');
241
+ }
242
+ return true;
243
+ }).length > 0
244
+ ) {
245
+ commandMapNodes.push('indent');
246
+ }
247
+ }
248
+
249
+ continue;
250
+ }
251
+
252
+ /** default active buttons [strong, ins, em, del, sub, sup] */
253
+ if (classOnCheck.test(nodeName)) {
254
+ nodeName = styleCommand[nodeName] || nodeName;
255
+ commandMapNodes.push(nodeName);
256
+ domUtils.addClass(commandTargets.get(nodeName), 'active');
257
+ }
258
+ }
259
+
260
+ this._setKeyEffect(commandMapNodes);
261
+
262
+ // cache style nodes
263
+ this.__cacheStyleNodes = styleNodes.reverse();
264
+
265
+ /** save current nodes */
266
+ this.status.currentNodes = currentNodes.reverse();
267
+ this.status.currentNodesMap = commandMapNodes;
268
+
269
+ /** Displays the current node structure to statusbar */
270
+ if (this.editor.frameOptions.get('statusbar_showPathLabel') && fc.get('navigation')) {
271
+ fc.get('navigation').textContent = this.options.get('_rtl') ? this.status.currentNodes.reverse().join(' < ') : this.status.currentNodes.join(' > ');
272
+ }
273
+
274
+ return selectionNode;
275
+ },
276
+
277
+ /**
278
+ * @description Gives an active effect when the mouse down event is blocked. (Used when "env.isGecko" is true)
279
+ * @param {Element} target Target element
280
+ * @private
281
+ */
282
+ _injectActiveEvent(target) {
283
+ domUtils.addClass(target, '__se__active');
284
+ this.__geckoActiveEvent = this.addGlobalEvent('mouseup', () => {
285
+ domUtils.removeClass(target, '__se__active');
286
+ this.__geckoActiveEvent = this.removeGlobalEvent(this.__geckoActiveEvent);
287
+ });
288
+ },
289
+
290
+ /**
291
+ * @description remove class, display text.
292
+ * @param {Array} ignoredList Igonred button list
293
+ * @private
294
+ */
295
+ _setKeyEffect(ignoredList) {
296
+ const activeCommands = this.editor.activeCommands;
297
+ const commandTargets = this.editor.commandTargets;
298
+ const plugins = this.plugins;
299
+ for (let i = 0, len = activeCommands.length, k, c, p; i < len; i++) {
300
+ k = activeCommands[i];
301
+ if (ignoredList.includes(k) || !(c = commandTargets.get(k))) continue;
302
+
303
+ p = plugins[k];
304
+ for (let j = 0, jLen = c.length, e; j < jLen; j++) {
305
+ e = c[j];
306
+ if (!e || e.length === 0) continue;
307
+ if (p) {
308
+ p.active(null, e);
309
+ } else if (/^outdent$/i.test(k)) {
310
+ if (!domUtils.isImportantDisabled(e)) e.setAttribute('disabled', true);
311
+ } else if (/^indent$/i.test(k)) {
312
+ if (!domUtils.isImportantDisabled(e)) e.removeAttribute('disabled');
313
+ } else {
314
+ domUtils.removeClass(e, 'active');
315
+ }
316
+ }
317
+ }
318
+ },
319
+
320
+ _showToolbarBalloonDelay() {
321
+ if (this._balloonDelay) {
322
+ _w.clearTimeout(this._balloonDelay);
323
+ }
324
+
325
+ this._balloonDelay = _w.setTimeout(() => {
326
+ _w.clearTimeout(this._balloonDelay);
327
+ this._balloonDelay = null;
328
+ if (this.editor.isSubBalloon) this.subToolbar._showBalloon();
329
+ else this.toolbar._showBalloon();
330
+ }, 250);
331
+ },
332
+
333
+ _toggleToolbarBalloon() {
334
+ this.selection._init();
335
+ const range = this.selection.getRange();
336
+ const hasSubMode = this.options.has('_subMode');
337
+
338
+ if (this.menu._bindControllersOff || (!(hasSubMode ? this.editor.isSubBalloonAlways : this.editor.isBalloonAlways) && range.collapsed)) {
339
+ if (hasSubMode) this._hideToolbar_sub();
340
+ else this._hideToolbar();
341
+ } else {
342
+ if (hasSubMode) this.subToolbar._showBalloon(range);
343
+ else this.toolbar._showBalloon(range);
344
+ }
345
+ },
346
+
347
+ _hideToolbar() {
348
+ if (!this.editor._notHideToolbar && !this.editor.frameContext.get('isFullScreen')) {
349
+ this.toolbar.hide();
350
+ }
351
+ },
352
+
353
+ _hideToolbar_sub() {
354
+ if (this.subToolbar && !this.editor._notHideToolbar) {
355
+ this.subToolbar.hide();
356
+ }
357
+ },
358
+
359
+ _isNonFocusNode(node) {
360
+ return node.nodeType === 1 && node.getAttribute('data-se-non-focus') === 'true';
361
+ },
362
+
363
+ _isUneditableNode(range, isFront) {
364
+ const container = isFront ? range.startContainer : range.endContainer;
365
+ const offset = isFront ? range.startOffset : range.endOffset;
366
+ const siblingKey = isFront ? 'previousSibling' : 'nextSibling';
367
+ const isElement = container.nodeType === 1;
368
+ let siblingNode;
369
+
370
+ if (isElement) {
371
+ siblingNode = this._isUneditableNode_getSibling(container.childNodes[offset], siblingKey, container);
372
+ return siblingNode && siblingNode.nodeType === 1 && siblingNode.getAttribute('contenteditable') === 'false' ? siblingNode : null;
373
+ } else {
374
+ siblingNode = this._isUneditableNode_getSibling(container, siblingKey, container);
375
+ return domUtils.isEdgePoint(container, offset, isFront ? 'front' : 'end') && siblingNode && siblingNode.nodeType === 1 && siblingNode.getAttribute('contenteditable') === 'false' ? siblingNode : null;
376
+ }
377
+ },
378
+
379
+ _isUneditableNode_getSibling(selectNode, siblingKey, container) {
380
+ if (!selectNode) return null;
381
+ let siblingNode = selectNode[siblingKey];
382
+
383
+ if (!siblingNode) {
384
+ siblingNode = this.format.getLine(container);
385
+ siblingNode = siblingNode ? siblingNode[siblingKey] : null;
386
+ if (siblingNode && !this.component.is(siblingNode)) siblingNode = siblingKey === 'previousSibling' ? siblingNode.firstChild : siblingNode.lastChild;
387
+ else return null;
388
+ }
389
+
390
+ return siblingNode;
391
+ },
392
+
393
+ // FireFox - table delete, Chrome - image, video, audio
394
+ _hardDelete() {
395
+ const range = this.selection.getRange();
396
+ const sc = range.startContainer;
397
+ const ec = range.endContainer;
398
+
399
+ // table
400
+ const sCell = this.format.getBlock(sc);
401
+ const eCell = this.format.getBlock(ec);
402
+ const sIsCell = domUtils.isTableCell(sCell);
403
+ const eIsCell = domUtils.isTableCell(eCell);
404
+ const ancestor = range.commonAncestorContainer;
405
+ if (((sIsCell && !sCell.previousElementSibling && !sCell.parentElement.previousElementSibling) || (eIsCell && !eCell.nextElementSibling && !eCell.parentElement.nextElementSibling)) && sCell !== eCell) {
406
+ if (!sIsCell) {
407
+ domUtils.removeItem(domUtils.getParentElement(eCell, (current) => ancestor === current.parentNode));
408
+ } else if (!eIsCell) {
409
+ domUtils.removeItem(domUtils.getParentElement(sCell, (current) => ancestor === current.parentNode));
410
+ } else {
411
+ domUtils.removeItem(domUtils.getParentElement(sCell, (current) => ancestor === current.parentNode));
412
+ this.editor._nativeFocus();
413
+ return true;
414
+ }
415
+ }
416
+
417
+ // component
418
+ const sComp = sc.nodeType === 1 ? domUtils.getParentElement(sc, '.se-component') : null;
419
+ const eComp = ec.nodeType === 1 ? domUtils.getParentElement(ec, '.se-component') : null;
420
+ if (sComp) domUtils.removeItem(sComp);
421
+ if (eComp) domUtils.removeItem(eComp);
422
+
423
+ return false;
424
+ },
425
+
426
+ /**
427
+ * @description If there is no default format, add a line and move 'selection'.
428
+ * @param {string|null} formatName Format tag name (default: 'P')
429
+ * @private
430
+ */
431
+ _setDefaultLine(formatName) {
432
+ if (!this.options.get('__lineFormatFilter')) return null;
433
+ if (this.editor._fileManager.pluginRegExp.test(this.editor.currentControllerName)) return;
434
+
435
+ const range = this.selection.getRange();
436
+ const commonCon = range.commonAncestorContainer;
437
+ const startCon = range.startContainer;
438
+ const rangeEl = this.format.getBlock(commonCon, null);
439
+ let focusNode, offset, format;
440
+
441
+ if (rangeEl) {
442
+ format = domUtils.createElement(formatName || this.options.get('defaultLine'));
443
+ format.innerHTML = rangeEl.innerHTML;
444
+ if (format.childNodes.length === 0) format.innerHTML = unicode.zeroWidthSpace;
445
+
446
+ rangeEl.innerHTML = format.outerHTML;
447
+ format = rangeEl.firstChild;
448
+ focusNode = domUtils.getEdgeChildNodes(format, null).sc;
449
+
450
+ if (!focusNode) {
451
+ focusNode = domUtils.createTextNode(unicode.zeroWidthSpace);
452
+ format.insertBefore(focusNode, format.firstChild);
453
+ }
454
+
455
+ offset = focusNode.textContent.length;
456
+ this.selection.setRange(focusNode, offset, focusNode, offset);
457
+ return;
458
+ }
459
+
460
+ if (commonCon.nodeType === 3 && this.component.is(commonCon.parentElement)) {
461
+ const compInfo = this.component.get(commonCon.parentElement);
462
+ const container = compInfo.container;
463
+
464
+ if (commonCon.parentElement === container) {
465
+ const siblingEl = commonCon.nextElementSibling ? container : container.nextElementSibling;
466
+ const el = domUtils.createElement(this.options.get('defaultLine'), null, commonCon);
467
+ container.parentElement.insertBefore(el, siblingEl);
468
+ this.editor.focusEdge(el);
469
+ return;
470
+ }
471
+
472
+ this.component.select(compInfo.target, compInfo.pluginName, false);
473
+ return null;
474
+ } else if (commonCon.nodeType === 1 && commonCon.getAttribute('data-se-embed') === 'true') {
475
+ let el = commonCon.nextElementSibling;
476
+ if (!this.format.isLine(el)) el = this.format.addLine(commonCon, this.options.get('defaultLine'));
477
+ this.selection.setRange(el.firstChild, 0, el.firstChild, 0);
478
+ return;
479
+ }
480
+
481
+ if ((this.format.isBlock(startCon) || domUtils.isWysiwygFrame(startCon)) && (this.component.is(startCon.children[range.startOffset]) || this.component.is(startCon.children[range.startOffset - 1]))) return;
482
+ if (domUtils.getParentElement(commonCon, domUtils.isExcludeFormat)) return null;
483
+
484
+ if (this.format.isBlock(commonCon) && commonCon.childNodes.length <= 1) {
485
+ let br = null;
486
+ if (commonCon.childNodes.length === 1 && domUtils.isBreak(commonCon.firstChild)) {
487
+ br = commonCon.firstChild;
488
+ } else {
489
+ br = domUtils.createTextNode(unicode.zeroWidthSpace);
490
+ commonCon.appendChild(br);
491
+ }
492
+
493
+ this.selection.setRange(br, 1, br, 1);
494
+ return;
495
+ }
496
+
497
+ try {
498
+ if (commonCon.nodeType === 3) {
499
+ format = domUtils.createElement(formatName || this.options.get('defaultLine'));
500
+ commonCon.parentNode.insertBefore(format, commonCon);
501
+ format.appendChild(commonCon);
502
+ }
503
+
504
+ if (domUtils.isBreak(format.nextSibling)) domUtils.removeItem(format.nextSibling);
505
+ if (domUtils.isBreak(format.previousSibling)) domUtils.removeItem(format.previousSibling);
506
+ if (domUtils.isBreak(focusNode)) {
507
+ const zeroWidth = domUtils.createTextNode(unicode.zeroWidthSpace);
508
+ focusNode.parentNode.insertBefore(zeroWidth, focusNode);
509
+ focusNode = zeroWidth;
510
+ }
511
+ } catch (e) {
512
+ this.editor.execCommand('formatBlock', false, formatName || this.options.get('defaultLine'));
513
+ this.selection.removeRange();
514
+ this.selection._init();
515
+ }
516
+
517
+ if (format) {
518
+ if (domUtils.isBreak(format.nextSibling)) domUtils.removeItem(format.nextSibling);
519
+ if (domUtils.isBreak(format.previousSibling)) domUtils.removeItem(format.previousSibling);
520
+ if (domUtils.isBreak(focusNode)) {
521
+ const zeroWidth = domUtils.createTextNode(unicode.zeroWidthSpace);
522
+ focusNode.parentNode.insertBefore(zeroWidth, focusNode);
523
+ focusNode = zeroWidth;
524
+ }
525
+ }
526
+
527
+ this.editor.effectNode = null;
528
+ this.editor._nativeFocus();
529
+ },
530
+
531
+ _dataTransferAction(type, e, clipboardData, frameContext) {
532
+ try {
533
+ this._setClipboardData(type, e, clipboardData, frameContext);
534
+ e.preventDefault();
535
+ e.stopPropagation();
536
+ return false;
537
+ } catch (err) {
538
+ console.warn('[SUNEDITOR.paste.error]', err);
539
+ }
540
+ },
541
+
542
+ async _setClipboardData(type, e, clipboardData, frameContext) {
543
+ let plainText = clipboardData.getData('text/plain');
544
+ let cleanData = clipboardData.getData('text/html');
545
+ const onlyText = !cleanData;
546
+
547
+ // SE copy data
548
+ const SEData = this.__secopy === plainText;
549
+ // MS word, OneNode, Excel
550
+ const MSData = /class=["']*Mso(Normal|List)/i.test(cleanData) || /content=["']*Word.Document/i.test(cleanData) || /content=["']*OneNote.File/i.test(cleanData) || /content=["']*Excel.Sheet/i.test(cleanData);
551
+ // from
552
+ const from = SEData ? 'SE' : MSData ? 'MS' : '';
553
+
554
+ if (onlyText) {
555
+ cleanData = converter.htmlToEntity(plainText).replace(/\n/g, '<br>');
556
+ } else {
557
+ cleanData = cleanData.replace(/^<html>\r?\n?<body>\r?\n?\x3C!--StartFragment-->|\x3C!--EndFragment-->\r?\n?<\/body>\r?\n?<\/html>$/g, '');
558
+ if (MSData) {
559
+ cleanData = cleanData.replace(/\n/g, ' ');
560
+ plainText = plainText.replace(/\n/g, ' ');
561
+ }
562
+ }
563
+
564
+ if (!SEData) {
565
+ const autoLinkify = this.options.get('autoLinkify');
566
+ if (autoLinkify) {
567
+ const dom = new DOMParser().parseFromString(cleanData, 'text/html');
568
+ domUtils.getListChildNodes(dom.body, converter.textToAnchor);
569
+ cleanData = dom.body.innerHTML;
570
+ }
571
+ }
572
+
573
+ if (!onlyText) {
574
+ cleanData = this.html.clean(cleanData, false, null, null);
575
+ }
576
+
577
+ const maxCharCount = this.char.test(this.editor.frameOptions.get('charCounter_type') === 'byte-html' ? cleanData : plainText, false);
578
+ // user event - paste
579
+ if (type === 'paste') {
580
+ const value = await this.triggerEvent('onPaste', { frameContext, event: e, html: cleanData, maxCharCount, from });
581
+ if (value === false) {
582
+ return false;
583
+ } else if (typeof value === 'string') {
584
+ if (!value) return false;
585
+ cleanData = value;
586
+ }
587
+ }
588
+ // user event - drop
589
+ if (type === 'drop') {
590
+ const value = await this.triggerEvent('onDrop', { frameContext, event: e, html: cleanData, maxCharCount, from });
591
+ if (value === false) {
592
+ return false;
593
+ } else if (typeof value === 'string') {
594
+ if (!value) return false;
595
+ cleanData = value;
596
+ }
597
+ }
598
+
599
+ // files
600
+ const files = clipboardData.files;
601
+ if (files.length > 0 && !MSData) {
602
+ for (let i = 0, len = files.length; i < len; i++) {
603
+ this._callPluginEvent('onPastAndDrop', { frameContext, event: e, file: files[i] });
604
+ }
605
+
606
+ return false;
607
+ }
608
+
609
+ if (!maxCharCount) {
610
+ return false;
611
+ }
612
+
613
+ if (cleanData) {
614
+ this.html.insert(cleanData, false, true, true);
615
+ return false;
616
+ }
617
+ },
618
+
619
+ _addCommonEvents() {
620
+ const buttonsHandler = ButtonsHandler.bind(this);
621
+ const toolbarHandler = OnClick_toolbar.bind(this);
622
+
623
+ /** menu event */
624
+ this.addEvent(this.context.get('menuTray'), 'mousedown', buttonsHandler, false);
625
+ this.addEvent(this.context.get('menuTray'), 'click', OnClick_menuTray.bind(this), true);
626
+
627
+ /** toolbar event */
628
+ this.addEvent(this.context.get('toolbar.main'), 'mousedown', buttonsHandler, false);
629
+ this.addEvent(this.context.get('toolbar.main'), 'click', toolbarHandler, false);
630
+ // subToolbar
631
+ if (this.options.has('_subMode')) {
632
+ this.addEvent(this.context.get('toolbar.sub.main'), 'mousedown', buttonsHandler, false);
633
+ this.addEvent(this.context.get('toolbar.sub.main'), 'click', toolbarHandler, false);
634
+ }
635
+
636
+ /** set response toolbar */
637
+ this.toolbar._setResponsive();
638
+
639
+ /** observer */
640
+ if (env.isResizeObserverSupported) {
641
+ this._toolbarObserver = new ResizeObserver(() => {
642
+ _w.setTimeout(() => {
643
+ this.toolbar.resetResponsiveToolbar();
644
+ }, 0);
645
+ });
646
+ this._wwFrameObserver = new ResizeObserver((entries) => {
647
+ _w.setTimeout(() => {
648
+ entries.forEach((e) => {
649
+ this.editor.__callResizeFunction(this.editor.frameRoots.get(e.target.getAttribute('data-root-key')), -1, e);
650
+ });
651
+ }, 0);
652
+ });
653
+ }
654
+
655
+ /** window event */
656
+ this.addEvent(_w, 'resize', OnResize_window.bind(this), false);
657
+ this.addEvent(_w, 'scroll', OnScroll_window.bind(this), false);
658
+ if (env.isMobile) {
659
+ this.addEvent(_w.visualViewport, 'resize', OnResize_viewport.bind(this), false);
660
+ this.addEvent(_w.visualViewport, 'scroll', OnScroll_viewport.bind(this), false);
661
+ this.addEvent(_w.visualViewport, 'scroll', converter.debounce(OnScroll_viewport_onKeyboardOn.bind(this), 200), false);
662
+ }
663
+ },
664
+
665
+ _addFrameEvents(fc) {
666
+ const isIframe = fc.get('options').get('iframe');
667
+ const eventWysiwyg = isIframe ? fc.get('_ww') : fc.get('wysiwyg');
668
+ fc.set('eventWysiwyg', eventWysiwyg);
669
+ const codeArea = fc.get('code');
670
+ const dragCursor = this.editor.carrierWrapper.querySelector('.se-drag-cursor');
671
+
672
+ /** editor area */
673
+ const wwMouseMove = OnMouseMove_wysiwyg.bind(this, fc);
674
+ this.addEvent(eventWysiwyg, 'mousemove', wwMouseMove, false);
675
+ this.addEvent(eventWysiwyg, 'mouseleave', OnMouseLeave_wysiwyg.bind(this, fc), false);
676
+ this.addEvent(eventWysiwyg, 'mousedown', OnMouseDown_wysiwyg.bind(this, fc), false);
677
+ this.addEvent(eventWysiwyg, 'mouseup', OnMouseUp_wysiwyg.bind(this, fc), false);
678
+ this.addEvent(eventWysiwyg, 'click', OnClick_wysiwyg.bind(this, fc), false);
679
+ this.addEvent(eventWysiwyg, 'input', OnInput_wysiwyg.bind(this, fc), false);
680
+ this.addEvent(eventWysiwyg, 'keydown', OnKeyDown_wysiwyg.bind(this, fc), false);
681
+ this.addEvent(eventWysiwyg, 'keyup', OnKeyUp_wysiwyg.bind(this, fc), false);
682
+ this.addEvent(eventWysiwyg, 'paste', OnPaste_wysiwyg.bind(this, fc), false);
683
+ this.addEvent(eventWysiwyg, 'copy', OnCopy_wysiwyg.bind(this, fc), false);
684
+ this.addEvent(eventWysiwyg, 'cut', OnCut_wysiwyg.bind(this, fc), false);
685
+ this.addEvent(
686
+ eventWysiwyg,
687
+ 'dragover',
688
+ OnDragOver_wysiwyg.bind(this, fc, dragCursor, isIframe ? this.editor.frameContext.get('topArea') : null, !this.options.get('toolbar_container') && !this.editor.isBalloon && !this.editor.isInline),
689
+ false
690
+ );
691
+ this.addEvent(eventWysiwyg, 'dragend', OnDragEnd_wysiwyg.bind(this, dragCursor), false);
692
+ this.addEvent(eventWysiwyg, 'drop', OnDrop_wysiwyg.bind(this, fc, dragCursor), false);
693
+ this.addEvent(eventWysiwyg, 'scroll', OnScroll_wysiwyg.bind(this, fc, eventWysiwyg), { passive: true, useCapture: false });
694
+ this.addEvent(eventWysiwyg, 'focus', OnFocus_wysiwyg.bind(this, fc), false);
695
+ this.addEvent(eventWysiwyg, 'blur', OnBlur_wysiwyg.bind(this, fc), false);
696
+ this.addEvent(codeArea, 'mousedown', OnFocus_code.bind(this, fc), false);
697
+
698
+ /** drag handle */
699
+ const dragHandle = fc.get('wrapper').querySelector('.se-drag-handle');
700
+ this.addEvent(
701
+ dragHandle,
702
+ 'wheel',
703
+ (event) => {
704
+ event.preventDefault();
705
+ this.component.deselect();
706
+ },
707
+ false
708
+ );
709
+
710
+ /** line breaker */
711
+ const lineBreakEventName = isMobile ? 'touchstart' : 'mousedown';
712
+ this.addEvent(
713
+ [fc.get('lineBreaker_t'), fc.get('lineBreaker_b')],
714
+ lineBreakEventName,
715
+ (e) => {
716
+ e.preventDefault();
717
+ },
718
+ false
719
+ );
720
+ this.addEvent(fc.get('lineBreaker_t'), lineBreakEventName, DisplayLineBreak.bind(this, 't'), false);
721
+ this.addEvent(fc.get('lineBreaker_b'), lineBreakEventName, DisplayLineBreak.bind(this, 'b'), false);
722
+
723
+ /** Events are registered mobile. */
724
+ if (isMobile) {
725
+ this.addEvent(eventWysiwyg, 'touchstart', wwMouseMove, {
726
+ passive: true,
727
+ useCapture: false
728
+ });
729
+ }
730
+
731
+ /** code view area auto line */
732
+ if (!this.options.get('hasCodeMirror')) {
733
+ const codeNumbers = fc.get('codeNumbers');
734
+ const cvAuthHeight = this.viewer._codeViewAutoHeight.bind(this.viewer, fc.get('code'), codeNumbers, this.editor.frameOptions.get('height') === 'auto');
735
+
736
+ this.addEvent(codeArea, 'keydown', cvAuthHeight, false);
737
+ this.addEvent(codeArea, 'keyup', cvAuthHeight, false);
738
+ this.addEvent(codeArea, 'paste', cvAuthHeight, false);
739
+
740
+ /** code view numbers */
741
+ if (codeNumbers) this.addEvent(codeArea, 'scroll', this.viewer._scrollLineNumbers.bind(codeArea, codeNumbers), false);
742
+ }
743
+
744
+ if (fc.has('statusbar')) this.__addStatusbarEvent(fc, fc.get('options'));
745
+
746
+ const OnScrollAbs = OnScroll_Abs.bind(this);
747
+ let scrollParent = fc.get('originElement');
748
+ while ((scrollParent = domUtils.getScrollParent(scrollParent.parentElement))) {
749
+ this.__scrollparents.push(scrollParent);
750
+ this.addEvent(scrollParent, 'scroll', OnScrollAbs, false);
751
+ }
752
+
753
+ /** focus temp (mobile) */
754
+ this.addEvent(this.__focusTemp, 'focus', (e) => e.preventDefault(), false);
755
+
756
+ /** document event */
757
+ if (this.__eventDoc !== fc.get('_wd')) {
758
+ this.__eventDoc = fc.get('_wd');
759
+ this.addEvent(this.__eventDoc, 'selectionchange', OnSelectionchange_document.bind(this, this.__eventDoc), false);
760
+ }
761
+ },
762
+
763
+ __addStatusbarEvent(fc, fo) {
764
+ if (/\d+/.test(fo.get('height')) && fo.get('statusbar_resizeEnable')) {
765
+ fo.set('__statusbarEvent', this.addEvent(fc.get('statusbar'), 'mousedown', OnMouseDown_statusbar.bind(this), false));
766
+ } else {
767
+ domUtils.addClass(fc.get('statusbar'), 'se-resizing-none');
768
+ }
769
+ },
770
+
771
+ _removeAllEvents() {
772
+ for (let i = 0, len = this._events.length, e; i < len; i++) {
773
+ e = this._events[i];
774
+ e.target.removeEventListener(e.type, e.handler, e.useCapture);
775
+ }
776
+
777
+ this._events = [];
778
+
779
+ if (this._wwFrameObserver) {
780
+ this._wwFrameObserver.disconnect();
781
+ this._wwFrameObserver = null;
782
+ }
783
+
784
+ if (this._toolbarObserver) {
785
+ this._toolbarObserver.disconnect();
786
+ this._toolbarObserver = null;
787
+ }
788
+ },
789
+
790
+ _moveContainer(eventWysiwyg) {
791
+ const y = eventWysiwyg.scrollY || eventWysiwyg.scrollTop || 0;
792
+ const x = eventWysiwyg.scrollX || eventWysiwyg.scrollLeft || 0;
793
+
794
+ if (this.editor.isBalloon) {
795
+ this.context.get('toolbar.main').style.top = this.toolbar._balloonOffset.top - y + 'px';
796
+ this.context.get('toolbar.main').style.left = this.toolbar._balloonOffset.left - x + 'px';
797
+ } else if (this.editor.isSubBalloon) {
798
+ this.context.get('toolbar.sub.main').style.top = this.subToolbar._balloonOffset.top - y + 'px';
799
+ this.context.get('toolbar.sub.main').style.left = this.subToolbar._balloonOffset.left - x + 'px';
800
+ }
801
+
802
+ if (this.editor._controllerTargetContext !== this.editor.frameContext.get('topArea')) {
803
+ this.editor._offCurrentController();
804
+ }
805
+
806
+ if (this.editor._lineBreaker_t) {
807
+ const t_style = this.editor._lineBreaker_t.style;
808
+ if (t_style.display !== 'none') {
809
+ const t_offset = (this.editor._lineBreaker_t.getAttribute('data-offset') || ',').split(',');
810
+ t_style.top = numbers.get(t_style.top, 0) - (y - numbers.get(t_offset[0], 0)) + 'px';
811
+ t_style.left = numbers.get(t_style.left, 0) - (x - numbers.get(t_offset[1], 0)) + 'px';
812
+ this.editor._lineBreaker_t.setAttribute('data-offset', y + ',' + x);
813
+ }
814
+ }
815
+
816
+ if (this.editor._lineBreaker_b) {
817
+ const b_style = this.editor._lineBreaker_b.style;
818
+ if (b_style.display !== 'none') {
819
+ const b_offset = (this.editor._lineBreaker_b.getAttribute('data-offset') || ',').split(',');
820
+ b_style.top = numbers.get(b_style.top, 0) - (y - numbers.get(b_offset[0], 0)) + 'px';
821
+ b_style[b_offset[1]] = numbers.get(b_style[b_offset[1]], 0) - (x - numbers.get(b_offset[2], 0)) + 'px';
822
+ this.editor._lineBreaker_b.setAttribute('data-offset', y + ',' + b_offset[1] + ',' + x);
823
+ }
824
+ }
825
+
826
+ const openCont = this.editor.opendControllers;
827
+ for (let i = 0; i < openCont.length; i++) {
828
+ if (!openCont[i].notInCarrier) continue;
829
+ openCont[i].form.style.top = openCont[i].inst.__offset.top - y + 'px';
830
+ openCont[i].form.style.left = openCont[i].inst.__offset.left - x + 'px';
831
+ }
832
+ },
833
+
834
+ _scrollContainer() {
835
+ const openCont = this.editor.opendControllers;
836
+ if (!openCont.length) return;
837
+
838
+ this.__rePositionController(openCont);
839
+ },
840
+
841
+ __rePositionController(cont) {
842
+ if (_DragHandle.get('__dragMove')) _DragHandle.get('__dragMove')();
843
+ for (let i = 0; i < cont.length; i++) {
844
+ if (cont[i].notInCarrier) continue;
845
+ cont[i].inst?.show();
846
+ }
847
+ },
848
+
849
+ _resetFrameStatus() {
850
+ if (!env.isResizeObserverSupported) {
851
+ this.toolbar.resetResponsiveToolbar();
852
+ if (this.options.get('_subMode')) this.subToolbar.resetResponsiveToolbar();
853
+ }
854
+
855
+ const toolbar = this.context.get('toolbar.main');
856
+ const isToolbarHidden = toolbar.style.display === 'none' || (this.editor.isInline && !this.toolbar._inlineToolbarAttr.isShow);
857
+ if (toolbar.offsetWidth === 0 && !isToolbarHidden) return;
858
+
859
+ const fc = this.editor.frameContext;
860
+ const fileBrowser = fc.get('fileBrowser');
861
+ if (fileBrowser && fileBrowser.area.style.display === 'block') {
862
+ fileBrowser.body.style.maxHeight = domUtils.getClientSize().h - fileBrowser.header.offsetHeight - 50 + 'px';
863
+ }
864
+
865
+ if (this.menu.currentDropdownActiveButton && this.menu.currentDropdown) {
866
+ this.menu._setMenuPosition(this.menu.currentDropdownActiveButton, this.menu.currentDropdown);
867
+ }
868
+
869
+ if (this.viewer._resetFullScreenHeight()) return;
870
+
871
+ if (fc.get('isCodeView') && this.editor.isInline) {
872
+ this.toolbar._showInline();
873
+ return;
874
+ }
875
+
876
+ this.editor._iframeAutoHeight(fc);
877
+
878
+ if (this.toolbar._sticky) {
879
+ this.context.get('toolbar.main').style.width = fc.get('topArea').offsetWidth - 2 + 'px';
880
+ this.toolbar._resetSticky();
881
+ }
882
+ },
883
+
884
+ _setSelectionSync() {
885
+ this.removeGlobalEvent(this.__selectionSyncEvent);
886
+ this.__selectionSyncEvent = this.addGlobalEvent('mouseup', () => {
887
+ this.selection._init();
888
+ this.removeGlobalEvent(this.__selectionSyncEvent);
889
+ });
890
+ },
891
+
892
+ _retainStyleNodes(formatEl, _styleNodes) {
893
+ const el = _styleNodes[0].cloneNode(false);
894
+ let n = el;
895
+ for (let i = 1, len = _styleNodes.length, t; i < len; i++) {
896
+ t = _styleNodes[i].cloneNode(false);
897
+ n.appendChild(t);
898
+ n = t;
899
+ }
900
+
901
+ const { parent, inner } = this.nodeTransform.createNestedNode(_styleNodes, null);
902
+ const zeroWidth = domUtils.createTextNode(unicode.zeroWidthSpace);
903
+ inner.appendChild(zeroWidth);
904
+
905
+ formatEl.innerHTML = '';
906
+ formatEl.appendChild(parent);
907
+
908
+ this.selection.setRange(zeroWidth, 1, zeroWidth, 1);
909
+ },
910
+
911
+ _clearRetainStyleNodes(formatEl) {
912
+ formatEl.innerHTML = '<br>';
913
+ this.selection.setRange(formatEl, 0, formatEl, 0);
914
+ },
915
+
916
+ _callPluginEvent(name, e) {
917
+ const eventPlugins = this.editor._onPluginEvents.get(name);
918
+ for (let i = 0; i < eventPlugins.length; i++) {
919
+ if (eventPlugins[i](e) === false) return false;
920
+ }
921
+ },
922
+
923
+ _overComponentSelect(target) {
924
+ const figure = domUtils.getParentElement(target, domUtils.isFigure);
925
+ let info = this.component.get(target);
926
+ if (info || figure) {
927
+ if (!info) info = this.component.get(figure);
928
+ if (info && !domUtils.hasClass(info.container, 'se-component-selected')) {
929
+ this.editor._offCurrentController();
930
+ _DragHandle.set('__overInfo', ON_OVER_COMPONENT);
931
+ this.component.select(info.target, info.pluginName, false);
932
+ }
933
+ } else if (_DragHandle.get('__overInfo') !== null && !domUtils.hasClass(target, 'se-drag-handle')) {
934
+ this.component.__deselect();
935
+ _DragHandle.set('__overInfo', null);
936
+ }
937
+ },
938
+
939
+ __removeInput() {
940
+ this._inputFocus = this.editor._antiBlur = false;
941
+ this.__inputBlurEvent = this.removeEvent(this.__inputBlurEvent);
942
+ this.__inputKeyEvent = this.removeEvent(this.__inputKeyEvent);
943
+ this.__inputPlugin = null;
944
+ },
945
+
946
+ __enterPrevent(e) {
947
+ e.preventDefault();
948
+ if (!isMobile) return;
949
+
950
+ this.__focusTemp.focus();
951
+ },
952
+
953
+ constructor: EventManager
954
+ };
955
+
956
+ function OnScroll_wysiwyg(frameContext, eventWysiwyg, e) {
957
+ this._moveContainer(eventWysiwyg);
958
+ this._scrollContainer();
959
+
960
+ // plugin event
961
+ this._callPluginEvent('onScroll', { frameContext, event: e });
962
+
963
+ // user event
964
+ this.triggerEvent('onScroll', { frameContext, event: e });
965
+ }
966
+
967
+ function OnFocus_wysiwyg(frameContext, e) {
968
+ const rootKey = frameContext.get('key');
969
+
970
+ if (this._inputFocus) {
971
+ if (this.editor.isInline) {
972
+ this._w.setTimeout(() => {
973
+ this.toolbar._showInline();
974
+ }, 0);
975
+ }
976
+ return;
977
+ }
978
+
979
+ if (this.status.rootKey === rootKey && this.editor._antiBlur) return;
980
+
981
+ const componentSelected = this.editor.status.componentSelected;
982
+ this.editor._offCurrentController();
983
+ this.status.hasFocus = true;
984
+
985
+ domUtils.removeClass(this.editor.commandTargets.get('codeView'), 'active');
986
+ domUtils.setDisabled(this.editor._codeViewDisabledButtons, false);
987
+
988
+ this.editor.changeFrameContext(rootKey);
989
+ this.history.resetButtons(rootKey, null);
990
+
991
+ if (!componentSelected) {
992
+ this.selection.removeRange();
993
+ this.applyTagEffect();
994
+ }
995
+
996
+ this._w.setTimeout(() => {
997
+ if (this.editor.isInline) this.toolbar._showInline();
998
+
999
+ // user event
1000
+ this.triggerEvent('onFocus', { frameContext, event: e });
1001
+ // plugin event
1002
+ this._callPluginEvent('onFocus', { frameContext, event: e });
1003
+ }, 0);
1004
+ }
1005
+
1006
+ function OnBlur_wysiwyg(frameContext, e) {
1007
+ if (this._inputFocus || this.editor._antiBlur || frameContext.get('isCodeView')) return;
1008
+
1009
+ this.status.hasFocus = false;
1010
+ this.editor.effectNode = null;
1011
+ this.editor._offCurrentController();
1012
+ if (this.editor.isInline || this.editor.isBalloon) this._hideToolbar();
1013
+ if (this.editor.isSubBalloon) this._hideToolbar_sub();
1014
+
1015
+ this._setKeyEffect([]);
1016
+
1017
+ this.status.currentNodes = [];
1018
+ this.status.currentNodesMap = [];
1019
+
1020
+ this.editor.applyFrameRoots((root) => {
1021
+ if (root.get('navigation')) root.get('navigation').textContent = '';
1022
+ });
1023
+
1024
+ this.history.check(frameContext.get('key'), this.status._range);
1025
+
1026
+ // user event
1027
+ this.triggerEvent('onBlur', { frameContext, event: e });
1028
+ // plugin event
1029
+ this._callPluginEvent('onBlur', { frameContext, event: e });
1030
+ }
1031
+
1032
+ function OnMouseDown_statusbar(e) {
1033
+ e.stopPropagation();
1034
+ this._resizeClientY = e.clientY;
1035
+ this.editor.enableBackWrapper('ns-resize');
1036
+ this.__resize_editor = this.addGlobalEvent('mousemove', __resizeEditor.bind(this));
1037
+ this.__close_move = this.addGlobalEvent('mouseup', __closeMove.bind(this));
1038
+ }
1039
+
1040
+ function __resizeEditor(e) {
1041
+ const fc = this.editor.frameContext;
1042
+ const resizeInterval = fc.get('wrapper').offsetHeight + (e.clientY - this._resizeClientY);
1043
+ const h = resizeInterval < fc.get('_minHeight') ? fc.get('_minHeight') : resizeInterval;
1044
+ fc.get('wysiwygFrame').style.height = fc.get('code').style.height = h + 'px';
1045
+ this._resizeClientY = e.clientY;
1046
+ if (!env.isResizeObserverSupported) this.editor.__callResizeFunction(h, null);
1047
+ }
1048
+
1049
+ function __closeMove() {
1050
+ this.editor.disableBackWrapper();
1051
+ if (this.__resize_editor) this.__resize_editor = this.removeGlobalEvent(this.__resize_editor);
1052
+ if (this.__close_move) this.__close_move = this.removeGlobalEvent(this.__close_move);
1053
+ }
1054
+
1055
+ function DisplayLineBreak(dir, e) {
1056
+ e.preventDefault();
1057
+
1058
+ const component = this._lineBreakComp;
1059
+ if (!component) return;
1060
+
1061
+ dir = !dir ? this._lineBreakDir : dir;
1062
+ const isList = domUtils.isListCell(component.parentNode);
1063
+ const format = domUtils.createElement(isList ? 'BR' : domUtils.isTableCell(component.parentNode) ? 'DIV' : this.options.get('defaultLine'));
1064
+ if (!isList) format.innerHTML = '<br>';
1065
+
1066
+ if (this.editor.frameOptions.get('charCounter_type') === 'byte-html' && !this.char.check(format.outerHTML)) return;
1067
+
1068
+ component.parentNode.insertBefore(format, dir === 't' ? component : component.nextSibling);
1069
+ this.component.deselect();
1070
+
1071
+ try {
1072
+ this.editor._antiBlur = true;
1073
+ const focusEl = isList ? format : format.firstChild;
1074
+ this.selection.setRange(focusEl, 1, focusEl, 1);
1075
+ this.history.push(false);
1076
+ } finally {
1077
+ this.editor._antiBlur = false;
1078
+ }
1079
+ }
1080
+
1081
+ function OnResize_window() {
1082
+ if (isMobile) {
1083
+ this._scrollContainer();
1084
+ } else {
1085
+ this.editor._offCurrentController();
1086
+ }
1087
+
1088
+ if (this.editor.isBalloon) this.toolbar.hide();
1089
+ else if (this.editor.isSubBalloon) this.subToolbar.hide();
1090
+
1091
+ this._resetFrameStatus();
1092
+ }
1093
+
1094
+ function OnScroll_window() {
1095
+ if (this.options.get('toolbar_sticky') > -1) {
1096
+ if (this._vitualKeyboardHeight && this.toolbar._sticky) {
1097
+ this.toolbar._visible(false);
1098
+ } else {
1099
+ this.toolbar._resetSticky();
1100
+ }
1101
+ }
1102
+
1103
+ if (this.editor.isBalloon && this.context.get('toolbar.main').style.display === 'block') {
1104
+ this.toolbar._setBalloonOffset(this.toolbar._balloonOffset.position === 'top');
1105
+ } else if (this.editor.isSubBalloon && this.context.get('toolbar.sub.main').style.display === 'block') {
1106
+ this.subToolbar._setBalloonOffset(this.subToolbar._balloonOffset.position === 'top');
1107
+ }
1108
+
1109
+ this._scrollContainer();
1110
+ }
1111
+
1112
+ function OnResize_viewport() {
1113
+ this._vitualKeyboardHeight = _w.innerHeight - _w.visualViewport.height;
1114
+ }
1115
+
1116
+ function OnScroll_viewport() {
1117
+ if (this.options.get('toolbar_sticky') > -1) {
1118
+ if (this._vitualKeyboardHeight && this.toolbar._sticky) {
1119
+ this.toolbar._visible(false);
1120
+ } else {
1121
+ this.toolbar._resetSticky();
1122
+ }
1123
+ }
1124
+ }
1125
+
1126
+ function OnScroll_viewport_onKeyboardOn() {
1127
+ this.toolbar._visible(true);
1128
+ if (this._vitualKeyboardHeight && this.options.get('toolbar_sticky') > -1) {
1129
+ this.toolbar._resetSticky();
1130
+ }
1131
+ }
1132
+
1133
+ function OnSelectionchange_document(_wd) {
1134
+ const selection = _wd.getSelection();
1135
+ let anchorNode = selection.anchorNode;
1136
+
1137
+ this.editor.applyFrameRoots((root) => {
1138
+ if (anchorNode && root.get('wysiwyg').contains(anchorNode)) {
1139
+ anchorNode = null;
1140
+ this.selection._init();
1141
+ this.applyTagEffect();
1142
+ }
1143
+ });
1144
+ }
1145
+
1146
+ function OnScroll_Abs() {
1147
+ this._scrollContainer();
1148
+ }
1149
+
1150
+ function OnFocus_code(frameContext) {
1151
+ this.editor.changeFrameContext(frameContext.get('key'));
1152
+ domUtils.addClass(this.editor.commandTargets.get('codeView'), 'active');
1153
+ domUtils.setDisabled(this.editor._codeViewDisabledButtons, true);
1154
+ }
1155
+
1156
+ export default EventManager;