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