suneditor 3.0.0-alpha.2 → 3.0.0-alpha.20

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 (306) hide show
  1. package/.eslintrc.json +4 -3
  2. package/CONTRIBUTING.md +4 -2
  3. package/README.md +19 -11
  4. package/README_V3_TEMP.md +705 -0
  5. package/dist/suneditor.min.css +1 -0
  6. package/dist/suneditor.min.js +1 -0
  7. package/example.md +587 -0
  8. package/package.json +15 -9
  9. package/src/assets/icons/_default.js +166 -131
  10. package/src/assets/{suneditor-content.css → suneditor-contents.css} +182 -45
  11. package/src/assets/suneditor.css +1195 -556
  12. package/src/assets/variables.css +138 -0
  13. package/src/core/base/eventHandlers/handler_toolbar.js +35 -14
  14. package/src/core/base/eventHandlers/handler_ww_clipboard.js +29 -4
  15. package/src/core/base/eventHandlers/handler_ww_dragDrop.js +59 -15
  16. package/src/core/base/eventHandlers/handler_ww_key_input.js +426 -212
  17. package/src/core/base/eventHandlers/handler_ww_mouse.js +108 -32
  18. package/src/core/base/eventManager.js +540 -209
  19. package/src/core/base/events.js +616 -320
  20. package/src/core/base/history.js +93 -39
  21. package/src/core/class/char.js +29 -13
  22. package/src/core/class/component.js +332 -145
  23. package/src/core/class/format.js +671 -509
  24. package/src/core/class/html.js +504 -290
  25. package/src/core/class/menu.js +114 -47
  26. package/src/core/class/nodeTransform.js +111 -66
  27. package/src/core/class/offset.js +409 -105
  28. package/src/core/class/selection.js +220 -108
  29. package/src/core/class/shortcuts.js +68 -8
  30. package/src/core/class/toolbar.js +106 -116
  31. package/src/core/class/ui.js +330 -0
  32. package/src/core/class/viewer.js +178 -74
  33. package/src/core/editor.js +489 -384
  34. package/src/core/section/actives.js +118 -22
  35. package/src/core/section/constructor.js +504 -170
  36. package/src/core/section/context.js +28 -23
  37. package/src/core/section/documentType.js +561 -0
  38. package/src/editorInjector/_classes.js +19 -5
  39. package/src/editorInjector/_core.js +71 -7
  40. package/src/editorInjector/index.js +63 -1
  41. package/src/helper/converter.js +137 -19
  42. package/src/helper/dom/domCheck.js +294 -0
  43. package/src/helper/dom/domQuery.js +609 -0
  44. package/src/helper/dom/domUtils.js +533 -0
  45. package/src/helper/dom/index.js +12 -0
  46. package/src/helper/env.js +42 -19
  47. package/src/helper/index.js +7 -4
  48. package/src/helper/keyCodeMap.js +183 -0
  49. package/src/helper/numbers.js +8 -8
  50. package/src/helper/unicode.js +5 -5
  51. package/src/langs/ckb.js +69 -3
  52. package/src/langs/cs.js +67 -1
  53. package/src/langs/da.js +68 -2
  54. package/src/langs/de.js +68 -3
  55. package/src/langs/en.js +29 -1
  56. package/src/langs/es.js +68 -3
  57. package/src/langs/fa.js +70 -2
  58. package/src/langs/fr.js +68 -2
  59. package/src/langs/he.js +68 -3
  60. package/src/langs/hu.js +226 -0
  61. package/src/langs/index.js +3 -2
  62. package/src/langs/it.js +65 -0
  63. package/src/langs/ja.js +68 -3
  64. package/src/langs/ko.js +66 -1
  65. package/src/langs/lv.js +68 -3
  66. package/src/langs/nl.js +68 -3
  67. package/src/langs/pl.js +68 -3
  68. package/src/langs/pt_br.js +65 -0
  69. package/src/langs/ro.js +69 -4
  70. package/src/langs/ru.js +68 -3
  71. package/src/langs/se.js +68 -3
  72. package/src/langs/tr.js +68 -0
  73. package/src/langs/ua.js +68 -3
  74. package/src/langs/ur.js +71 -6
  75. package/src/langs/zh_cn.js +69 -4
  76. package/src/modules/ApiManager.js +77 -54
  77. package/src/modules/Browser.js +667 -0
  78. package/src/modules/ColorPicker.js +162 -102
  79. package/src/modules/Controller.js +233 -136
  80. package/src/modules/Figure.js +913 -489
  81. package/src/modules/FileManager.js +141 -72
  82. package/src/modules/HueSlider.js +113 -61
  83. package/src/modules/Modal.js +292 -113
  84. package/src/modules/ModalAnchorEditor.js +380 -230
  85. package/src/modules/SelectMenu.js +270 -168
  86. package/src/modules/_DragHandle.js +2 -1
  87. package/src/modules/index.js +3 -3
  88. package/src/plugins/browser/audioGallery.js +83 -0
  89. package/src/plugins/browser/fileBrowser.js +103 -0
  90. package/src/plugins/browser/fileGallery.js +83 -0
  91. package/src/plugins/browser/imageGallery.js +81 -0
  92. package/src/plugins/browser/videoGallery.js +103 -0
  93. package/src/plugins/command/blockquote.js +40 -27
  94. package/src/plugins/command/exportPDF.js +134 -0
  95. package/src/plugins/command/fileUpload.js +226 -158
  96. package/src/plugins/command/list_bulleted.js +93 -47
  97. package/src/plugins/command/list_numbered.js +93 -47
  98. package/src/plugins/dropdown/align.js +66 -54
  99. package/src/plugins/dropdown/backgroundColor.js +76 -45
  100. package/src/plugins/dropdown/font.js +71 -47
  101. package/src/plugins/dropdown/fontColor.js +78 -46
  102. package/src/plugins/dropdown/formatBlock.js +74 -33
  103. package/src/plugins/dropdown/hr.js +102 -51
  104. package/src/plugins/dropdown/layout.js +37 -26
  105. package/src/plugins/dropdown/lineHeight.js +54 -38
  106. package/src/plugins/dropdown/list.js +60 -45
  107. package/src/plugins/dropdown/paragraphStyle.js +51 -30
  108. package/src/plugins/dropdown/table.js +1269 -777
  109. package/src/plugins/dropdown/template.js +38 -26
  110. package/src/plugins/dropdown/textStyle.js +43 -31
  111. package/src/plugins/field/mention.js +144 -82
  112. package/src/plugins/index.js +32 -6
  113. package/src/plugins/input/fontSize.js +161 -108
  114. package/src/plugins/input/pageNavigator.js +70 -0
  115. package/src/plugins/modal/audio.js +341 -169
  116. package/src/plugins/modal/drawing.js +530 -0
  117. package/src/plugins/modal/embed.js +886 -0
  118. package/src/plugins/modal/image.js +673 -358
  119. package/src/plugins/modal/link.js +100 -71
  120. package/src/plugins/modal/math.js +384 -168
  121. package/src/plugins/modal/video.js +693 -336
  122. package/src/plugins/popup/anchor.js +222 -0
  123. package/src/suneditor.js +54 -12
  124. package/src/themes/dark.css +85 -0
  125. package/src/typedef.js +86 -0
  126. package/types/assets/icons/_default.d.ts +152 -0
  127. package/types/core/base/eventHandlers/handler_toolbar.d.ts +41 -0
  128. package/types/core/base/eventHandlers/handler_ww_clipboard.d.ts +40 -0
  129. package/types/core/base/eventHandlers/handler_ww_dragDrop.d.ts +35 -0
  130. package/types/core/base/eventHandlers/handler_ww_key_input.d.ts +45 -0
  131. package/types/core/base/eventHandlers/handler_ww_mouse.d.ts +39 -0
  132. package/types/core/base/eventManager.d.ts +377 -0
  133. package/types/core/base/events.d.ts +297 -0
  134. package/types/core/base/history.d.ts +81 -0
  135. package/types/core/class/char.d.ts +60 -0
  136. package/types/core/class/component.d.ts +259 -0
  137. package/types/core/class/format.d.ts +615 -0
  138. package/types/core/class/html.d.ts +377 -0
  139. package/types/core/class/menu.d.ts +118 -0
  140. package/types/core/class/nodeTransform.d.ts +93 -0
  141. package/types/core/class/offset.d.ts +512 -0
  142. package/types/core/class/selection.d.ts +188 -0
  143. package/types/core/class/shortcuts.d.ts +142 -0
  144. package/types/core/class/toolbar.d.ts +189 -0
  145. package/types/core/class/ui.d.ts +144 -0
  146. package/types/core/class/viewer.d.ts +140 -0
  147. package/types/core/editor.d.ts +606 -0
  148. package/types/core/section/actives.d.ts +46 -0
  149. package/types/core/section/constructor.d.ts +748 -0
  150. package/types/core/section/context.d.ts +45 -0
  151. package/types/core/section/documentType.d.ts +178 -0
  152. package/types/editorInjector/_classes.d.ts +41 -0
  153. package/types/editorInjector/_core.d.ts +92 -0
  154. package/types/editorInjector/index.d.ts +71 -0
  155. package/types/helper/converter.d.ts +150 -0
  156. package/types/helper/dom/domCheck.d.ts +182 -0
  157. package/types/helper/dom/domQuery.d.ts +214 -0
  158. package/types/helper/dom/domUtils.d.ts +211 -0
  159. package/types/helper/dom/index.d.ts +9 -0
  160. package/types/helper/env.d.ts +149 -0
  161. package/types/helper/index.d.ts +163 -0
  162. package/types/helper/keyCodeMap.d.ts +110 -0
  163. package/types/helper/numbers.d.ts +43 -0
  164. package/types/helper/unicode.d.ts +28 -0
  165. package/types/index.d.ts +0 -0
  166. package/{typings/Lang.d.ts → types/langs/_Lang.d.ts} +170 -103
  167. package/types/langs/ckb.d.ts +384 -0
  168. package/types/langs/cs.d.ts +384 -0
  169. package/types/langs/da.d.ts +384 -0
  170. package/types/langs/de.d.ts +384 -0
  171. package/types/langs/en.d.ts +384 -0
  172. package/types/langs/es.d.ts +384 -0
  173. package/types/langs/fa.d.ts +384 -0
  174. package/types/langs/fr.d.ts +384 -0
  175. package/types/langs/he.d.ts +384 -0
  176. package/types/langs/hu.d.ts +384 -0
  177. package/types/langs/index.d.ts +48 -0
  178. package/types/langs/it.d.ts +384 -0
  179. package/types/langs/ja.d.ts +384 -0
  180. package/types/langs/ko.d.ts +384 -0
  181. package/types/langs/lv.d.ts +384 -0
  182. package/types/langs/nl.d.ts +384 -0
  183. package/types/langs/pl.d.ts +384 -0
  184. package/types/langs/pt_br.d.ts +384 -0
  185. package/types/langs/ro.d.ts +384 -0
  186. package/types/langs/ru.d.ts +384 -0
  187. package/types/langs/se.d.ts +384 -0
  188. package/types/langs/tr.d.ts +384 -0
  189. package/types/langs/ua.d.ts +384 -0
  190. package/types/langs/ur.d.ts +384 -0
  191. package/types/langs/zh_cn.d.ts +384 -0
  192. package/types/modules/ApiManager.d.ts +125 -0
  193. package/types/modules/Browser.d.ts +326 -0
  194. package/types/modules/ColorPicker.d.ts +131 -0
  195. package/types/modules/Controller.d.ts +231 -0
  196. package/types/modules/Figure.d.ts +504 -0
  197. package/types/modules/FileManager.d.ts +202 -0
  198. package/types/modules/HueSlider.d.ts +136 -0
  199. package/types/modules/Modal.d.ts +117 -0
  200. package/types/modules/ModalAnchorEditor.d.ts +236 -0
  201. package/types/modules/SelectMenu.d.ts +194 -0
  202. package/types/modules/_DragHandle.d.ts +7 -0
  203. package/types/modules/index.d.ts +26 -0
  204. package/types/plugins/browser/audioGallery.d.ts +55 -0
  205. package/types/plugins/browser/fileBrowser.d.ts +64 -0
  206. package/types/plugins/browser/fileGallery.d.ts +55 -0
  207. package/types/plugins/browser/imageGallery.d.ts +51 -0
  208. package/types/plugins/browser/videoGallery.d.ts +57 -0
  209. package/types/plugins/command/blockquote.d.ts +28 -0
  210. package/types/plugins/command/exportPDF.d.ts +46 -0
  211. package/types/plugins/command/fileUpload.d.ts +156 -0
  212. package/types/plugins/command/list_bulleted.d.ts +56 -0
  213. package/types/plugins/command/list_numbered.d.ts +56 -0
  214. package/types/plugins/dropdown/align.d.ts +60 -0
  215. package/types/plugins/dropdown/backgroundColor.d.ts +63 -0
  216. package/types/plugins/dropdown/font.d.ts +54 -0
  217. package/types/plugins/dropdown/fontColor.d.ts +63 -0
  218. package/types/plugins/dropdown/formatBlock.d.ts +58 -0
  219. package/types/plugins/dropdown/hr.d.ts +81 -0
  220. package/types/plugins/dropdown/layout.d.ts +40 -0
  221. package/types/plugins/dropdown/lineHeight.d.ts +50 -0
  222. package/types/plugins/dropdown/list.d.ts +39 -0
  223. package/types/plugins/dropdown/paragraphStyle.d.ts +54 -0
  224. package/types/plugins/dropdown/table.d.ts +579 -0
  225. package/types/plugins/dropdown/template.d.ts +40 -0
  226. package/types/plugins/dropdown/textStyle.d.ts +41 -0
  227. package/types/plugins/field/mention.d.ts +102 -0
  228. package/types/plugins/index.d.ts +107 -0
  229. package/types/plugins/input/fontSize.d.ts +170 -0
  230. package/types/plugins/input/pageNavigator.d.ts +28 -0
  231. package/types/plugins/modal/audio.d.ts +269 -0
  232. package/types/plugins/modal/drawing.d.ts +246 -0
  233. package/types/plugins/modal/embed.d.ts +387 -0
  234. package/types/plugins/modal/image.d.ts +451 -0
  235. package/types/plugins/modal/link.d.ts +128 -0
  236. package/types/plugins/modal/math.d.ts +193 -0
  237. package/types/plugins/modal/video.d.ts +485 -0
  238. package/types/plugins/popup/anchor.d.ts +56 -0
  239. package/types/suneditor.d.ts +51 -0
  240. package/types/typedef-global.d.ts +144 -0
  241. package/src/core/class/notice.js +0 -42
  242. package/src/helper/domUtils.js +0 -1177
  243. package/src/modules/FileBrowser.js +0 -271
  244. package/src/plugins/command/exportPdf.js +0 -168
  245. package/src/plugins/fileBrowser/imageGallery.js +0 -81
  246. package/src/themes/test.css +0 -61
  247. package/typings/CommandPlugin.d.ts +0 -8
  248. package/typings/DialogPlugin.d.ts +0 -20
  249. package/typings/FileBrowserPlugin.d.ts +0 -30
  250. package/typings/Module.d.ts +0 -15
  251. package/typings/Plugin.d.ts +0 -42
  252. package/typings/SubmenuPlugin.d.ts +0 -8
  253. package/typings/_classes.d.ts +0 -17
  254. package/typings/_colorPicker.d.ts +0 -60
  255. package/typings/_core.d.ts +0 -55
  256. package/typings/align.d.ts +0 -5
  257. package/typings/audio.d.ts +0 -5
  258. package/typings/backgroundColor.d.ts +0 -5
  259. package/typings/blockquote.d.ts +0 -5
  260. package/typings/char.d.ts +0 -39
  261. package/typings/component.d.ts +0 -38
  262. package/typings/context.d.ts +0 -39
  263. package/typings/converter.d.ts +0 -33
  264. package/typings/dialog.d.ts +0 -28
  265. package/typings/domUtils.d.ts +0 -361
  266. package/typings/editor.d.ts +0 -7
  267. package/typings/editor.ts +0 -542
  268. package/typings/env.d.ts +0 -70
  269. package/typings/eventManager.d.ts +0 -37
  270. package/typings/events.d.ts +0 -262
  271. package/typings/fileBrowser.d.ts +0 -42
  272. package/typings/fileManager.d.ts +0 -67
  273. package/typings/font.d.ts +0 -5
  274. package/typings/fontColor.d.ts +0 -5
  275. package/typings/fontSize.d.ts +0 -5
  276. package/typings/format.d.ts +0 -191
  277. package/typings/formatBlock.d.ts +0 -5
  278. package/typings/history.d.ts +0 -48
  279. package/typings/horizontalRule.d.ts +0 -5
  280. package/typings/image.d.ts +0 -5
  281. package/typings/imageGallery.d.ts +0 -5
  282. package/typings/index.d.ts +0 -21
  283. package/typings/index.modules.d.ts +0 -11
  284. package/typings/index.plugins.d.ts +0 -58
  285. package/typings/lineHeight.d.ts +0 -5
  286. package/typings/link.d.ts +0 -5
  287. package/typings/list.d.ts +0 -5
  288. package/typings/math.d.ts +0 -5
  289. package/typings/mediaContainer.d.ts +0 -25
  290. package/typings/mention.d.ts +0 -5
  291. package/typings/node.d.ts +0 -57
  292. package/typings/notice.d.ts +0 -16
  293. package/typings/numbers.d.ts +0 -29
  294. package/typings/offset.d.ts +0 -24
  295. package/typings/options.d.ts +0 -589
  296. package/typings/paragraphStyle.d.ts +0 -5
  297. package/typings/resizing.d.ts +0 -141
  298. package/typings/selection.d.ts +0 -94
  299. package/typings/shortcuts.d.ts +0 -13
  300. package/typings/suneditor.d.ts +0 -9
  301. package/typings/table.d.ts +0 -5
  302. package/typings/template.d.ts +0 -5
  303. package/typings/textStyle.d.ts +0 -5
  304. package/typings/toolbar.d.ts +0 -32
  305. package/typings/unicode.d.ts +0 -25
  306. package/typings/video.d.ts +0 -5
@@ -1,5 +1,5 @@
1
1
  import EditorInjector from '../../editorInjector';
2
- import { domUtils, numbers, converter, env } from '../../helper';
2
+ import { dom, numbers, converter, env, keyCodeMap } from '../../helper';
3
3
  import { Controller, SelectMenu, ColorPicker, Figure, _DragHandle } from '../../modules';
4
4
 
5
5
  const { _w, ON_OVER_COMPONENT } = env;
@@ -61,270 +61,365 @@ const DEFAULT_COLOR_LIST = [
61
61
  '#000000'
62
62
  ];
63
63
 
64
- const Table = function (editor, pluginOptions) {
65
- // plugin bisic properties
66
- EditorInjector.call(this, editor);
67
- this.title = this.lang.table;
68
- this.icon = 'table';
69
-
70
- // pluginOptions options
71
- this.figureScrollList = ['se-scroll-figure-xy', 'se-scroll-figure-x', 'se-scroll-figure-y'];
72
- this.figureScroll = typeof pluginOptions.scrollType === 'string' ? pluginOptions.scrollType.toLowerCase() : 'x';
73
- this.captionPosition = pluginOptions.captionPosition !== 'bottom' ? 'top' : 'bottom';
74
- this.cellControllerTop = (pluginOptions.cellControllerPosition !== 'cell' ? 'table' : 'cell') === 'table';
75
-
76
- // create HTML
77
- const menu = CreateHTML(editor);
78
- const commandArea = menu.querySelector('.se-controller-table-picker');
79
- const controller_table = CreateHTML_controller_table(editor);
80
- const controller_cell = CreateHTML_controller_cell(editor, this.cellControllerTop);
81
- const controller_props = CreateHTML_controller_properties(editor);
82
-
83
- editor.applyFrameRoots((e) => {
84
- e.get('wrapper').appendChild(domUtils.createElement('DIV', { class: RESIZE_CELL_CLASS.replace(/^\./, '') }));
85
- e.get('wrapper').appendChild(domUtils.createElement('DIV', { class: RESIZE_CELL_PREV_CLASS.replace(/^\./, '') }));
86
- e.get('wrapper').appendChild(domUtils.createElement('DIV', { class: RESIZE_ROW_CLASS.replace(/^\./, '') }));
87
- e.get('wrapper').appendChild(domUtils.createElement('DIV', { class: RESIZE_ROW_PREV_CLASS.replace(/^\./, '') }));
88
- });
89
-
90
- // members - Controller
91
- this.controller_table = new Controller(this, controller_table, { position: 'top' });
92
- this.controller_cell = new Controller(this, controller_cell, { position: this.cellControllerTop ? 'top' : 'bottom' });
93
- // props
94
- const propsTargetForms = [this.controller_table.form, this.controller_cell.form];
95
- this.controller_props = new Controller(this, controller_props, { position: 'bottom', parents: propsTargetForms, isInsideForm: true });
96
- this.controller_props_title = controller_props.querySelector('.se-controller-title');
97
- // color picker
98
- const colorForm = domUtils.createElement('DIV', { class: 'se-controller se-list-layer' }, null);
99
- this.colorPicker = new ColorPicker(this, '', {
100
- colorList: pluginOptions.colorList || DEFAULT_COLOR_LIST,
101
- splitNum: 5,
102
- disableRemove: true,
103
- hueSliderOptions: { controllerOptions: { parents: [colorForm], isOutsideForm: true } }
104
- });
105
-
106
- colorForm.appendChild(this.colorPicker.target);
107
- this.controller_colorPicker = new Controller(this, colorForm, {
108
- position: 'bottom',
109
- parents: [this.controller_props.form].concat(propsTargetForms),
110
- isInsideForm: true,
111
- isWWTarget: false,
112
- initMethod: () => {
113
- this.colorPicker.hueSlider.close();
114
- domUtils.removeClass(this.controller_colorPicker.currentTarget, 'on');
115
- }
116
- });
117
-
118
- this.figure = new Figure(this, null, {});
119
-
120
- this.sliderType = '';
121
-
122
- // members - SelectMenu - split
123
- const splitMenu = CreateSplitMenu(this.lang);
124
- this.splitButton = controller_cell.querySelector('[data-command="onsplit"]');
125
- this.selectMenu_split = new SelectMenu(this, { checkList: false, position: 'bottom-center' });
126
- this.selectMenu_split.on(this.splitButton, OnSplitCells.bind(this));
127
- this.selectMenu_split.create(splitMenu.items, splitMenu.menus);
128
-
129
- // members - SelectMenu - column
130
- const columnMenu = CreateColumnMenu(this.lang, this.icons);
131
- const columnButton = controller_cell.querySelector('[data-command="oncolumn"]');
132
- this.selectMenu_column = new SelectMenu(this, { checkList: false, position: 'bottom-center' });
133
- this.selectMenu_column.on(columnButton, OnColumnEdit.bind(this));
134
- this.selectMenu_column.create(columnMenu.items, columnMenu.menus);
135
-
136
- // members - SelectMenu - row
137
- const rownMenu = CreateRowMenu(this.lang, this.icons);
138
- const rowButton = controller_cell.querySelector('[data-command="onrow"]');
139
- this.selectMenu_row = new SelectMenu(this, { checkList: false, position: 'bottom-center' });
140
- this.selectMenu_row.on(rowButton, OnRowEdit.bind(this));
141
- this.selectMenu_row.create(rownMenu.items, rownMenu.menus);
142
-
143
- // members - SelectMenu - properties - border style
144
- const borderMenu = CreateBorderMenu();
145
- const borderButton = controller_props.querySelector('[data-command="props_onborder_style"]');
146
- this.selectMenu_props_border = new SelectMenu(this, { checkList: false, position: 'bottom-center' });
147
- this.selectMenu_props_border.on(borderButton, OnPropsBorderEdit.bind(this));
148
- this.selectMenu_props_border.create(borderMenu.items, borderMenu.menus);
149
-
150
- // members - SelectMenu - properties - border format
151
- const borderFormatMenu = CreateBorderFormatMenu(this.lang, this.icons, []);
152
- const borderFormatButton = controller_props.querySelector('[data-command="props_onborder_format"]');
153
- this.selectMenu_props_border_format = new SelectMenu(this, { checkList: false, position: 'bottom-left', dir: 'ltr', splitNum: 5 });
154
- this.selectMenu_props_border_format.on(borderFormatButton, OnPropsBorderFormatEdit.bind(this, 'all'));
155
- this.selectMenu_props_border_format.create(borderFormatMenu.items, borderFormatMenu.menus);
156
-
157
- const borderFormatMenu_oneCell = CreateBorderFormatMenu(this.lang, this.icons, BORDER_FORMAT_INSIDE);
158
- this.selectMenu_props_border_format_oneCell = new SelectMenu(this, { checkList: false, position: 'bottom-left', dir: 'ltr', splitNum: 6 });
159
- this.selectMenu_props_border_format_oneCell.on(borderFormatButton, OnPropsBorderFormatEdit.bind(this, 'outside'));
160
- this.selectMenu_props_border_format_oneCell.create(borderFormatMenu_oneCell.items, borderFormatMenu_oneCell.menus);
161
-
162
- // memberts - elements..
163
- this.maxText = this.lang.maxSize;
164
- this.minText = this.lang.minSize;
165
- this.propTargets = {
166
- cell_alignment: controller_props.querySelector('.se-table-props-align > .__se__a_h'),
167
- cell_alignment_vertical: controller_props.querySelector('.se-table-props-align > .__se__a_v'),
168
- border_format: borderFormatButton,
169
- border_style: controller_props.querySelector('[data-command="props_onborder_style"] .se-txt'),
170
- border_color: controller_props.querySelector('.__se_border_color'),
171
- border_width: controller_props.querySelector('.__se__border_size'),
172
- back_color: controller_props.querySelector('.__se_back_color'),
173
- font_color: controller_props.querySelector('.__se_font_color'),
174
- palette_border_button: controller_props.querySelector('[data-command="props_onpalette"][data-value="border"]'),
175
- font_bold: controller_props.querySelector('[data-command="props_font_style"][data-value="bold"]'),
176
- font_underline: controller_props.querySelector('[data-command="props_font_style"][data-value="underline"]'),
177
- font_italic: controller_props.querySelector('[data-command="props_font_style"][data-value="italic"]'),
178
- font_strike: controller_props.querySelector('[data-command="props_font_style"][data-value="strike"]')
179
- };
180
- this._propsCache = [];
181
- this._currentFontStyles = [];
182
- this._propsAlignCache = '';
183
- this._propsVerticalAlignCache = '';
184
- this._typeCache = '';
185
- this.tableHighlight = menu.querySelector('.se-table-size-highlighted');
186
- this.tableUnHighlight = menu.querySelector('.se-table-size-unhighlighted');
187
- this.tableDisplay = menu.querySelector('.se-table-size-display');
188
- this.resizeButton = controller_table.querySelector('._se_table_resize');
189
- this.resizeText = controller_table.querySelector('._se_table_resize > span > span');
190
- this.columnFixedButton = controller_table.querySelector('._se_table_fixed_column');
191
- this.headerButton = controller_table.querySelector('._se_table_header');
192
- this.captionButton = controller_table.querySelector('._se_table_caption');
193
- this.mergeButton = controller_cell.querySelector('[data-command="merge"]');
194
-
195
- // members - private
196
- this._resizing = false;
197
- this._resizeLine = null;
198
- this._resizeLinePrev = null;
199
- this._figure = null;
200
- this._element = null;
201
- this._tdElement = null;
202
- this._trElement = null;
203
- this._trElements = null;
204
- this._tableXY = [];
205
- this._maxWidth = true;
206
- this._fixedColumn = false;
207
- this._physical_cellCnt = 0;
208
- this._logical_cellCnt = 0;
209
- this._rowCnt = 0;
210
- this._rowIndex = 0;
211
- this._physical_cellIndex = 0;
212
- this._logical_cellIndex = 0;
213
- this._current_colSpan = 0;
214
- this._current_rowSpan = 0;
215
-
216
- // member - multi selecte
217
- this._selectedCells = null;
218
- this._shift = false;
219
- this._fixedCell = null;
220
- this._fixedCellName = null;
221
- this._selectedCell = null;
222
- this._selectedTable = null;
223
- this._ref = null;
224
-
225
- // member - global events
226
- this._bindMultiOn = OnCellMultiSelect.bind(this);
227
- this._bindMultiOff = OffCellMultiSelect.bind(this);
228
- this._bindShiftOff = OffCellShift.bind(this);
229
- this._bindTouchOff = OffCellTouch.bind(this);
230
- this.__globalEvents = {
231
- on: null,
232
- off: null,
233
- shiftOff: null,
234
- touchOff: null,
235
- resize: null,
236
- resizeStop: null,
237
- resizeKeyDown: null
238
- };
64
+ /**
65
+ * @class
66
+ * @description Table Plugin
67
+ */
68
+ class Table extends EditorInjector {
69
+ static key = 'table';
70
+ static type = 'dropdown-free';
71
+ static className = '';
72
+ static options = { isInputComponent: true };
73
+ /**
74
+ * @this {Table}
75
+ * @param {HTMLElement} node - The node to check.
76
+ * @returns {HTMLElement|null} Returns a node if the node is a valid component.
77
+ */
78
+ static component(node) {
79
+ return dom.check.isTable(node) ? node : null;
80
+ }
239
81
 
240
- // init
241
- this.menu.initDropdownTarget(Table, menu);
242
- this.eventManager.addEvent(commandArea, 'mousemove', OnMouseMoveTablePicker.bind(this));
243
- this.eventManager.addEvent(commandArea, 'click', OnClickTablePicker.bind(this));
244
- };
82
+ /**
83
+ * @constructor
84
+ * @param {__se__EditorCore} editor - The root editor instance
85
+ * @param {Object} pluginOptions
86
+ * @param {"x"|"y"|"xy"} [pluginOptions.scrollType='x'] - Scroll type ('x', 'y', 'xy')
87
+ * @param {"top"|"bottom"} [pluginOptions.captionPosition='bottom'] - Caption position ('top', 'bottom')
88
+ * @param {"cell"|"table"} [pluginOptions.cellControllerPosition='cell'] - Cell controller position ('cell', 'table')
89
+ * @param {Array} [pluginOptions.colorList] - Color list, used in cell color picker
90
+ */
91
+ constructor(editor, pluginOptions) {
92
+ // plugin bisic properties
93
+ super(editor);
94
+ this.title = this.lang.table;
95
+ this.icon = 'table';
96
+
97
+ // pluginOptions options
98
+ this.figureScrollList = ['se-scroll-figure-xy', 'se-scroll-figure-x', 'se-scroll-figure-y'];
99
+ this.figureScroll = typeof pluginOptions.scrollType === 'string' ? pluginOptions.scrollType.toLowerCase() : 'x';
100
+ this.captionPosition = pluginOptions.captionPosition !== 'bottom' ? 'top' : 'bottom';
101
+ this.cellControllerTop = (pluginOptions.cellControllerPosition !== 'cell' ? 'table' : 'cell') === 'table';
102
+
103
+ // create HTML
104
+ const menu = CreateHTML();
105
+ const commandArea = menu.querySelector('.se-controller-table-picker');
106
+ const controller_table = CreateHTML_controller_table(editor);
107
+ const controller_cell = CreateHTML_controller_cell(editor, this.cellControllerTop);
108
+ const controller_props = CreateHTML_controller_properties(editor);
109
+
110
+ editor.applyFrameRoots((e) => {
111
+ e.get('wrapper').appendChild(dom.utils.createElement('DIV', { class: RESIZE_CELL_CLASS.replace(/^\./, '') }));
112
+ e.get('wrapper').appendChild(dom.utils.createElement('DIV', { class: RESIZE_CELL_PREV_CLASS.replace(/^\./, '') }));
113
+ e.get('wrapper').appendChild(dom.utils.createElement('DIV', { class: RESIZE_ROW_CLASS.replace(/^\./, '') }));
114
+ e.get('wrapper').appendChild(dom.utils.createElement('DIV', { class: RESIZE_ROW_PREV_CLASS.replace(/^\./, '') }));
115
+ });
116
+
117
+ // members - Controller
118
+ this.controller_table = new Controller(this, controller_table, { position: 'top' });
119
+ this.controller_cell = new Controller(this, controller_cell.html, { position: this.cellControllerTop ? 'top' : 'bottom' });
120
+ // props
121
+ const propsTargetForms = [this.controller_table.form, this.controller_cell.form];
122
+ this.controller_props = new Controller(this, controller_props.html, { position: 'bottom', parents: propsTargetForms, isInsideForm: true });
123
+ this.controller_props_title = controller_props.controller_props_title;
124
+ // color picker
125
+ const colorForm = dom.utils.createElement('DIV', { class: 'se-controller se-list-layer' }, null);
126
+ this.colorPicker = new ColorPicker(this, '', {
127
+ colorList: pluginOptions.colorList || DEFAULT_COLOR_LIST,
128
+ splitNum: 5,
129
+ disableRemove: true,
130
+ hueSliderOptions: { controllerOptions: { parents: [colorForm], isOutsideForm: true } }
131
+ });
132
+
133
+ colorForm.appendChild(this.colorPicker.target);
134
+ this.controller_colorPicker = new Controller(this, colorForm, {
135
+ position: 'bottom',
136
+ parents: [this.controller_props.form].concat(propsTargetForms),
137
+ isInsideForm: true,
138
+ isWWTarget: false,
139
+ initMethod: () => {
140
+ this.colorPicker.hueSlider.close();
141
+ dom.utils.removeClass(this.controller_colorPicker.currentTarget, 'on');
142
+ }
143
+ });
144
+
145
+ this.figure = new Figure(this, null, {});
146
+
147
+ this.sliderType = '';
148
+
149
+ // members - SelectMenu - split
150
+ const splitMenu = CreateSplitMenu(this.lang);
151
+ this.splitButton = controller_cell.splitButton;
152
+ this.selectMenu_split = new SelectMenu(this, { checkList: false, position: 'bottom-center' });
153
+ this.selectMenu_split.on(this.splitButton, this.#OnSplitCells.bind(this));
154
+ this.selectMenu_split.create(splitMenu.items, splitMenu.menus);
155
+
156
+ // members - SelectMenu - column
157
+ const columnMenu = CreateColumnMenu(this.lang, this.icons);
158
+ const columnButton = controller_cell.columnButton;
159
+ this.selectMenu_column = new SelectMenu(this, { checkList: false, position: 'bottom-center' });
160
+ this.selectMenu_column.on(columnButton, this.#OnColumnEdit.bind(this));
161
+ this.selectMenu_column.create(columnMenu.items, columnMenu.menus);
162
+
163
+ // members - SelectMenu - row
164
+ const rownMenu = CreateRowMenu(this.lang, this.icons);
165
+ const rowButton = controller_cell.rowButton;
166
+ this.selectMenu_row = new SelectMenu(this, { checkList: false, position: 'bottom-center' });
167
+ this.selectMenu_row.on(rowButton, this.#OnRowEdit.bind(this));
168
+ this.selectMenu_row.create(rownMenu.items, rownMenu.menus);
169
+
170
+ // members - SelectMenu - properties - border style
171
+ const borderMenu = CreateBorderMenu();
172
+ const borderButton = controller_props.borderButton;
173
+ this.selectMenu_props_border = new SelectMenu(this, { checkList: false, position: 'bottom-center' });
174
+ this.selectMenu_props_border.on(borderButton, OnPropsBorderEdit.bind(this));
175
+ this.selectMenu_props_border.create(borderMenu.items, borderMenu.menus);
176
+
177
+ // members - SelectMenu - properties - border format
178
+ const borderFormatMenu = CreateBorderFormatMenu(this.lang, this.icons, []);
179
+ const borderFormatButton = controller_props.borderFormatButton;
180
+ this.selectMenu_props_border_format = new SelectMenu(this, { checkList: false, position: 'bottom-left', dir: 'ltr', splitNum: 5 });
181
+ this.selectMenu_props_border_format.on(borderFormatButton, OnPropsBorderFormatEdit.bind(this, 'all'));
182
+ this.selectMenu_props_border_format.create(borderFormatMenu.items, borderFormatMenu.menus);
183
+
184
+ const borderFormatMenu_oneCell = CreateBorderFormatMenu(this.lang, this.icons, BORDER_FORMAT_INSIDE);
185
+ this.selectMenu_props_border_format_oneCell = new SelectMenu(this, { checkList: false, position: 'bottom-left', dir: 'ltr', splitNum: 6 });
186
+ this.selectMenu_props_border_format_oneCell.on(borderFormatButton, OnPropsBorderFormatEdit.bind(this, 'outside'));
187
+ this.selectMenu_props_border_format_oneCell.create(borderFormatMenu_oneCell.items, borderFormatMenu_oneCell.menus);
188
+
189
+ // memberts - elements..
190
+ this.maxText = this.lang.maxSize;
191
+ this.minText = this.lang.minSize;
192
+ this.propTargets = {
193
+ cell_alignment: controller_props.cell_alignment,
194
+ cell_alignment_vertical: controller_props.cell_alignment_vertical,
195
+ cell_alignment_table_text: controller_props.cell_alignment_table_text,
196
+ border_format: borderFormatButton,
197
+ border_style: controller_props.border_style,
198
+ border_color: controller_props.border_color,
199
+ border_width: controller_props.border_width,
200
+ back_color: controller_props.back_color,
201
+ font_color: controller_props.font_color,
202
+ palette_border_button: controller_props.palette_border_button,
203
+ font_bold: controller_props.font_bold,
204
+ font_underline: controller_props.font_underline,
205
+ font_italic: controller_props.font_italic,
206
+ font_strike: controller_props.font_strike
207
+ };
208
+ this._propsCache = [];
209
+ this._currentFontStyles = [];
210
+ this._propsAlignCache = '';
211
+ this._propsVerticalAlignCache = '';
212
+ this._typeCache = '';
213
+
214
+ /** @type {HTMLElement} */
215
+ this.tableHighlight = menu.querySelector('.se-table-size-highlighted');
216
+ /** @type {HTMLElement} */
217
+ this.tableUnHighlight = menu.querySelector('.se-table-size-unhighlighted');
218
+ /** @type {HTMLElement} */
219
+ this.tableDisplay = menu.querySelector('.se-table-size-display');
220
+ /** @type {HTMLButtonElement} */
221
+ this.resizeButton = controller_table.querySelector('._se_table_resize');
222
+ /** @type {HTMLSpanElement} */
223
+ this.resizeText = controller_table.querySelector('._se_table_resize > span > span');
224
+ /** @type {HTMLButtonElement} */
225
+ this.columnFixedButton = controller_table.querySelector('._se_table_fixed_column');
226
+ /** @type {HTMLButtonElement} */
227
+ this.headerButton = controller_table.querySelector('._se_table_header');
228
+ /** @type {HTMLButtonElement} */
229
+ this.captionButton = controller_table.querySelector('._se_table_caption');
230
+ /** @type {HTMLButtonElement} */
231
+ this.mergeButton = controller_cell.mergeButton;
232
+
233
+ // members - private
234
+ this._resizing = false;
235
+ this._resizeLine = null;
236
+ this._resizeLinePrev = null;
237
+
238
+ /** @type {HTMLElement} */
239
+ this._figure = null;
240
+ /** @type {HTMLTableElement} */
241
+ this._element = null;
242
+ /** @type {HTMLTableCellElement} */
243
+ this._tdElement = null;
244
+ /** @type {HTMLTableRowElement} */
245
+ this._trElement = null;
246
+ /** @type {HTMLTableRowElement[]|HTMLCollectionOf<HTMLTableRowElement>} */
247
+ this._trElements = null;
248
+
249
+ this._tableXY = [];
250
+ this._maxWidth = true;
251
+ this._fixedColumn = false;
252
+ this._physical_cellCnt = 0;
253
+ this._logical_cellCnt = 0;
254
+ this._rowCnt = 0;
255
+ this._rowIndex = 0;
256
+ this._physical_cellIndex = 0;
257
+ this._logical_cellIndex = 0;
258
+ this._current_colSpan = 0;
259
+ this._current_rowSpan = 0;
260
+
261
+ // member - multi selecte
262
+ /** @type {HTMLTableElement} */
263
+ this._selectedTable = null;
264
+ /** @type {HTMLTableCellElement} */
265
+ this._fixedCell = null;
266
+ /** @type {HTMLTableCellElement} */
267
+ this._selectedCell = null;
268
+ /** @type {HTMLTableCellElement[]} */
269
+ this._selectedCells = null;
270
+
271
+ this._shift = false;
272
+ this.__s = false;
273
+ this._fixedCellName = null;
274
+ this._ref = null;
275
+
276
+ // member - global events
277
+ this._bindMultiOn = this.#OnCellMultiSelect.bind(this);
278
+ this._bindMultiOff = this.#OffCellMultiSelect.bind(this);
279
+ this._bindShiftOff = this.#OffCellShift.bind(this);
280
+ this._bindTouchOff = this.#OffCellTouch.bind(this);
281
+ this.__globalEvents = {
282
+ on: null,
283
+ off: null,
284
+ shiftOff: null,
285
+ touchOff: null,
286
+ resize: null,
287
+ resizeStop: null,
288
+ resizeKeyDown: null
289
+ };
290
+
291
+ // init
292
+ this.menu.initDropdownTarget(Table, menu);
293
+ this.eventManager.addEvent(commandArea, 'mousemove', this.#OnMouseMoveTablePicker.bind(this));
294
+ this.eventManager.addEvent(commandArea, 'click', this.#OnClickTablePicker.bind(this));
295
+ }
245
296
 
246
- Table.key = 'table';
247
- Table.type = 'dropdown-free';
248
- Table.className = '';
249
- Table.component = function (node) {
250
- return domUtils.isTable(node) ? node : null;
251
- };
252
- Table.options = { isInputComponent: true };
253
- Table.prototype = {
254
297
  /**
255
- * @override core
298
+ * @editorMethod Editor.core
299
+ * @description Executes the main execution method of the plugin.
300
+ * - Called when an item in the "dropdown" menu is clicked.
256
301
  */
257
302
  action() {
258
- const oTable = domUtils.createElement('TABLE');
303
+ const oTable = dom.utils.createElement('TABLE');
259
304
  const x = this._tableXY[0];
260
305
  const y = this._tableXY[1];
261
306
 
262
- const body = `<tbody>${`<tr>${CreateCells('td', x, false)}</tr>`.repeat(y)}</tbody>`;
307
+ const body = `<tbody>${`<tr>${CreateCellsString('td', x)}</tr>`.repeat(y)}</tbody>`;
263
308
  const colGroup = `<colgroup>${`<col style="width: ${numbers.get(100 / x, CELL_DECIMAL_END)}%;">`.repeat(x)}</colgroup>`;
264
309
  oTable.innerHTML = colGroup + body;
265
310
 
266
- const figure = domUtils.createElement('FIGURE', { class: 'se-flex-component se-input-component' });
311
+ // scroll
312
+ let scrollTypeClass = '';
313
+ if (this.figureScroll) {
314
+ scrollTypeClass = ` se-scroll-figure-${this.figureScroll}`;
315
+ }
316
+
317
+ const figure = dom.utils.createElement('FIGURE', { class: 'se-flex-component se-input-component' + scrollTypeClass });
267
318
  figure.appendChild(oTable);
268
319
 
269
- if (this.component.insert(figure, false, false)) {
320
+ if (this.component.insert(figure, { skipCharCount: false, skipSelection: false, skipHistory: false })) {
270
321
  this._resetTablePicker();
271
322
  const target = oTable.querySelector('td div');
272
323
  this.selection.setRange(target, 0, target, 0);
273
324
  }
274
- },
325
+ }
275
326
 
276
327
  /**
277
- * @override core
328
+ * @editorMethod Modules.Component
329
+ * @description Executes the method that is called when a component of a plugin is selected.
330
+ * @param {HTMLElement} target Target component element
331
+ */
332
+ select(target) {
333
+ this._figureOpen(target);
334
+ if (!this._figure) this.setTableInfo(target);
335
+
336
+ const targetWidth = this._figure?.style.width || '100%';
337
+ this._maxWidth = targetWidth === '100%';
338
+ this._fixedColumn = dom.utils.hasClass(target, 'se-table-layout-fixed') || target.style.tableLayout === 'fixed';
339
+ this._setTableStyle(this._maxWidth ? 'width|column' : 'width', true);
340
+
341
+ if (_DragHandle.get('__overInfo') === ON_OVER_COMPONENT) return;
342
+
343
+ if (!this._tdElement) return;
344
+ this.setCellInfo(this._tdElement, true);
345
+
346
+ // controller open
347
+ const btnDisabled = this._selectedCells.length > 1;
348
+ const figureEl = dom.query.getParentElement(target, dom.check.isFigure);
349
+ this.controller_table.open(figureEl, null, { isWWTarget: false, initMethod: null, addOffset: null, disabled: btnDisabled });
350
+
351
+ const addOffset = !this.cellControllerTop ? null : this.controller_table.form.style.display === 'block' ? { left: this.controller_table.form.offsetWidth + 2 } : null;
352
+ this.controller_cell.open(this._tdElement, this.cellControllerTop ? figureEl : null, { isWWTarget: false, initMethod: null, addOffset: addOffset, disabled: btnDisabled });
353
+ }
354
+
355
+ /**
356
+ * @editorMethod Editor.core
357
+ * @description This method is used to validate and preserve the format of the component within the editor.
358
+ * - It ensures that the structure and attributes of the element are maintained and secure.
359
+ * - The method checks if the element is already wrapped in a valid container and updates its attributes if necessary.
360
+ * - If the element isn't properly contained, a new container is created to retain the format.
361
+ * @returns {{query: string, method: (element: HTMLTableElement) => void}} The format retention object containing the query and method to process the element.
362
+ * - query: The selector query to identify the relevant elements (in this case, 'audio').
363
+ * - method:The function to execute on the element to validate and preserve its format.
364
+ * - The function takes the element as an argument, checks if it is contained correctly, and applies necessary adjustments.
278
365
  */
279
366
  retainFormat() {
280
367
  return {
281
368
  query: 'table',
282
369
  method: (element) => {
283
370
  const ColgroupEl = element.querySelector('colgroup');
284
- let FigureEl = domUtils.isFigure(element.parentNode) ? element.parentNode : null;
371
+ let FigureEl = dom.check.isFigure(element.parentNode) ? element.parentNode : null;
285
372
  if (ColgroupEl && FigureEl) return;
286
373
 
287
374
  // create colgroup
288
375
  if (!ColgroupEl) {
289
376
  const maxCount = GetMaxColumns(element);
290
- const colGroup = domUtils.createElement('colgroup', null, `<col style="width: ${numbers.get(100 / maxCount, CELL_DECIMAL_END)}%;">`.repeat(maxCount));
377
+ const colGroup = dom.utils.createElement('colgroup', null, `<col style="width: ${numbers.get(100 / maxCount, CELL_DECIMAL_END)}%;">`.repeat(maxCount));
291
378
  element.insertBefore(colGroup, element.firstElementChild);
292
379
  }
293
380
 
294
381
  // figure
295
382
  if (!FigureEl) {
296
- FigureEl = domUtils.createElement('FIGURE', { class: 'se-flex-component se-input-component' });
383
+ FigureEl = dom.utils.createElement('FIGURE', { class: 'se-flex-component se-input-component' });
297
384
  element.parentNode.insertBefore(FigureEl, element);
298
385
  FigureEl.appendChild(element);
299
386
  } else {
300
- domUtils.addClass(FigureEl, 'se-flex-component|se-input-component');
387
+ dom.utils.addClass(FigureEl, 'se-flex-component|se-input-component');
301
388
  }
302
389
 
303
390
  // scroll
304
391
  if (!this.figureScroll) {
305
- domUtils.removeClass(FigureEl, this.figureScrollList.join('|'));
392
+ dom.utils.removeClass(FigureEl, this.figureScrollList.join('|'));
306
393
  } else {
307
394
  const scrollTypeClass = `se-scroll-figure-${this.figureScroll}`;
308
- domUtils.addClass(FigureEl, scrollTypeClass);
309
- domUtils.removeClass(FigureEl, this.figureScrollList.filter((v) => v !== scrollTypeClass).join('|'));
395
+ dom.utils.addClass(FigureEl, scrollTypeClass);
396
+ dom.utils.removeClass(FigureEl, this.figureScrollList.filter((v) => v !== scrollTypeClass).join('|'));
310
397
  }
311
398
  }
312
399
  };
313
- },
400
+ }
314
401
 
315
402
  /**
316
- * @override core
317
- * @param {"rtl"|"ltr"} dir Direction
403
+ * @editorMethod Editor.core
404
+ * @description Executes the method called when the rtl, ltr mode changes. ("editor.setDir")
405
+ * @param {string} dir Direction ("rtl" or "ltr")
318
406
  */
319
407
  setDir(dir) {
320
408
  this.tableHighlight.style.left = dir === 'rtl' ? 10 * 18 - 13 + 'px' : '';
321
409
  this._resetTablePicker();
322
- this._resetPropsAlign(dir === 'rtl');
323
- },
410
+ this._resetPropsAlign();
411
+ }
324
412
 
413
+ /**
414
+ * @editorMethod Editor.EventManager
415
+ * @description Executes the event function of "mousemove".
416
+ * @param {__se__PluginMouseEventInfo} params
417
+ */
325
418
  onMouseMove({ event }) {
326
419
  if (this._resizing) return;
327
- const target = domUtils.getParentElement(event.target, IsResizeEls);
420
+
421
+ const eventTarget = dom.query.getEventTarget(event);
422
+ const target = dom.query.getParentElement(eventTarget, IsResizeEls);
328
423
  if (!target || this._fixedCell) {
329
424
  this.__hideResizeLine();
330
425
  return;
@@ -336,7 +431,7 @@ Table.prototype = {
336
431
  this.__removeGlobalEvents();
337
432
  if (this._resizeLine?.style.display === 'block') this._resizeLine.style.display = 'none';
338
433
  this._resizeLine = this.editor.frameContext.get('wrapper').querySelector(RESIZE_CELL_CLASS);
339
- this._setResizeLinePosition(domUtils.getParentElement(target, domUtils.isTable), target, this._resizeLine, cellEdge.isLeft);
434
+ this._setResizeLinePosition(dom.query.getParentElement(target, dom.check.isTable), target, this._resizeLine, cellEdge.isLeft);
340
435
  this._resizeLine.style.display = 'block';
341
436
  return;
342
437
  }
@@ -344,33 +439,39 @@ Table.prototype = {
344
439
  const rowEdge = CheckRowEdge(event, target);
345
440
  if (rowEdge.is) {
346
441
  this.__removeGlobalEvents();
347
- this._element = domUtils.getParentElement(target, domUtils.isTable);
442
+ this._element = dom.query.getParentElement(target, dom.check.isTable);
348
443
  this._element.style.cursor = 'ns-resize';
349
444
  if (this._resizeLine?.style.display === 'block') this._resizeLine.style.display = 'none';
350
445
  this._resizeLine = this.editor.frameContext.get('wrapper').querySelector(RESIZE_ROW_CLASS);
351
- this._setResizeRowPosition(domUtils.getParentElement(target, domUtils.isTable), target, this._resizeLine);
446
+ this._setResizeRowPosition(dom.query.getParentElement(target, dom.check.isTable), target, this._resizeLine);
352
447
  this._resizeLine.style.display = 'block';
353
448
  return;
354
449
  }
355
450
 
356
451
  if (this._element) this._element.style.cursor = '';
357
452
  this.__hideResizeLine();
358
- },
453
+ }
359
454
 
455
+ /**
456
+ * @editorMethod Editor.EventManager
457
+ * @description Executes the event function of "scroll".
458
+ */
360
459
  onScroll() {
361
460
  if (this._resizeLine?.style.display !== 'block') return;
362
461
  // delete resize line position
363
462
  if (this._element) this._element.style.cursor = '';
364
463
  this._resizeLine.style.display = 'none';
365
- },
464
+ }
366
465
 
367
466
  /**
368
- * @override core
369
- * @param {any} event Event object
467
+ * @editorMethod Editor.EventManager
468
+ * @description Executes the event function of "mousedown".
469
+ * @param {__se__PluginMouseEventInfo} params
370
470
  */
371
471
  onMouseDown({ event }) {
372
472
  this._ref = null;
373
- const target = domUtils.getParentElement(event.target, IsResizeEls);
473
+ const eventTarget = dom.query.getEventTarget(event);
474
+ const target = /** @type {HTMLTableCellElement} */ (dom.query.getParentElement(eventTarget, IsResizeEls));
374
475
  if (!target) return;
375
476
 
376
477
  const cellEdge = CheckCellEdge(event, target);
@@ -381,7 +482,7 @@ Table.prototype = {
381
482
  const colIndex = this._logical_cellIndex - (cellEdge.isLeft ? 1 : 0);
382
483
 
383
484
  // ready
384
- this.editor.enableBackWrapper('ew-resize');
485
+ this.ui.enableBackWrapper('ew-resize');
385
486
  if (!this._resizeLine) this._resizeLine = this.editor.frameContext.get('wrapper').querySelector(RESIZE_CELL_CLASS);
386
487
  this._resizeLinePrev = this.editor.frameContext.get('wrapper').querySelector(RESIZE_CELL_PREV_CLASS);
387
488
 
@@ -404,11 +505,12 @@ Table.prototype = {
404
505
  const rowEdge = CheckRowEdge(event, target);
405
506
  if (rowEdge.is) {
406
507
  try {
407
- let row = domUtils.getParentElement(target, domUtils.isTableRow);
508
+ /** @type {HTMLTableRowElement} */
509
+ let row = dom.query.getParentElement(target, dom.check.isTableRow);
408
510
  let rowSpan = target.rowSpan;
409
511
  if (rowSpan > 1) {
410
- while (domUtils.isTableRow(row) && rowSpan > 1) {
411
- row = row.nextElementSibling;
512
+ while (dom.check.isTableRow(row) && rowSpan > 1) {
513
+ row = /** @type {HTMLTableRowElement} */ (row.nextElementSibling);
412
514
  --rowSpan;
413
515
  }
414
516
  }
@@ -417,7 +519,7 @@ Table.prototype = {
417
519
  this.setRowInfo(row);
418
520
 
419
521
  // ready
420
- this.editor.enableBackWrapper('ns-resize');
522
+ this.ui.enableBackWrapper('ns-resize');
421
523
  if (!this._resizeLine) this._resizeLine = this.editor.frameContext.get('wrapper').querySelector(RESIZE_ROW_CLASS);
422
524
  this._resizeLinePrev = this.editor.frameContext.get('wrapper').querySelector(RESIZE_ROW_PREV_CLASS);
423
525
 
@@ -430,52 +532,56 @@ Table.prototype = {
430
532
  return;
431
533
  }
432
534
 
433
- if (!(target !== this._fixedCell && !this._shift)) return;
535
+ if (this._shift && target !== this._fixedCell) return;
434
536
 
435
537
  this._deleteStyleSelectedCells();
436
538
  if (/^TR$/i.test(target.nodeName)) return;
437
539
 
438
540
  this.selectCells(target, false);
439
- },
541
+ }
440
542
 
441
543
  /**
442
- * @override core
544
+ * @editorMethod Editor.EventManager
545
+ * @description Executes the event function of "mouseup".
443
546
  */
444
547
  onMouseUp() {
445
548
  this._shift = false;
446
- },
549
+ }
447
550
 
448
551
  /**
449
- * @override core
552
+ * @editorMethod Editor.EventManager
553
+ * @description Executes the event function of "mouseleave".
450
554
  */
451
555
  onMouseLeave() {
452
556
  this.__hideResizeLine();
453
- },
557
+ }
454
558
 
455
559
  /**
456
- * @override core
457
- * @param {any} event Event object
458
- * @param {any} range range object
459
- * @param {Element} line Current line element
560
+ * @editorMethod Editor.EventManager
561
+ * @description Executes the event function of "keydown".
562
+ * @param {__se__PluginKeyEventInfo} params
460
563
  */
461
564
  onKeyDown({ event, range, line }) {
462
565
  this._ref = null;
463
- if (this.editor.selectMenuOn || this._resizing) return;
566
+ if (this.editor.selectMenuOn || this._resizing || this.__s) return;
464
567
 
465
- const keyCode = event.keyCode;
568
+ const keyCode = event.code;
569
+ this.__s = event.shiftKey;
466
570
  // table tabkey
467
- if (keyCode === 9) {
468
- const tableCell = domUtils.getParentElement(line, domUtils.isTableCell);
469
- if (tableCell && range.collapsed && domUtils.isEdgePoint(range.startContainer, range.startOffset)) {
571
+ if (keyCodeMap.isTab(keyCode)) {
572
+ const tableCell = dom.query.getParentElement(line, dom.check.isTableCell);
573
+ if (tableCell && range.collapsed && dom.check.isEdgePoint(range.startContainer, range.startOffset)) {
470
574
  this._closeController();
471
575
 
472
576
  const shift = event.shiftKey;
473
- const table = domUtils.getParentElement(tableCell, 'table');
474
- const cells = domUtils.getListChildren(table, domUtils.isTableCell);
475
- const idx = shift ? domUtils.prevIndex(cells, tableCell) : domUtils.nextIndex(cells, tableCell);
577
+ /** @type {HTMLTableElement} */
578
+ const table = dom.query.getParentElement(tableCell, 'table');
579
+ /** @type {HTMLTableCellElement[]} */
580
+ const cells = dom.query.getListChildren(table, dom.check.isTableCell);
581
+ const idx = shift ? dom.utils.prevIndex(cells, tableCell) : dom.utils.nextIndex(cells, tableCell);
476
582
 
477
583
  if (idx === cells.length && !shift) {
478
- if (!domUtils.getParentElement(tableCell, 'thead')) {
584
+ if (!dom.query.getParentElement(tableCell, 'thead')) {
479
585
  const rows = table.rows;
480
586
  const newRow = this.insertBodyRow(table, rows.length, rows[rows.length - 1].cells.length);
481
587
  const firstTd = newRow.querySelector('td div');
@@ -490,11 +596,11 @@ Table.prototype = {
490
596
 
491
597
  if (idx === -1 && shift) return;
492
598
 
493
- let moveCell = cells[idx];
599
+ const moveCell = cells[idx];
494
600
  if (!moveCell) return;
495
601
 
496
- moveCell = moveCell.firstElementChild || moveCell;
497
- this.selection.setRange(moveCell, 0, moveCell, 0);
602
+ const rangeCell = moveCell.firstElementChild || moveCell;
603
+ this.selection.setRange(rangeCell, 0, rangeCell, 0);
498
604
 
499
605
  event.preventDefault();
500
606
  event.stopPropagation();
@@ -504,9 +610,9 @@ Table.prototype = {
504
610
  }
505
611
 
506
612
  let cell = null;
507
- if (!event.shiftKey || keyCode !== 16) {
508
- cell = domUtils.getParentElement(line, domUtils.isTableCell);
509
- if (!domUtils.hasClass(cell, 'se-selected-cell-focus')) return;
613
+ if (!keyCodeMap.isShift(event)) {
614
+ cell = dom.query.getParentElement(line, dom.check.isTableCell);
615
+ if (!dom.utils.hasClass(cell, 'se-selected-cell-focus')) return;
510
616
 
511
617
  this._deleteStyleSelectedCells();
512
618
  this._toggleEditor(true);
@@ -518,43 +624,46 @@ Table.prototype = {
518
624
 
519
625
  if (this._shift || this._ref) return;
520
626
 
521
- cell = cell || domUtils.getParentElement(line, domUtils.isTableCell);
627
+ cell = /** @type {HTMLTableCellElement} */ (cell || dom.query.getParentElement(line, dom.check.isTableCell));
522
628
  if (cell) {
629
+ this.__s = false;
523
630
  this._fixedCell = cell;
524
631
  this._closeController();
525
632
  this.selectCells(cell, event.shiftKey);
526
633
  return false;
527
634
  }
528
- },
635
+ }
529
636
 
530
637
  /**
531
- * @override core
532
- * @param {any} event Event object
533
- * @param {any} range range object
534
- * @param {Element} line Current line element
638
+ * @editorMethod Editor.EventManager
639
+ * @description Executes the event function of "keyup".
640
+ * @param {__se__PluginKeyEventInfo} params
535
641
  */
536
642
  onKeyUp({ line }) {
537
- if (this._shift && domUtils.getParentElement(line, domUtils.isTableCell) === this._fixedCell) {
643
+ this.__s = false;
644
+ if (this._shift && dom.query.getParentElement(line, dom.check.isTableCell) === this._fixedCell) {
538
645
  this._deleteStyleSelectedCells();
539
646
  this._toggleEditor(true);
540
647
  this.__removeGlobalEvents();
541
648
  }
542
649
  this._shift = false;
543
- },
650
+ }
544
651
 
545
652
  /**
546
- * @override ColorPicker
653
+ * @editorMethod Modules.ColorPicker
654
+ * @description Executes the method called when a button of "ColorPicker" module is clicked.
655
+ * @param {string} color - Color code (hex)
547
656
  */
548
657
  colorPickerAction(color) {
549
658
  const target = this.propTargets[`${this.sliderType}_color`];
550
659
  target.style.borderColor = target.value = color;
551
660
  this.controller_colorPicker.close();
552
- },
661
+ }
553
662
 
554
663
  /**
555
- * @override controller
556
- * @param {Element} target Target button element
557
- * @returns
664
+ * @editorMethod Modules.Controller
665
+ * @description Executes the method that is called when a button is clicked in the "controller".
666
+ * @param {HTMLButtonElement} target Target button element
558
667
  */
559
668
  controllerAction(target) {
560
669
  const command = target.getAttribute('data-command');
@@ -614,7 +723,7 @@ Table.prototype = {
614
723
  this._onColorPalette(target, value, value === 'border' ? border_color : value === 'back' ? back_color : font_color);
615
724
  break;
616
725
  case 'props_font_style':
617
- domUtils.toggleClass(this.propTargets[`font_${value}`], 'on');
726
+ dom.utils.toggleClass(this.propTargets[`font_${value}`], 'on');
618
727
  break;
619
728
  case 'props_submit':
620
729
  this._submitProps(target);
@@ -627,7 +736,7 @@ Table.prototype = {
627
736
  // alignment
628
737
  this._setAlignProps(this.propTargets.cell_alignment, this._propsAlignCache, true);
629
738
  this._setAlignProps(this.propTargets.cell_alignment_vertical, this._propsVerticalAlignCache, true);
630
- if (domUtils.isTable(propsCache[0][0]) && this._figure) {
739
+ if (dom.check.isTable(propsCache[0][0]) && this._figure) {
631
740
  this._figure.style.float = this._propsAlignCache;
632
741
  }
633
742
  break;
@@ -646,19 +755,19 @@ Table.prototype = {
646
755
  break;
647
756
  case 'resize':
648
757
  this._maxWidth = !this._maxWidth;
649
- this.setTableStyle('width', false);
758
+ this._setTableStyle('width', false);
650
759
  this._historyPush();
651
760
  this.component.select(this._element, Table.key, true);
652
761
  break;
653
762
  case 'layout':
654
763
  this._fixedColumn = !this._fixedColumn;
655
- this.setTableStyle('column', false);
764
+ this._setTableStyle('column', false);
656
765
  this._historyPush();
657
766
  this.component.select(this._element, Table.key, true);
658
767
  break;
659
768
  case 'remove': {
660
769
  const emptyDiv = this._figure?.parentNode;
661
- domUtils.removeItem(this._figure);
770
+ dom.utils.removeItem(this._figure);
662
771
  this._closeController();
663
772
 
664
773
  if (emptyDiv !== this.editor.frameContext.get('wysiwyg'))
@@ -680,12 +789,13 @@ Table.prototype = {
680
789
  }
681
790
 
682
791
  if (!/^(remove|props_|on|open|merge)/.test(command)) {
683
- this.setCellControllerPosition(this._tdElement, this._shift);
792
+ this._setCellControllerPosition(this._tdElement, this._shift);
684
793
  }
685
- },
794
+ }
686
795
 
687
796
  /**
688
- * @override controller
797
+ * @editorMethod Modules.Controller
798
+ * @description Executes the method called when the "controller" is closed.
689
799
  */
690
800
  close() {
691
801
  this.__removeGlobalEvents();
@@ -719,19 +829,26 @@ Table.prototype = {
719
829
  this._fixedCellName = null;
720
830
 
721
831
  const { border_format, border_color, border_style, border_width, back_color, font_color, cell_alignment, cell_alignment_vertical, font_bold, font_underline, font_italic, font_strike } = this.propTargets;
722
- domUtils.removeClass([border_format, border_color, border_style, border_width, back_color, font_color, cell_alignment, cell_alignment_vertical, font_bold, font_underline, font_italic, font_strike], 'on');
723
- },
832
+ dom.utils.removeClass([border_format, border_color, border_style, border_width, back_color, font_color, cell_alignment, cell_alignment_vertical, font_bold, font_underline, font_italic, font_strike], 'on');
833
+ }
724
834
 
835
+ /**
836
+ * @description Selects cells in a table, handling single and multi-cell selection, and managing shift key behavior for extended selection.
837
+ * @param {HTMLTableCellElement} tdElement The target table cell (`<td>`) element that is being selected.
838
+ * @param {boolean} shift A flag indicating whether the shift key is held down for multi-cell selection.
839
+ * If `true`, the selection will extend to include adjacent cells, otherwise it selects only the provided cell.
840
+ */
725
841
  selectCells(tdElement, shift) {
842
+ this.__s = shift;
726
843
  if (!this._shift && !this._ref) this.__removeGlobalEvents();
727
844
 
728
845
  this._shift = shift;
729
846
  this._fixedCell = tdElement;
730
847
  this._fixedCellName = tdElement.nodeName;
731
- this._selectedTable = domUtils.getParentElement(tdElement, 'TABLE');
848
+ this._selectedTable = dom.query.getParentElement(tdElement, 'TABLE');
732
849
 
733
850
  this._deleteStyleSelectedCells();
734
- domUtils.addClass(tdElement, 'se-selected-cell-focus');
851
+ dom.utils.addClass(tdElement, 'se-selected-cell-focus');
735
852
 
736
853
  if (!shift) {
737
854
  this.__globalEvents.on = this.eventManager.addGlobalEvent('mousemove', this._bindMultiOn, false);
@@ -742,30 +859,41 @@ Table.prototype = {
742
859
 
743
860
  this.__globalEvents.off = this.eventManager.addGlobalEvent('mouseup', this._bindMultiOff, false);
744
861
  this.__globalEvents.touchOff = this.eventManager.addGlobalEvent('touchmove', this._bindTouchOff, false);
745
- },
862
+ }
746
863
 
747
- seTableInfo(element) {
748
- const table = (this._element = this._selectedTable || domUtils.getParentElement(element, 'TABLE'));
749
- this._figure = domUtils.getParentElement(table, domUtils.isFigure) || table;
750
- return table;
751
- },
864
+ /**
865
+ * @description Sets the table and figure elements based on the provided cell element, and stores references to them for later use.
866
+ * @param {Node} element The target table cell (`<td>`) element from which the table info will be extracted.
867
+ * @returns {HTMLTableElement} The `<table>` element that is the parent of the provided `element`.
868
+ */
869
+ setTableInfo(element) {
870
+ const table = (this._element = this._selectedTable || dom.query.getParentElement(element, 'TABLE'));
871
+ this._figure = dom.query.getParentElement(table, dom.check.isFigure) || table;
872
+ return /** @type {HTMLTableElement} */ (table);
873
+ }
752
874
 
875
+ /**
876
+ * @description Sets various table-related information based on the provided table cell element (`<td>`). This includes updating cell, row, and table attributes, handling spanning cells, and adjusting the UI for elements like headers and captions.
877
+ * @param {HTMLTableCellElement} tdElement The target table cell (`<td>`) element from which table information will be extracted.
878
+ * @param {boolean} reset A flag indicating whether to reset the cell information. If `true`, the cell information will be reset and recalculated.
879
+ */
753
880
  setCellInfo(tdElement, reset) {
754
- const table = this.seTableInfo(tdElement);
755
- this._trElement = tdElement.parentNode;
881
+ const table = this.setTableInfo(tdElement);
882
+ if (!table) return;
883
+ this._trElement = /** @type {HTMLTableRowElement} */ (tdElement.parentNode);
756
884
 
757
885
  // hedaer
758
- if (table.querySelector('thead')) domUtils.addClass(this.headerButton, 'active');
759
- else domUtils.removeClass(this.headerButton, 'active');
886
+ if (table.querySelector('thead')) dom.utils.addClass(this.headerButton, 'active');
887
+ else dom.utils.removeClass(this.headerButton, 'active');
760
888
 
761
889
  // caption
762
- if (table.querySelector('caption')) domUtils.addClass(this.captionButton, 'active');
763
- else domUtils.removeClass(this.captionButton, 'active');
890
+ if (table.querySelector('caption')) dom.utils.addClass(this.captionButton, 'active');
891
+ else dom.utils.removeClass(this.captionButton, 'active');
764
892
 
765
893
  if (reset || this._physical_cellCnt === 0) {
766
894
  if (this._tdElement !== tdElement) {
767
895
  this._tdElement = tdElement;
768
- this._trElement = tdElement.parentNode;
896
+ this._trElement = /** @type {HTMLTableRowElement} */ (tdElement.parentNode);
769
897
  }
770
898
 
771
899
  if (!this._selectedCells || this._selectedCells.length === 0) this._selectedCells = [tdElement];
@@ -854,30 +982,39 @@ Table.prototype = {
854
982
  rowSpanArr = null;
855
983
  spanIndex = null;
856
984
  }
857
- },
985
+ }
858
986
 
987
+ /**
988
+ * @description Sets row-related information based on the provided table row element (`<tr>`). This includes updating the row count and the index of the selected row.
989
+ * @param {HTMLTableRowElement} trElement The target table row (`<tr>`) element from which row information will be extracted.
990
+ */
859
991
  setRowInfo(trElement) {
860
- const table = this.seTableInfo(trElement);
992
+ const table = this.setTableInfo(trElement);
861
993
  const rows = (this._trElements = table.rows);
862
994
  this._rowCnt = rows.length;
863
995
  this._rowIndex = trElement.rowIndex;
864
- },
996
+ }
865
997
 
998
+ /**
999
+ * @description Edits the table by adding, removing, or modifying rows and cells, based on the provided options. Supports both single and multi-cell/row editing.
1000
+ * @param {"row"|"cell"} type The type of element to edit ('row' or 'cell').
1001
+ * @param {?"up"|"down"|"left"|"right"} option The action to perform: 'up', 'down', 'left', 'right', or `null` for removing.
1002
+ */
866
1003
  editTable(type, option) {
867
1004
  const table = this._element;
868
1005
  const isRow = type === 'row';
869
1006
 
870
1007
  if (isRow) {
871
- const tableAttr = this._trElement.parentNode;
1008
+ const tableAttr = this._trElement.parentElement;
872
1009
  if (/^THEAD$/i.test(tableAttr.nodeName)) {
873
1010
  if (option === 'up') {
874
1011
  return;
875
1012
  } else if (!tableAttr.nextElementSibling || !/^TBODY$/i.test(tableAttr.nextElementSibling.nodeName)) {
876
1013
  if (!option) {
877
- domUtils.removeItem(this._figure);
1014
+ dom.utils.removeItem(this._figure);
878
1015
  this._closeController();
879
1016
  } else {
880
- table.innerHTML += '<tbody><tr>' + CreateCells('td', this._logical_cellCnt, false) + '</tr></tbody>';
1017
+ table.innerHTML += '<tbody><tr>' + CreateCellsString('td', this._logical_cellCnt) + '</tr></tbody>';
881
1018
  }
882
1019
  return;
883
1020
  }
@@ -959,16 +1096,26 @@ Table.prototype = {
959
1096
  const children = table.children;
960
1097
  for (let i = 0; i < children.length; i++) {
961
1098
  if (children[i].children.length === 0) {
962
- domUtils.removeItem(children[i]);
1099
+ dom.utils.removeItem(children[i]);
963
1100
  i--;
964
1101
  }
965
1102
  }
966
1103
 
967
- if (table.children.length === 0) domUtils.removeItem(table);
1104
+ if (table.children.length === 0) dom.utils.removeItem(table);
968
1105
  }
969
- },
1106
+ }
970
1107
 
1108
+ /**
1109
+ * @description Edits a table row, either adding, removing, the row
1110
+ * @param {?string} option The action to perform on the row ("up"|"down"|null)
1111
+ * - null: to remove the row
1112
+ * - 'up': to insert the row up
1113
+ * - 'down': to insert the row down, or null to remove.
1114
+ * @param {?HTMLTableCellElement=} [positionResetElement] The element to reset the position of (optional). This can be the cell that triggered the row edit.
1115
+ */
971
1116
  editRow(option, positionResetElement) {
1117
+ this._deleteStyleSelectedCells();
1118
+
972
1119
  const remove = !option;
973
1120
  const up = option === 'up';
974
1121
  const originRowIndex = this._rowIndex;
@@ -1008,7 +1155,7 @@ Table.prototype = {
1008
1155
 
1009
1156
  if (cell.rowSpan > 1) {
1010
1157
  cell.rowSpan -= 1;
1011
- spanCells.push({ cell: cell.cloneNode(false), index: logcalIndex });
1158
+ spanCells.push({ cell: /** @type {HTMLTableCellElement} */ (cell.cloneNode(false)), index: logcalIndex });
1012
1159
  }
1013
1160
  }
1014
1161
 
@@ -1047,12 +1194,20 @@ Table.prototype = {
1047
1194
  }
1048
1195
 
1049
1196
  if (!remove) {
1050
- this.setCellControllerPosition(positionResetElement || this._tdElement, true);
1197
+ this._setCellControllerPosition(positionResetElement || this._tdElement, true);
1051
1198
  } else {
1052
1199
  this._closeController();
1053
1200
  }
1054
- },
1201
+ }
1055
1202
 
1203
+ /**
1204
+ * @description Edits a table cell(column), either adding, removing, or modifying the cell based on the provided option.
1205
+ * @param {?string} option The action to perform on the cell ("left"|"right"|null)
1206
+ * - null: to remove the cell
1207
+ * - left: to insert a new cell to the left
1208
+ * - right: to insert a new cell to the right
1209
+ * @param {?HTMLTableCellElement=} [positionResetElement] The element to reset the position of (optional). This can be the cell that triggered the column edit.
1210
+ */
1056
1211
  editCell(option, positionResetElement) {
1057
1212
  const remove = !option;
1058
1213
  const left = option === 'left';
@@ -1172,7 +1327,7 @@ Table.prototype = {
1172
1327
  }
1173
1328
 
1174
1329
  if (insertIndex !== null && cells.length > 0) {
1175
- newCell = CreateCells(cells[0].nodeName, 0, true);
1330
+ newCell = CreateCellsHTML(cells[0].nodeName);
1176
1331
  newCell = row.insertBefore(newCell, cells[insertIndex]);
1177
1332
  }
1178
1333
  }
@@ -1182,16 +1337,16 @@ Table.prototype = {
1182
1337
  if (colgroup) {
1183
1338
  const cols = colgroup.querySelectorAll('col');
1184
1339
  if (remove) {
1185
- domUtils.removeItem(cols[insertIndex]);
1340
+ dom.utils.removeItem(cols[insertIndex]);
1186
1341
  } else {
1187
1342
  let totalW = 0;
1188
1343
  for (let i = 0, len = cols.length, w; i < len; i++) {
1189
1344
  w = numbers.get(cols[i].style.width);
1190
- w -= Math.round((w * len * 0.1) / 2, CELL_DECIMAL_END);
1345
+ w -= Math.round((w * len * 0.1) / 2);
1191
1346
  totalW += w;
1192
1347
  cols[i].style.width = `${w}%`;
1193
1348
  }
1194
- const newCol = domUtils.createElement('col', { style: `width:${100 - totalW}%` });
1349
+ const newCol = dom.utils.createElement('col', { style: `width:${100 - totalW}%` });
1195
1350
  colgroup.insertBefore(newCol, cols[insertIndex]);
1196
1351
  }
1197
1352
  }
@@ -1199,12 +1354,12 @@ Table.prototype = {
1199
1354
  if (remove) {
1200
1355
  let removeFirst, removeEnd;
1201
1356
  for (let r = 0, rLen = removeCell.length, row; r < rLen; r++) {
1202
- row = removeCell[r].parentNode;
1203
- domUtils.removeItem(removeCell[r]);
1357
+ row = /** @type {HTMLTableRowElement} */ (removeCell[r].parentNode);
1358
+ dom.utils.removeItem(removeCell[r]);
1204
1359
  if (row.cells.length === 0) {
1205
- if (!removeFirst) removeFirst = domUtils.getArrayIndex(rows, row);
1206
- removeEnd = domUtils.getArrayIndex(rows, row);
1207
- domUtils.removeItem(row);
1360
+ if (!removeFirst) removeFirst = dom.utils.getArrayIndex(rows, row);
1361
+ removeEnd = dom.utils.getArrayIndex(rows, row);
1362
+ dom.utils.removeItem(row);
1208
1363
  }
1209
1364
  }
1210
1365
 
@@ -1215,16 +1370,27 @@ Table.prototype = {
1215
1370
 
1216
1371
  this._closeController();
1217
1372
  } else {
1218
- this.setCellControllerPosition(positionResetElement || this._tdElement, true);
1373
+ this._setCellControllerPosition(positionResetElement || this._tdElement, true);
1219
1374
  }
1220
- },
1375
+ }
1221
1376
 
1377
+ /**
1378
+ * @description Inserts a new row into the table at the specified index to it.
1379
+ * @param {HTMLTableElement} table The table element to insert the row into.
1380
+ * @param {number} rowIndex The index at which to insert the new row.
1381
+ * @param {number} cellCnt The number of cells to create in the new row.
1382
+ * @returns {HTMLTableRowElement} The newly inserted row element.
1383
+ */
1222
1384
  insertBodyRow(table, rowIndex, cellCnt) {
1223
1385
  const newRow = table.insertRow(rowIndex);
1224
- newRow.innerHTML = CreateCells('td', cellCnt, false);
1386
+ newRow.innerHTML = CreateCellsString('td', cellCnt);
1225
1387
  return newRow;
1226
- },
1388
+ }
1227
1389
 
1390
+ /**
1391
+ * @description Merges the selected table cells into one cell by combining their contents and adjusting their row and column spans.
1392
+ * - This method removes the selected cells, consolidates their contents, and applies the appropriate row and column spans to the merged cell.
1393
+ */
1228
1394
  mergeCells() {
1229
1395
  const ref = this._ref;
1230
1396
  const selectedCells = this._selectedCells;
@@ -1239,17 +1405,17 @@ Table.prototype = {
1239
1405
 
1240
1406
  for (let i = 1, len = selectedCells.length, cell, ch; i < len; i++) {
1241
1407
  cell = selectedCells[i];
1242
- if (row !== cell.parentNode) row = cell.parentNode;
1408
+ if (row !== cell.parentNode) row = /** @type {HTMLTableRowElement} */ (cell.parentNode);
1243
1409
 
1244
1410
  ch = cell.children;
1245
1411
  for (let c = 0, cLen = ch.length; c < cLen; c++) {
1246
- if (this.format.isLine(ch[c]) && domUtils.isZeroWith(ch[c].textContent)) {
1247
- domUtils.removeItem(ch[c]);
1412
+ if (this.format.isLine(ch[c]) && dom.check.isZeroWidth(ch[c].textContent)) {
1413
+ dom.utils.removeItem(ch[c]);
1248
1414
  }
1249
1415
  }
1250
1416
 
1251
1417
  mergeHTML += cell.innerHTML;
1252
- domUtils.removeItem(cell);
1418
+ dom.utils.removeItem(cell);
1253
1419
 
1254
1420
  if (row.cells.length === 0) {
1255
1421
  if (!emptyRowFirst) emptyRowFirst = row;
@@ -1260,8 +1426,8 @@ Table.prototype = {
1260
1426
 
1261
1427
  if (emptyRowFirst) {
1262
1428
  const rows = this._trElements;
1263
- const rowIndexFirst = domUtils.getArrayIndex(rows, emptyRowFirst);
1264
- const rowIndexLast = domUtils.getArrayIndex(rows, emptyRowLast || emptyRowFirst);
1429
+ const rowIndexFirst = dom.utils.getArrayIndex(rows, emptyRowFirst);
1430
+ const rowIndexLast = dom.utils.getArrayIndex(rows, emptyRowLast || emptyRowFirst);
1265
1431
  const removeRows = [];
1266
1432
 
1267
1433
  for (let i = 0, cells; i <= rowIndexLast; i++) {
@@ -1281,7 +1447,7 @@ Table.prototype = {
1281
1447
  }
1282
1448
 
1283
1449
  for (let i = 0, len = removeRows.length; i < len; i++) {
1284
- domUtils.removeItem(removeRows[i]);
1450
+ dom.utils.removeItem(removeRows[i]);
1285
1451
  }
1286
1452
  }
1287
1453
 
@@ -1289,53 +1455,65 @@ Table.prototype = {
1289
1455
  mergeCell.colSpan = cs;
1290
1456
  mergeCell.rowSpan = rs;
1291
1457
 
1292
- this.setMergeSplitButton(true, false);
1293
- this.setController(mergeCell);
1458
+ this._setMergeSplitButton(true, false);
1459
+ this._setController(mergeCell);
1294
1460
 
1295
1461
  this.editor.focusEdge(mergeCell);
1296
1462
  this._historyPush();
1297
- },
1463
+ }
1298
1464
 
1465
+ /**
1466
+ * @description Toggles the visibility of the table header (`<thead>`). If the header is present, it is removed; if absent, it is added.
1467
+ */
1299
1468
  toggleHeader() {
1300
1469
  const btn = this.headerButton;
1301
- const active = domUtils.hasClass(btn, 'active');
1470
+ const active = dom.utils.hasClass(btn, 'active');
1302
1471
  const table = this._element;
1303
1472
 
1304
1473
  if (!active) {
1305
- const header = domUtils.createElement('THEAD');
1306
- header.innerHTML = '<tr>' + CreateCells('th', this._logical_cellCnt, false) + '</tr>';
1474
+ const header = dom.utils.createElement('THEAD');
1475
+ header.innerHTML = '<tr>' + CreateCellsString('th', this._logical_cellCnt) + '</tr>';
1307
1476
  table.insertBefore(header, table.firstElementChild);
1308
1477
  } else {
1309
- domUtils.removeItem(table.querySelector('thead'));
1478
+ dom.utils.removeItem(table.querySelector('thead'));
1310
1479
  }
1311
1480
 
1312
- domUtils.toggleClass(btn, 'active');
1481
+ dom.utils.toggleClass(btn, 'active');
1313
1482
 
1314
1483
  if (/TH/i.test(this._tdElement.nodeName)) {
1315
1484
  this._closeController();
1316
1485
  } else {
1317
- this.setCellControllerPosition(this._tdElement, false);
1486
+ this._setCellControllerPosition(this._tdElement, false);
1318
1487
  }
1319
- },
1488
+ }
1320
1489
 
1490
+ /**
1491
+ * @description Toggles the visibility of the table caption (`<caption>`). If the caption is present, it is removed; if absent, it is added.
1492
+ */
1321
1493
  toggleCaption() {
1322
1494
  const btn = this.captionButton;
1323
- const active = domUtils.hasClass(btn, 'active');
1495
+ const active = dom.utils.hasClass(btn, 'active');
1324
1496
  const table = this._element;
1325
1497
 
1326
1498
  if (!active) {
1327
- const caption = domUtils.createElement('CAPTION', { class: `se-table-caption-${this.captionPosition}` });
1499
+ const caption = dom.utils.createElement('CAPTION', { class: `se-table-caption-${this.captionPosition}` });
1328
1500
  caption.innerHTML = '<div><br></div>';
1329
1501
  table.insertBefore(caption, table.firstElementChild);
1330
1502
  } else {
1331
- domUtils.removeItem(table.querySelector('caption'));
1503
+ dom.utils.removeItem(table.querySelector('caption'));
1332
1504
  }
1333
1505
 
1334
- domUtils.toggleClass(btn, 'active');
1335
- this.setCellControllerPosition(this._tdElement, false);
1336
- },
1506
+ dom.utils.toggleClass(btn, 'active');
1507
+ this._setCellControllerPosition(this._tdElement, false);
1508
+ }
1337
1509
 
1338
- setTableStyle(styles, ondisplay) {
1510
+ /**
1511
+ * @private
1512
+ * @description Updates table styles.
1513
+ * @param {string} styles - Styles to update.
1514
+ * @param {boolean} ondisplay - Whether to update display.
1515
+ */
1516
+ _setTableStyle(styles, ondisplay) {
1339
1517
  if (styles.includes('width')) {
1340
1518
  const targets = this._figure;
1341
1519
  if (!targets) return;
@@ -1351,24 +1529,30 @@ Table.prototype = {
1351
1529
  if (!ondisplay) targets.style.width = '100%';
1352
1530
  }
1353
1531
 
1354
- domUtils.changeElement(this.resizeButton.firstElementChild, sizeIcon);
1355
- domUtils.changeTxt(this.resizeText, text);
1532
+ dom.utils.changeElement(this.resizeButton.firstElementChild, sizeIcon);
1533
+ dom.utils.changeTxt(this.resizeText, text);
1356
1534
  }
1357
1535
 
1358
1536
  if (styles.includes('column')) {
1359
1537
  if (!this._fixedColumn) {
1360
- domUtils.removeClass(this._element, 'se-table-layout-fixed');
1361
- domUtils.addClass(this._element, 'se-table-layout-auto');
1362
- domUtils.removeClass(this.columnFixedButton, 'active');
1538
+ dom.utils.removeClass(this._element, 'se-table-layout-fixed');
1539
+ dom.utils.addClass(this._element, 'se-table-layout-auto');
1540
+ dom.utils.removeClass(this.columnFixedButton, 'active');
1363
1541
  } else {
1364
- domUtils.removeClass(this._element, 'se-table-layout-auto');
1365
- domUtils.addClass(this._element, 'se-table-layout-fixed');
1366
- domUtils.addClass(this.columnFixedButton, 'active');
1542
+ dom.utils.removeClass(this._element, 'se-table-layout-auto');
1543
+ dom.utils.addClass(this._element, 'se-table-layout-fixed');
1544
+ dom.utils.addClass(this.columnFixedButton, 'active');
1367
1545
  }
1368
1546
  }
1369
- },
1547
+ }
1370
1548
 
1371
- setMergeSplitButton(fixedCell, selectedCell) {
1549
+ /**
1550
+ * @private
1551
+ * @description Sets the merge/split button visibility.
1552
+ * @param {boolean} fixedCell - Whether a single cell is selected.
1553
+ * @param {boolean} selectedCell - Whether multiple cells are selected.
1554
+ */
1555
+ _setMergeSplitButton(fixedCell, selectedCell) {
1372
1556
  if (!selectedCell || !selectedCell || fixedCell === selectedCell) {
1373
1557
  this.splitButton.style.display = 'block';
1374
1558
  this.mergeButton.style.display = 'none';
@@ -1376,67 +1560,70 @@ Table.prototype = {
1376
1560
  this.splitButton.style.display = 'none';
1377
1561
  this.mergeButton.style.display = 'block';
1378
1562
  }
1379
- },
1563
+ }
1380
1564
 
1381
1565
  /**
1382
- * @override fileManager
1383
- * @param {Element} target Target element
1566
+ * @private
1567
+ * @description Sets the controller position for a cell.
1568
+ * @param {HTMLTableCellElement} tdElement - The target table cell.
1384
1569
  */
1385
- select(target) {
1386
- this._figureOpen(target);
1387
-
1388
- const targetWidth = this._figure?.style.width || '100%';
1389
- this._maxWidth = targetWidth === '100%';
1390
- this._fixedColumn = domUtils.hasClass(target, 'se-table-layout-fixed') || target.style.tableLayout === 'fixed';
1391
- this.setTableStyle(this._maxWidth ? 'width|column' : 'width', true);
1392
-
1393
- if (_DragHandle.get('__overInfo') === ON_OVER_COMPONENT) return;
1394
-
1395
- if (!this._tdElement) return;
1396
- this.setCellInfo(this._tdElement, true);
1397
-
1398
- // controller open
1399
- const figureEl = domUtils.getParentElement(target, domUtils.isFigure);
1400
- this.controller_table.open(figureEl, null, { isWWTarget: false, initMethod: null, addOffset: null });
1401
-
1402
- const addOffset = !this.cellControllerTop ? null : this.controller_table.form.style.display === 'block' ? { left: this.controller_table.form.offsetWidth + 2 } : null;
1403
- this.controller_cell.open(this._tdElement, this.cellControllerTop ? figureEl : null, { isWWTarget: false, initMethod: null, addOffset: addOffset });
1404
- },
1405
-
1406
- setController(tdElement) {
1570
+ _setController(tdElement) {
1407
1571
  if (!this.selection.get().isCollapsed && !this._selectedCell) {
1408
1572
  this._deleteStyleSelectedCells();
1409
1573
  return;
1410
1574
  }
1411
1575
 
1412
1576
  this._tdElement = tdElement;
1413
- domUtils.addClass(tdElement, 'se-selected-cell-focus');
1414
- const tableElement = this._element || this._selectedTable || domUtils.getParentElement(tdElement, 'TABLE');
1577
+ dom.utils.addClass(tdElement, 'se-selected-cell-focus');
1578
+ const tableElement = this._element || this._selectedTable || dom.query.getParentElement(tdElement, 'TABLE');
1415
1579
  this.component.select(tableElement, Table.key, true);
1416
- },
1580
+ }
1417
1581
 
1418
- setCellControllerPosition(tdElement, reset) {
1582
+ /**
1583
+ * @private
1584
+ * @description Sets the position of the cell controller.
1585
+ * @param {HTMLTableCellElement} tdElement - The target table cell.
1586
+ * @param {boolean} reset - Whether to reset the controller position.
1587
+ */
1588
+ _setCellControllerPosition(tdElement, reset) {
1419
1589
  this.setCellInfo(tdElement, reset);
1420
- this.controller_cell.resetPosition(this.cellControllerTop ? domUtils.getParentElement(tdElement, domUtils.isTable) : tdElement);
1421
- },
1590
+ this.controller_cell.resetPosition(this.cellControllerTop ? dom.query.getParentElement(tdElement, dom.check.isTable) : tdElement);
1591
+ }
1422
1592
 
1593
+ /**
1594
+ * @private
1595
+ * @description Adds a new entry to the history stack.
1596
+ */
1423
1597
  _historyPush() {
1424
1598
  this._deleteStyleSelectedCells();
1425
1599
  this.history.push(false);
1426
1600
  this._recallStyleSelectedCells();
1427
- },
1601
+ }
1428
1602
 
1603
+ /**
1604
+ * @private
1605
+ * @description Opens the figure.
1606
+ * @param {Node} target - The target figure element.
1607
+ */
1429
1608
  _figureOpen(target) {
1430
1609
  this.figure.open(target, { nonResizing: true, nonSizeInfo: true, nonBorder: true, figureTarget: true, __fileManagerInfo: false });
1431
- },
1610
+ }
1432
1611
 
1612
+ /**
1613
+ * @private
1614
+ * @description Starts resizing a table cell.
1615
+ * @param {HTMLElement} col The column element.
1616
+ * @param {number} startX The starting X position.
1617
+ * @param {number} startWidth The initial width of the column.
1618
+ * @param {boolean} isLeftEdge Whether the resizing is on the left edge.
1619
+ */
1433
1620
  _startCellResizing(col, startX, startWidth, isLeftEdge) {
1434
1621
  this._setResizeLinePosition(this._figure, this._tdElement, this._resizeLinePrev, isLeftEdge);
1435
1622
  this._resizeLinePrev.style.display = 'block';
1436
1623
  const prevValue = col.style.width;
1437
- const nextCol = col.nextElementSibling;
1624
+ const nextCol = /** @type {HTMLElement} */ (col.nextElementSibling);
1438
1625
  const nextColPrevValue = nextCol.style.width;
1439
- const realWidth = domUtils.hasClass(this._element, 'se-table-layout-fixed') ? nextColPrevValue : converter.getWidthInPercentage(col);
1626
+ const realWidth = dom.utils.hasClass(this._element, 'se-table-layout-fixed') ? nextColPrevValue : converter.getWidthInPercentage(col);
1440
1627
 
1441
1628
  if (_DragHandle.get('__dragHandler')) _DragHandle.get('__dragHandler').style.display = 'none';
1442
1629
  this._addResizeGlobalEvents(
@@ -1465,8 +1652,24 @@ Table.prototype = {
1465
1652
  this._stopResize(nextCol, nextColPrevValue, 'width', e);
1466
1653
  }
1467
1654
  );
1468
- },
1655
+ }
1469
1656
 
1657
+ /**
1658
+ * @private
1659
+ * @description Resizes a table cell.
1660
+ * @param {HTMLElement} col The column element.
1661
+ * @param {HTMLElement} nextCol The next column element.
1662
+ * @param {HTMLElement} figure The table figure element.
1663
+ * @param {HTMLElement} tdEl The table cell element.
1664
+ * @param {HTMLElement} resizeLine The resize line element.
1665
+ * @param {boolean} isLeftEdge Whether the resizing is on the left edge.
1666
+ * @param {number} startX The starting X position.
1667
+ * @param {number} startWidth The initial width of the column.
1668
+ * @param {number} prevWidthPercent The previous width percentage.
1669
+ * @param {number} nextColWidthPercent The next column's width percentage.
1670
+ * @param {number} tableWidth The total width of the table.
1671
+ * @param {MouseEvent} e The mouse event.
1672
+ */
1470
1673
  _cellResize(col, nextCol, figure, tdEl, resizeLine, isLeftEdge, startX, startWidth, prevWidthPercent, nextColWidthPercent, tableWidth, e) {
1471
1674
  const deltaX = e.clientX - startX;
1472
1675
  const newWidthPx = startWidth + deltaX;
@@ -1478,8 +1681,15 @@ Table.prototype = {
1478
1681
  nextCol.style.width = `${nextColWidthPercent + delta}%`;
1479
1682
  this._setResizeLinePosition(figure, tdEl, resizeLine, isLeftEdge);
1480
1683
  }
1481
- },
1684
+ }
1482
1685
 
1686
+ /**
1687
+ * @private
1688
+ * @description Starts resizing a table row.
1689
+ * @param {HTMLElement} row The table row element.
1690
+ * @param {number} startY The starting Y position.
1691
+ * @param {number} startHeight The initial height of the row.
1692
+ */
1483
1693
  _startRowResizing(row, startY, startHeight) {
1484
1694
  this._setResizeRowPosition(this._figure, row, this._resizeLinePrev);
1485
1695
  this._resizeLinePrev.style.display = 'block';
@@ -1488,20 +1698,36 @@ Table.prototype = {
1488
1698
  this._addResizeGlobalEvents(
1489
1699
  this._rowResize.bind(this, row, this._figure, this._resizeLine, startY, startHeight),
1490
1700
  () => {
1491
- this.__removeGlobalEvents(this);
1701
+ this.__removeGlobalEvents();
1492
1702
  this.history.push(true);
1493
1703
  },
1494
1704
  this._stopResize.bind(this, row, prevValue, 'height')
1495
1705
  );
1496
- },
1706
+ }
1497
1707
 
1708
+ /**
1709
+ * @private
1710
+ * @description Resizes a table row.
1711
+ * @param {HTMLElement} row The table row element.
1712
+ * @param {HTMLElement} figure The table figure element.
1713
+ * @param {HTMLElement} resizeLine The resize line element.
1714
+ * @param {number} startY The starting Y position.
1715
+ * @param {number} startHeight The initial height of the row.
1716
+ * @param {MouseEvent} e The mouse event.
1717
+ */
1498
1718
  _rowResize(row, figure, resizeLine, startY, startHeight, e) {
1499
1719
  const deltaY = e.clientY - startY;
1500
1720
  const newHeightPx = startHeight + deltaY;
1501
1721
  row.style.height = `${newHeightPx}px`;
1502
1722
  this._setResizeRowPosition(figure, row, resizeLine);
1503
- },
1723
+ }
1504
1724
 
1725
+ /**
1726
+ * @private
1727
+ * @description Starts resizing the table figure.
1728
+ * @param {number} startX The starting X position.
1729
+ * @param {boolean} isLeftEdge Whether the resizing is on the left edge.
1730
+ */
1505
1731
  _startFigureResizing(startX, isLeftEdge) {
1506
1732
  const figure = this._figure;
1507
1733
  this._setResizeLinePosition(figure, figure, this._resizeLinePrev, isLeftEdge);
@@ -1518,8 +1744,19 @@ Table.prototype = {
1518
1744
  },
1519
1745
  this._stopResize.bind(this, figure, figure.style.width, 'width')
1520
1746
  );
1521
- },
1747
+ }
1522
1748
 
1749
+ /**
1750
+ * @private
1751
+ * @description Resizes the table figure.
1752
+ * @param {HTMLElement} figure The table figure element.
1753
+ * @param {HTMLElement} resizeLine The resize line element.
1754
+ * @param {boolean} isLeftEdge Whether the resizing is on the left edge.
1755
+ * @param {number} startX The starting X position.
1756
+ * @param {number} startWidth The initial width of the figure.
1757
+ * @param {number} constNum A constant number used for width calculation.
1758
+ * @param {MouseEvent} e The mouse event.
1759
+ */
1523
1760
  _figureResize(figure, resizeLine, isLeftEdge, startX, startWidth, constNum, e) {
1524
1761
  const deltaX = isLeftEdge ? startX - e.clientX : e.clientX - startX;
1525
1762
  const newWidthPx = startWidth + deltaX;
@@ -1529,78 +1766,126 @@ Table.prototype = {
1529
1766
  figure.style.width = `${newWidthPercent}%`;
1530
1767
  this._setResizeLinePosition(figure, figure, resizeLine, isLeftEdge);
1531
1768
  }
1532
- },
1769
+ }
1533
1770
 
1771
+ /**
1772
+ * @private
1773
+ * @description Sets the resize line position.
1774
+ * @param {HTMLElement} figure The table figure element.
1775
+ * @param {HTMLElement} target The target element.
1776
+ * @param {HTMLElement} resizeLine The resize line element.
1777
+ * @param {boolean} isLeftEdge Whether the resizing is on the left edge.
1778
+ */
1534
1779
  _setResizeLinePosition(figure, target, resizeLine, isLeftEdge) {
1535
- const tdOffset = this.offset.get(target);
1536
- const tableOffset = this.offset.get(figure);
1780
+ const tdOffset = this.offset.getLocal(target);
1781
+ const tableOffset = this.offset.getLocal(figure);
1537
1782
  resizeLine.style.left = `${tdOffset.left + (isLeftEdge ? 0 : target.offsetWidth)}px`;
1538
1783
  resizeLine.style.top = `${tableOffset.top}px`;
1539
1784
  resizeLine.style.height = `${figure.offsetHeight}px`;
1540
- },
1785
+ }
1541
1786
 
1787
+ /**
1788
+ * @private
1789
+ * @description Sets the resize row position.
1790
+ * @param {HTMLElement} figure The table figure element.
1791
+ * @param {HTMLElement} target The target row element.
1792
+ * @param {HTMLElement} resizeLine The resize line element.
1793
+ */
1542
1794
  _setResizeRowPosition(figure, target, resizeLine) {
1543
- const rowOffset = this.offset.get(target);
1544
- const tableOffset = this.offset.get(figure);
1795
+ const rowOffset = this.offset.getLocal(target);
1796
+ const tableOffset = this.offset.getLocal(figure);
1545
1797
  resizeLine.style.top = `${rowOffset.top + target.offsetHeight}px`;
1546
1798
  resizeLine.style.left = `${tableOffset.left}px`;
1547
1799
  resizeLine.style.width = `${figure.offsetWidth}px`;
1548
- },
1800
+ }
1549
1801
 
1802
+ /**
1803
+ * @private
1804
+ * @description Stops resizing the table.
1805
+ * @param {HTMLElement} target The target element.
1806
+ * @param {string} prevValue The previous style value.
1807
+ * @param {string} styleProp The CSS property being changed.
1808
+ * @param {KeyboardEvent} e The keyboard event.
1809
+ */
1550
1810
  _stopResize(target, prevValue, styleProp, e) {
1551
- if (e.keyCode !== 27) return;
1811
+ if (!keyCodeMap.isEsc(e.code)) return;
1552
1812
  this.__removeGlobalEvents();
1553
1813
  target.style[styleProp] = prevValue;
1554
1814
  // figure reopen
1555
1815
  if (styleProp === 'width') {
1556
1816
  this.component.select(this._element, Table.key, true);
1557
1817
  }
1558
- },
1818
+ }
1559
1819
 
1820
+ /**
1821
+ * @private
1822
+ * @description Deletes styles from selected table cells.
1823
+ */
1560
1824
  _deleteStyleSelectedCells() {
1561
- domUtils.removeClass([this._fixedCell, this._selectedCell], 'se-selected-cell-focus');
1825
+ dom.utils.removeClass([this._fixedCell, this._selectedCell], 'se-selected-cell-focus');
1562
1826
  if (this._selectedTable) {
1563
1827
  const selectedCells = this._selectedTable.querySelectorAll('.se-selected-table-cell');
1564
1828
  for (let i = 0, len = selectedCells.length; i < len; i++) {
1565
- domUtils.removeClass(selectedCells[i], 'se-selected-table-cell');
1829
+ dom.utils.removeClass(selectedCells[i], 'se-selected-table-cell');
1566
1830
  }
1567
1831
  }
1568
- },
1832
+ }
1569
1833
 
1834
+ /**
1835
+ * @private
1836
+ * @description Restores styles for selected table cells.
1837
+ */
1570
1838
  _recallStyleSelectedCells() {
1571
1839
  if (this._selectedCells) {
1572
1840
  const selectedCells = this._selectedCells;
1573
1841
  for (let i = 0, len = selectedCells.length; i < len; i++) {
1574
- domUtils.addClass(selectedCells[i], 'se-selected-table-cell');
1842
+ dom.utils.addClass(selectedCells[i], 'se-selected-table-cell');
1575
1843
  }
1576
1844
  }
1577
- },
1845
+ }
1578
1846
 
1847
+ /**
1848
+ * @private
1849
+ * @description Adds global event listeners for resizing.
1850
+ * @param {(...args: *) => void} resizeFn The function handling the resize event.
1851
+ * @param {(...args: *) => void} stopFn The function handling the stop event.
1852
+ * @param {(...args: *) => void} keyDownFn The function handling the keydown event.
1853
+ */
1579
1854
  _addResizeGlobalEvents(resizeFn, stopFn, keyDownFn) {
1580
1855
  this.__globalEvents.resize = this.eventManager.addGlobalEvent('mousemove', resizeFn, false);
1581
1856
  this.__globalEvents.resizeStop = this.eventManager.addGlobalEvent('mouseup', stopFn, false);
1582
1857
  this.__globalEvents.resizeKeyDown = this.eventManager.addGlobalEvent('keydown', keyDownFn, false);
1583
1858
  this._resizing = true;
1584
- },
1859
+ }
1585
1860
 
1861
+ /**
1862
+ * @private
1863
+ * @description Enables or disables editor mode.
1864
+ * @param {boolean} enabled Whether to enable or disable the editor.
1865
+ */
1586
1866
  _toggleEditor(enabled) {
1587
1867
  const wysiwyg = this.editor.frameContext.get('wysiwyg');
1588
- wysiwyg.setAttribute('contenteditable', enabled);
1589
- if (enabled) domUtils.removeClass(wysiwyg, 'se-disabled');
1590
- else domUtils.addClass(wysiwyg, 'se-disabled');
1591
- },
1868
+ if (enabled) dom.utils.removeClass(wysiwyg, 'se-disabled');
1869
+ else dom.utils.addClass(wysiwyg, 'se-disabled');
1870
+ }
1592
1871
 
1872
+ /**
1873
+ * @private
1874
+ * @description Updates control properties.
1875
+ * @param {string} type The type of control property.
1876
+ */
1593
1877
  _setCtrlProps(type) {
1594
1878
  this._typeCache = type;
1595
1879
  const isTable = type === 'table';
1596
1880
  const targets = isTable ? [this._element] : this._selectedCells;
1597
1881
  if (!targets || targets.length === 0) return;
1598
1882
 
1599
- const { border_format, border_color, border_style, border_width, back_color, font_color, cell_alignment, cell_alignment_vertical, font_bold, font_underline, font_italic, font_strike } = this.propTargets;
1883
+ const { border_format, border_color, border_style, border_width, back_color, font_color, cell_alignment, cell_alignment_vertical, cell_alignment_table_text, font_bold, font_underline, font_italic, font_strike } = this.propTargets;
1600
1884
  const { border, backgroundColor, color, textAlign, verticalAlign, fontWeight, textDecoration, fontStyle } = _w.getComputedStyle(targets[0]);
1601
1885
  const cellBorder = this._getBorderStyle(border);
1602
1886
 
1603
- cell_alignment.querySelector('[data-value="justify"]').style.display = isTable ? 'none' : '';
1887
+ /** @type {HTMLElement} */ (cell_alignment.querySelector('[data-value="justify"]')).style.display = isTable ? 'none' : '';
1888
+ cell_alignment_table_text.style.display = isTable ? '' : 'none';
1604
1889
  if (isTable) cell_alignment_vertical.style.display = 'none';
1605
1890
  else cell_alignment_vertical.style.display = '';
1606
1891
 
@@ -1632,7 +1917,7 @@ Table.prototype = {
1632
1917
  if (fontColor !== converter.rgb2hex(color)) fontColor = '';
1633
1918
  if (align !== (isTable ? this._figure?.style.float : textAlign)) align = '';
1634
1919
  if (align_v && align_v !== verticalAlign) align_v = '';
1635
- if (bold && bold !== /.+/.test(fontWeight)) bold = '';
1920
+ if (bold && bold !== /.+/.test(fontWeight)) bold = false;
1636
1921
  if (underline && underline !== /underline/i.test(textDecoration)) underline = false;
1637
1922
  if (strike && strike !== /line-through/i.test(textDecoration)) strike = false;
1638
1923
  if (italic && italic !== /italic/i.test(fontStyle)) italic = false;
@@ -1644,7 +1929,7 @@ Table.prototype = {
1644
1929
  // border - format
1645
1930
  border_format.firstElementChild.innerHTML = this.icons[BORDER_FORMATS[targets.length === 1 ? 'outside' : 'all']];
1646
1931
  border_format.setAttribute('se-border-format', 'all');
1647
- domUtils.removeClass(border_format, 'active');
1932
+ dom.utils.removeClass(border_format, 'active');
1648
1933
 
1649
1934
  // border - styles
1650
1935
  b_style = b_style || BORDER_LIST[0];
@@ -1658,43 +1943,64 @@ Table.prototype = {
1658
1943
  font_color.value = font_color.style.borderColor = fontColor;
1659
1944
 
1660
1945
  // font style
1661
- if (bold) domUtils.addClass(font_bold, 'on');
1662
- if (underline) domUtils.addClass(font_underline, 'on');
1663
- if (strike) domUtils.addClass(font_strike, 'on');
1664
- if (italic) domUtils.addClass(font_italic, 'on');
1946
+ if (bold) dom.utils.addClass(font_bold, 'on');
1947
+ if (underline) dom.utils.addClass(font_underline, 'on');
1948
+ if (strike) dom.utils.addClass(font_strike, 'on');
1949
+ if (italic) dom.utils.addClass(font_italic, 'on');
1665
1950
 
1666
1951
  // align
1667
1952
  this._setAlignProps(cell_alignment, (this._propsAlignCache = align), true);
1668
1953
  this._setAlignProps(cell_alignment_vertical, (this._propsVerticalAlignCache = align_v), true);
1669
- },
1954
+ }
1670
1955
 
1956
+ /**
1957
+ * @private
1958
+ * @description Sets text alignment properties.
1959
+ * @param {Element} el The element to apply alignment to.
1960
+ * @param {string} align The alignment value.
1961
+ * @param {boolean} reset Whether to reset the alignment.
1962
+ */
1671
1963
  _setAlignProps(el, align, reset) {
1672
- domUtils.removeClass(el.querySelectorAll('button'), 'on');
1964
+ dom.utils.removeClass(el.querySelectorAll('button'), 'on');
1673
1965
 
1674
1966
  if (!reset && el.getAttribute('se-cell-align') === align) {
1675
1967
  el.setAttribute('se-cell-align', '');
1676
1968
  return;
1677
1969
  }
1678
1970
 
1679
- domUtils.addClass(el.querySelector(`[data-value="${align}"]`), 'on');
1971
+ dom.utils.addClass(el.querySelector(`[data-value="${align}"]`), 'on');
1680
1972
  el.setAttribute('se-cell-align', align);
1681
- },
1973
+ }
1682
1974
 
1975
+ /**
1976
+ * @private
1977
+ * @description Disables or enables border properties.
1978
+ * @param {boolean} disabled Whether to disable or enable border properties.
1979
+ */
1683
1980
  _disableBorderProps(disabled) {
1684
1981
  const { border_color, border_width, palette_border_button } = this.propTargets;
1685
1982
  if (disabled) {
1686
- border_color.setAttribute('disabled', true);
1687
- border_width.setAttribute('disabled', true);
1688
- palette_border_button.setAttribute('disabled', true);
1689
- border_width.setAttribute('disabled', true);
1983
+ border_color.disabled = true;
1984
+ border_width.disabled = true;
1985
+ palette_border_button.disabled = true;
1986
+ border_width.disabled = true;
1690
1987
  } else {
1691
- border_color.removeAttribute('disabled');
1692
- border_width.removeAttribute('disabled');
1693
- palette_border_button.removeAttribute('disabled');
1694
- border_width.removeAttribute('disabled');
1988
+ border_color.disabled = false;
1989
+ border_width.disabled = false;
1990
+ palette_border_button.disabled = false;
1991
+ border_width.disabled = false;
1695
1992
  }
1696
- },
1993
+ }
1697
1994
 
1995
+ /**
1996
+ * @private
1997
+ * @description Gets the border style.
1998
+ * @param {string} borderStyle The border style string.
1999
+ * @returns {{w: string, s: string, c: string}} The parsed border style object.
2000
+ * - w: The border width.
2001
+ * - s: The border style.
2002
+ * - c: The border color.
2003
+ */
1698
2004
  _getBorderStyle(borderStyle) {
1699
2005
  const parts = borderStyle.split(/\s(?![^()]*\))/);
1700
2006
  let w = '',
@@ -1722,15 +2028,20 @@ Table.prototype = {
1722
2028
  }
1723
2029
 
1724
2030
  return { w, s, c: converter.rgb2hex(c) };
1725
- },
2031
+ }
1726
2032
 
2033
+ /**
2034
+ * @private
2035
+ * @description Applies properties to table cells.
2036
+ * @param {HTMLButtonElement} target The target element.
2037
+ */
1727
2038
  _submitProps(target) {
1728
2039
  try {
1729
- target.setAttribute('disabled', true);
2040
+ target.disabled = true;
1730
2041
 
1731
2042
  const isTable = this.controller_table.form.contains(this.controller_props.currentTarget);
1732
2043
  const targets = isTable ? [this._element] : this._selectedCells;
1733
- const tr = targets[0];
2044
+ const tr = /** @type {HTMLTableCellElement} */ (targets[0]);
1734
2045
  const trStyles = _w.getComputedStyle(tr);
1735
2046
  const { border_format, border_color, border_style, border_width, back_color, font_color, cell_alignment, cell_alignment_vertical } = this.propTargets;
1736
2047
 
@@ -1753,14 +2064,16 @@ Table.prototype = {
1753
2064
  top: [],
1754
2065
  right: [],
1755
2066
  bottom: [],
1756
- middle: []
2067
+ middle: [],
2068
+ all: null
1757
2069
  };
1758
2070
 
1759
2071
  if (!isTable) {
2072
+ const trRow = /** @type {HTMLTableRowElement} */ (tr.parentElement);
1760
2073
  // --- target cells roof
1761
2074
  let { rs, re, cs, ce } = this._ref || {
1762
- rs: tr.parentElement.rowIndex || 0,
1763
- re: tr.parentElement.rowIndex || 0,
2075
+ rs: trRow.rowIndex || 0,
2076
+ re: trRow.rowIndex || 0,
1764
2077
  cs: tr.cellIndex || 0,
1765
2078
  ce: tr.cellIndex || 0
1766
2079
  };
@@ -1770,17 +2083,17 @@ Table.prototype = {
1770
2083
  rs -= rs;
1771
2084
  ce -= cs;
1772
2085
  cs -= cs;
1773
- let prevRow = tr.parentNode;
2086
+ let prevRow = /** @type {HTMLElement} */ (trRow);
1774
2087
  for (let i = 0, cellCnt = 0, len = targets.length, e, es, rowIndex = 0, cellIndex, colspan, rowspan; i < len; i++, cellCnt++) {
1775
- e = targets[i];
2088
+ e = /** @type {HTMLTableCellElement} */ (targets[i]);
1776
2089
  colspan = e.colSpan;
1777
2090
  rowspan = e.rowSpan;
1778
2091
  cellIndex = e.cellIndex - cellStartIndex;
1779
2092
 
1780
- if (prevRow !== e.parentNode) {
2093
+ if (prevRow !== e.parentElement) {
1781
2094
  rowIndex++;
1782
2095
  cellCnt = 0;
1783
- prevRow = e.parentNode;
2096
+ prevRow = e.parentElement;
1784
2097
  }
1785
2098
 
1786
2099
  let c = 0;
@@ -1874,83 +2187,93 @@ Table.prototype = {
1874
2187
  if (this._tdElement) {
1875
2188
  this._recallStyleSelectedCells();
1876
2189
  this.setCellInfo(this._tdElement, true);
1877
- domUtils.addClass(this._tdElement, 'se-selected-cell-focus');
2190
+ dom.utils.addClass(this._tdElement, 'se-selected-cell-focus');
1878
2191
  }
1879
2192
  } catch (err) {
1880
2193
  console.warn('[SUNEDITOR.plugins.table.setProps.error]', err);
1881
2194
  } finally {
1882
- target.removeAttribute('disabled');
2195
+ target.disabled = false;
1883
2196
  }
1884
- },
2197
+ }
1885
2198
 
2199
+ /**
2200
+ * @private
2201
+ * @description Sets font styles.
2202
+ * @param {CSSStyleDeclaration} styles The style object to modify.
2203
+ */
1886
2204
  _setFontStyle(styles) {
1887
2205
  const { font_bold, font_italic, font_strike, font_underline } = this.propTargets;
1888
- styles.fontWeight = domUtils.hasClass(font_bold, 'on') ? 'bold' : '';
1889
- styles.fontStyle = domUtils.hasClass(font_italic, 'on') ? 'italic' : '';
1890
- styles.textDecoration = ((domUtils.hasClass(font_strike, 'on') ? 'line-through ' : '') + (domUtils.hasClass(font_underline, 'on') ? 'underline' : '')).trim();
1891
- },
2206
+ styles.fontWeight = dom.utils.hasClass(font_bold, 'on') ? 'bold' : '';
2207
+ styles.fontStyle = dom.utils.hasClass(font_italic, 'on') ? 'italic' : '';
2208
+ styles.textDecoration = ((dom.utils.hasClass(font_strike, 'on') ? 'line-through ' : '') + (dom.utils.hasClass(font_underline, 'on') ? 'underline' : '')).trim();
2209
+ }
1892
2210
 
1893
2211
  /**
1894
2212
  * @private
1895
- * @description Set border format
1896
- * @param {Element[]} cells Target elements
1897
- * @param {"all"|"inside"|"horizon"|"vertical"|"outside"|"left"|"top"|"right"|"bottom"} borderKey Border style
1898
- * @param {number} s Border style
1899
- * @param {boolean} isTable table selected
2213
+ * @description Sets border format and styles.
2214
+ * @param {{left: Node[], top: Node[], right: Node[], bottom: Node[], all: Node[]}} cells The table cells categorized by border positions.
2215
+ * @param {string} borderKey Border style ("all"|"inside"|"horizon"|"vertical"|"outside"|"left"|"top"|"right"|"bottom")
2216
+ * @param {string} s The border style value.
1900
2217
  */
1901
2218
  _setBorderStyles(cells, borderKey, s) {
1902
2219
  const { left, top, right, bottom, all } = cells;
1903
2220
  switch (borderKey) {
1904
2221
  case 'inside':
1905
- if (cells.length === 1) return;
1906
- domUtils.setStyle(
2222
+ if (all.length === 1) return;
2223
+ dom.utils.setStyle(
1907
2224
  all.filter((c) => !bottom.includes(c)),
1908
2225
  BORDER_NS.b,
1909
2226
  s
1910
2227
  );
1911
- domUtils.setStyle(
2228
+ dom.utils.setStyle(
1912
2229
  all.filter((c) => !right.includes(c)),
1913
2230
  BORDER_NS.r,
1914
2231
  s
1915
2232
  );
1916
2233
  break;
1917
2234
  case 'horizon':
1918
- if (cells.length === 1) return;
1919
- domUtils.setStyle(
2235
+ if (all.length === 1) return;
2236
+ dom.utils.setStyle(
1920
2237
  all.filter((c) => !bottom.includes(c)),
1921
2238
  BORDER_NS.b,
1922
2239
  s
1923
2240
  );
1924
2241
  break;
1925
2242
  case 'vertical':
1926
- if (cells.length === 1) return;
1927
- domUtils.setStyle(
2243
+ if (all.length === 1) return;
2244
+ dom.utils.setStyle(
1928
2245
  all.filter((c) => !right.includes(c)),
1929
2246
  BORDER_NS.r,
1930
2247
  s
1931
2248
  );
1932
2249
  break;
1933
2250
  case 'outside':
1934
- domUtils.setStyle(left, BORDER_NS.l, s);
1935
- domUtils.setStyle(top, BORDER_NS.t, s);
1936
- domUtils.setStyle(right, BORDER_NS.r, s);
1937
- domUtils.setStyle(bottom, BORDER_NS.b, s);
2251
+ dom.utils.setStyle(left, BORDER_NS.l, s);
2252
+ dom.utils.setStyle(top, BORDER_NS.t, s);
2253
+ dom.utils.setStyle(right, BORDER_NS.r, s);
2254
+ dom.utils.setStyle(bottom, BORDER_NS.b, s);
1938
2255
  break;
1939
2256
  case 'left':
1940
- domUtils.setStyle(left, BORDER_NS.l, s);
2257
+ dom.utils.setStyle(left, BORDER_NS.l, s);
1941
2258
  break;
1942
2259
  case 'top':
1943
- domUtils.setStyle(top, BORDER_NS.t, s);
2260
+ dom.utils.setStyle(top, BORDER_NS.t, s);
1944
2261
  break;
1945
2262
  case 'right':
1946
- domUtils.setStyle(right, BORDER_NS.r, s);
2263
+ dom.utils.setStyle(right, BORDER_NS.r, s);
1947
2264
  break;
1948
2265
  case 'bottom':
1949
- domUtils.setStyle(bottom, BORDER_NS.b, s);
2266
+ dom.utils.setStyle(bottom, BORDER_NS.b, s);
1950
2267
  break;
1951
2268
  }
1952
- },
2269
+ }
1953
2270
 
2271
+ /**
2272
+ * @private
2273
+ * @description Selects multiple table cells and applies selection styles.
2274
+ * @param {Node} startCell The first cell in the selection.
2275
+ * @param {Node} endCell The last cell in the selection.
2276
+ */
1954
2277
  _setMultiCells(startCell, endCell) {
1955
2278
  const rows = this._selectedTable.rows;
1956
2279
  this._deleteStyleSelectedCells();
@@ -1958,7 +2281,7 @@ Table.prototype = {
1958
2281
  if (startCell === endCell) {
1959
2282
  if (!this._shift) return;
1960
2283
  } else {
1961
- domUtils.addClass(startCell, 'se-selected-table-cell');
2284
+ dom.utils.addClass(startCell, 'se-selected-table-cell');
1962
2285
  }
1963
2286
 
1964
2287
  let findSelectedCell = true;
@@ -2034,7 +2357,7 @@ Table.prototype = {
2034
2357
  break;
2035
2358
  }
2036
2359
 
2037
- domUtils.addClass(cell, 'se-selected-table-cell');
2360
+ dom.utils.addClass(cell, 'se-selected-table-cell');
2038
2361
  }
2039
2362
 
2040
2363
  if (rs > 0) {
@@ -2054,8 +2377,12 @@ Table.prototype = {
2054
2377
  });
2055
2378
  rowSpanArr = [];
2056
2379
  }
2057
- },
2380
+ }
2058
2381
 
2382
+ /**
2383
+ * @private
2384
+ * @description Resets the table picker display.
2385
+ */
2059
2386
  _resetTablePicker() {
2060
2387
  if (!this.tableHighlight) return;
2061
2388
 
@@ -2067,10 +2394,14 @@ Table.prototype = {
2067
2394
  unHighlight.width = '10em';
2068
2395
  unHighlight.height = '10em';
2069
2396
 
2070
- domUtils.changeTxt(this.tableDisplay, '1 x 1');
2397
+ dom.utils.changeTxt(this.tableDisplay, '1 x 1');
2071
2398
  this.menu.dropdownOff();
2072
- },
2399
+ }
2073
2400
 
2401
+ /**
2402
+ * @private
2403
+ * @description Resets the alignment properties for table cells.
2404
+ */
2074
2405
  _resetPropsAlign() {
2075
2406
  const { cell_alignment } = this.propTargets;
2076
2407
  const left = cell_alignment.querySelector('[data-value="left"]');
@@ -2079,35 +2410,54 @@ Table.prototype = {
2079
2410
  const r_parent = right.parentElement;
2080
2411
  l_parent.appendChild(right);
2081
2412
  r_parent.appendChild(left);
2082
- },
2413
+ }
2083
2414
 
2415
+ /**
2416
+ * @private
2417
+ * @description Handles color selection from the color palette.
2418
+ * @param {Node} button The button triggering the color palette.
2419
+ * @param {string} type The type of color selection.
2420
+ * @param {HTMLInputElement} color Color text input element.
2421
+ */
2084
2422
  _onColorPalette(button, type, color) {
2085
2423
  if (this.controller_colorPicker.isOpen && type === this.sliderType) {
2086
2424
  this.controller_colorPicker.close();
2087
2425
  } else {
2088
2426
  this.sliderType = type;
2089
- domUtils.addClass(button, 'on');
2427
+ dom.utils.addClass(button, 'on');
2090
2428
  this.colorPicker.init(color?.value || '', button);
2091
2429
  this.controller_colorPicker.open(button, null, { isWWTarget: false, initMethod: null, addOffset: null });
2092
2430
  }
2093
- },
2431
+ }
2094
2432
 
2433
+ /**
2434
+ * @private
2435
+ * @description Closes table-related controllers.
2436
+ */
2095
2437
  _closeController() {
2096
2438
  this.component.deselect();
2097
2439
  this.controller_table.close();
2098
2440
  this.controller_cell.close();
2099
- },
2441
+ }
2100
2442
 
2443
+ /**
2444
+ * @private
2445
+ * @description Hides the resize line if it is visible.
2446
+ */
2101
2447
  __hideResizeLine() {
2102
2448
  if (this._resizeLine) {
2103
2449
  this._resizeLine.style.display = 'none';
2104
2450
  this._resizeLine = null;
2105
2451
  }
2106
- },
2452
+ }
2107
2453
 
2454
+ /**
2455
+ * @private
2456
+ * @description Removes global event listeners and resets resize-related properties.
2457
+ */
2108
2458
  __removeGlobalEvents() {
2109
2459
  this._resizing = false;
2110
- this.editor.disableBackWrapper();
2460
+ this.ui.disableBackWrapper();
2111
2461
  this.__hideResizeLine();
2112
2462
  if (this._resizeLinePrev) {
2113
2463
  this._resizeLinePrev.style.display = 'none';
@@ -2117,372 +2467,457 @@ Table.prototype = {
2117
2467
  for (const k in globalEvents) {
2118
2468
  if (globalEvents[k]) globalEvents[k] = this.eventManager.removeGlobalEvent(globalEvents[k]);
2119
2469
  }
2120
- },
2121
-
2122
- constructor: Table
2123
- };
2124
-
2125
- function IsResizeEls(node) {
2126
- return /^(TD|TH|TR)$/i.test(node?.nodeName);
2127
- }
2128
-
2129
- function CheckCellEdge(event, tableCell) {
2130
- const startX = event.clientX;
2131
- const startWidth = numbers.get(_w.getComputedStyle(tableCell).width, CELL_DECIMAL_END);
2132
- const rect = tableCell.getBoundingClientRect();
2133
- const offsetX = Math.round(startX - rect.left);
2134
- const isLeft = offsetX <= CELL_SELECT_MARGIN;
2135
- const is = isLeft || startWidth - offsetX <= CELL_SELECT_MARGIN;
2136
-
2137
- return {
2138
- is,
2139
- isLeft,
2140
- startX
2141
- };
2142
- }
2143
-
2144
- function CheckRowEdge(event, tableCell) {
2145
- const startY = event.clientY;
2146
- const startHeight = numbers.get(_w.getComputedStyle(tableCell).height, CELL_DECIMAL_END);
2147
- const rect = tableCell.getBoundingClientRect();
2148
- const is = Math.ceil(startHeight + rect.top - startY) <= ROW_SELECT_MARGIN;
2149
-
2150
- return {
2151
- is,
2152
- startY
2153
- };
2154
- }
2470
+ }
2155
2471
 
2156
- function OnSplitCells(direction) {
2157
- const vertical = direction === 'vertical';
2158
- const currentCell = this._tdElement;
2159
- const rows = this._trElements;
2160
- const currentRow = this._trElement;
2161
- const index = this._logical_cellIndex;
2162
- const rowIndex = this._rowIndex;
2163
- const newCell = CreateCells(currentCell.nodeName, 0, true);
2164
-
2165
- // vertical
2166
- if (vertical) {
2167
- const currentColSpan = currentCell.colSpan;
2168
- newCell.rowSpan = currentCell.rowSpan;
2169
-
2170
- // colspan > 1
2171
- if (currentColSpan > 1) {
2172
- newCell.colSpan = Math.floor(currentColSpan / 2);
2173
- currentCell.colSpan = currentColSpan - newCell.colSpan;
2174
- currentRow.insertBefore(newCell, currentCell.nextElementSibling);
2175
- } else {
2176
- // colspan - 1
2177
- let rowSpanArr = [];
2178
- let spanIndex = [];
2472
+ /**
2473
+ * @description Splits a table cell either vertically or horizontally.
2474
+ * @param {"vertical"|"horizontal"} direction The direction to split the cell.
2475
+ */
2476
+ #OnSplitCells(direction) {
2477
+ const vertical = direction === 'vertical';
2478
+ const currentCell = this._tdElement;
2479
+ const rows = this._trElements;
2480
+ const currentRow = this._trElement;
2481
+ const index = this._logical_cellIndex;
2482
+ const rowIndex = this._rowIndex;
2483
+ const newCell = CreateCellsHTML(currentCell.nodeName);
2484
+
2485
+ // vertical
2486
+ if (vertical) {
2487
+ const currentColSpan = currentCell.colSpan;
2488
+ newCell.rowSpan = currentCell.rowSpan;
2179
2489
 
2180
- for (let i = 0, len = this._rowCnt, cells, colSpan; i < len; i++) {
2181
- cells = rows[i].cells;
2182
- colSpan = 0;
2183
- for (let c = 0, cLen = cells.length, cell, cs, rs, logcalIndex; c < cLen; c++) {
2184
- cell = cells[c];
2185
- cs = cell.colSpan - 1;
2186
- rs = cell.rowSpan - 1;
2187
- logcalIndex = c + colSpan;
2490
+ // colspan > 1
2491
+ if (currentColSpan > 1) {
2492
+ newCell.colSpan = Math.floor(currentColSpan / 2);
2493
+ currentCell.colSpan = currentColSpan - newCell.colSpan;
2494
+ currentRow.insertBefore(newCell, currentCell.nextElementSibling);
2495
+ } else {
2496
+ // colspan - 1
2497
+ let rowSpanArr = [];
2498
+ let spanIndex = [];
2188
2499
 
2189
- if (spanIndex.length > 0) {
2190
- for (let r = 0, arr; r < spanIndex.length; r++) {
2191
- arr = spanIndex[r];
2192
- if (arr.row > i) continue;
2193
- if (logcalIndex >= arr.index) {
2194
- colSpan += arr.cs;
2195
- logcalIndex += arr.cs;
2196
- arr.rs -= 1;
2197
- arr.row = i + 1;
2198
- if (arr.rs < 1) {
2199
- spanIndex.splice(r, 1);
2200
- r--;
2201
- }
2202
- } else if (c === cLen - 1) {
2203
- arr.rs -= 1;
2204
- arr.row = i + 1;
2205
- if (arr.rs < 1) {
2206
- spanIndex.splice(r, 1);
2207
- r--;
2500
+ for (let i = 0, len = this._rowCnt, cells, colSpan; i < len; i++) {
2501
+ cells = rows[i].cells;
2502
+ colSpan = 0;
2503
+ for (let c = 0, cLen = cells.length, cell, cs, rs, logcalIndex; c < cLen; c++) {
2504
+ cell = cells[c];
2505
+ cs = cell.colSpan - 1;
2506
+ rs = cell.rowSpan - 1;
2507
+ logcalIndex = c + colSpan;
2508
+
2509
+ if (spanIndex.length > 0) {
2510
+ for (let r = 0, arr; r < spanIndex.length; r++) {
2511
+ arr = spanIndex[r];
2512
+ if (arr.row > i) continue;
2513
+ if (logcalIndex >= arr.index) {
2514
+ colSpan += arr.cs;
2515
+ logcalIndex += arr.cs;
2516
+ arr.rs -= 1;
2517
+ arr.row = i + 1;
2518
+ if (arr.rs < 1) {
2519
+ spanIndex.splice(r, 1);
2520
+ r--;
2521
+ }
2522
+ } else if (c === cLen - 1) {
2523
+ arr.rs -= 1;
2524
+ arr.row = i + 1;
2525
+ if (arr.rs < 1) {
2526
+ spanIndex.splice(r, 1);
2527
+ r--;
2528
+ }
2208
2529
  }
2209
2530
  }
2210
2531
  }
2211
- }
2212
2532
 
2213
- if (logcalIndex <= index && rs > 0) {
2214
- rowSpanArr.push({
2215
- index: logcalIndex,
2216
- cs: cs + 1,
2217
- rs: rs,
2218
- row: -1
2219
- });
2220
- }
2533
+ if (logcalIndex <= index && rs > 0) {
2534
+ rowSpanArr.push({
2535
+ index: logcalIndex,
2536
+ cs: cs + 1,
2537
+ rs: rs,
2538
+ row: -1
2539
+ });
2540
+ }
2221
2541
 
2222
- if (cell !== currentCell && logcalIndex <= index && logcalIndex + cs >= index + currentColSpan - 1) {
2223
- cell.colSpan += 1;
2224
- break;
2225
- }
2542
+ if (cell !== currentCell && logcalIndex <= index && logcalIndex + cs >= index + currentColSpan - 1) {
2543
+ cell.colSpan += 1;
2544
+ break;
2545
+ }
2226
2546
 
2227
- if (logcalIndex > index) break;
2547
+ if (logcalIndex > index) break;
2228
2548
 
2229
- colSpan += cs;
2549
+ colSpan += cs;
2550
+ }
2551
+
2552
+ spanIndex = spanIndex.concat(rowSpanArr).sort(function (a, b) {
2553
+ return a.index - b.index;
2554
+ });
2555
+ rowSpanArr = [];
2230
2556
  }
2231
2557
 
2232
- spanIndex = spanIndex.concat(rowSpanArr).sort(function (a, b) {
2233
- return a.index - b.index;
2234
- });
2235
- rowSpanArr = [];
2558
+ currentRow.insertBefore(newCell, currentCell.nextElementSibling);
2236
2559
  }
2560
+ } else {
2561
+ // horizontal
2562
+ const currentRowSpan = currentCell.rowSpan;
2563
+ newCell.colSpan = currentCell.colSpan;
2237
2564
 
2238
- currentRow.insertBefore(newCell, currentCell.nextElementSibling);
2239
- }
2240
- } else {
2241
- // horizontal
2242
- const currentRowSpan = currentCell.rowSpan;
2243
- newCell.colSpan = currentCell.colSpan;
2565
+ // rowspan > 1
2566
+ if (currentRowSpan > 1) {
2567
+ newCell.rowSpan = Math.floor(currentRowSpan / 2);
2568
+ const newRowSpan = currentRowSpan - newCell.rowSpan;
2569
+
2570
+ const rowSpanArr = [];
2571
+ const nextRowIndex = dom.utils.getArrayIndex(rows, currentRow) + newRowSpan;
2244
2572
 
2245
- // rowspan > 1
2246
- if (currentRowSpan > 1) {
2247
- newCell.rowSpan = Math.floor(currentRowSpan / 2);
2248
- const newRowSpan = currentRowSpan - newCell.rowSpan;
2573
+ for (let i = 0, cells, colSpan; i < nextRowIndex; i++) {
2574
+ cells = rows[i].cells;
2575
+ colSpan = 0;
2576
+ for (let c = 0, cLen = cells.length, cell, cs, logcalIndex; c < cLen; c++) {
2577
+ logcalIndex = c + colSpan;
2578
+ if (logcalIndex >= index) break;
2579
+
2580
+ cell = cells[c];
2581
+ cs = cell.rowSpan - 1;
2582
+ if (cs > 0 && cs + i >= nextRowIndex && logcalIndex < index) {
2583
+ rowSpanArr.push({
2584
+ index: logcalIndex,
2585
+ cs: cell.colSpan
2586
+ });
2587
+ }
2588
+ colSpan += cell.colSpan - 1;
2589
+ }
2590
+ }
2249
2591
 
2250
- const rowSpanArr = [];
2251
- const nextRowIndex = domUtils.getArrayIndex(rows, currentRow) + newRowSpan;
2592
+ const nextRow = rows[nextRowIndex];
2593
+ const nextCells = nextRow.cells;
2594
+ let rs = rowSpanArr.shift();
2252
2595
 
2253
- for (let i = 0, cells, colSpan; i < nextRowIndex; i++) {
2254
- cells = rows[i].cells;
2255
- colSpan = 0;
2256
- for (let c = 0, cLen = cells.length, cell, cs, logcalIndex; c < cLen; c++) {
2596
+ for (let c = 0, cLen = nextCells.length, colSpan = 0, cell, cs, logcalIndex, insertIndex; c < cLen; c++) {
2257
2597
  logcalIndex = c + colSpan;
2258
- if (logcalIndex >= index) break;
2598
+ cell = nextCells[c];
2599
+ cs = cell.colSpan - 1;
2600
+ insertIndex = logcalIndex + cs + 1;
2259
2601
 
2260
- cell = cells[c];
2261
- cs = cell.rowSpan - 1;
2262
- if (cs > 0 && cs + i >= nextRowIndex && logcalIndex < index) {
2263
- rowSpanArr.push({
2264
- index: logcalIndex,
2265
- cs: cell.colSpan
2266
- });
2602
+ if (rs && insertIndex >= rs.index) {
2603
+ colSpan += rs.cs;
2604
+ insertIndex += rs.cs;
2605
+ rs = rowSpanArr.shift();
2267
2606
  }
2268
- colSpan += cell.colSpan - 1;
2269
- }
2270
- }
2271
-
2272
- const nextRow = rows[nextRowIndex];
2273
- const nextCells = nextRow.cells;
2274
- let rs = rowSpanArr.shift();
2275
2607
 
2276
- for (let c = 0, cLen = nextCells.length, colSpan = 0, cell, cs, logcalIndex, insertIndex; c < cLen; c++) {
2277
- logcalIndex = c + colSpan;
2278
- cell = nextCells[c];
2279
- cs = cell.colSpan - 1;
2280
- insertIndex = logcalIndex + cs + 1;
2608
+ if (insertIndex >= index || c === cLen - 1) {
2609
+ nextRow.insertBefore(newCell, cell.nextElementSibling);
2610
+ break;
2611
+ }
2281
2612
 
2282
- if (rs && insertIndex >= rs.index) {
2283
- colSpan += rs.cs;
2284
- insertIndex += rs.cs;
2285
- rs = rowSpanArr.shift();
2613
+ colSpan += cs;
2286
2614
  }
2287
2615
 
2288
- if (insertIndex >= index || c === cLen - 1) {
2289
- nextRow.insertBefore(newCell, cell.nextElementSibling);
2290
- break;
2616
+ currentCell.rowSpan = newRowSpan;
2617
+ } else {
2618
+ // rowspan - 1
2619
+ newCell.rowSpan = currentCell.rowSpan;
2620
+ const newRow = dom.utils.createElement('TR');
2621
+ newRow.appendChild(newCell);
2622
+
2623
+ for (let i = 0, cells; i < rowIndex; i++) {
2624
+ cells = rows[i].cells;
2625
+ if (cells.length === 0) return;
2626
+
2627
+ for (let c = 0, cLen = cells.length; c < cLen; c++) {
2628
+ if (i + cells[c].rowSpan - 1 >= rowIndex) {
2629
+ cells[c].rowSpan += 1;
2630
+ }
2631
+ }
2291
2632
  }
2292
2633
 
2293
- colSpan += cs;
2294
- }
2295
-
2296
- currentCell.rowSpan = newRowSpan;
2297
- } else {
2298
- // rowspan - 1
2299
- newCell.rowSpan = currentCell.rowSpan;
2300
- const newRow = domUtils.createElement('TR');
2301
- newRow.appendChild(newCell);
2302
-
2303
- for (let i = 0, cells; i < rowIndex; i++) {
2304
- cells = rows[i].cells;
2305
- if (cells.length === 0) return;
2634
+ const physicalIndex = this._physical_cellIndex;
2635
+ const cells = currentRow.cells;
2306
2636
 
2307
2637
  for (let c = 0, cLen = cells.length; c < cLen; c++) {
2308
- if (i + cells[c].rowSpan - 1 >= rowIndex) {
2309
- cells[c].rowSpan += 1;
2310
- }
2638
+ if (c === physicalIndex) continue;
2639
+ cells[c].rowSpan += 1;
2311
2640
  }
2641
+
2642
+ currentRow.parentNode.insertBefore(newRow, currentRow.nextElementSibling);
2312
2643
  }
2644
+ }
2313
2645
 
2314
- const physicalIndex = this._physical_cellIndex;
2315
- const cells = currentRow.cells;
2646
+ this.selectMenu_split.close();
2647
+ this.editor.focusEdge(currentCell);
2316
2648
 
2317
- for (let c = 0, cLen = cells.length; c < cLen; c++) {
2318
- if (c === physicalIndex) continue;
2319
- cells[c].rowSpan += 1;
2320
- }
2649
+ this._deleteStyleSelectedCells();
2650
+ this.history.push(false);
2321
2651
 
2322
- currentRow.parentNode.insertBefore(newRow, currentRow.nextElementSibling);
2323
- }
2652
+ this._setController(currentCell);
2653
+ this._selectedCell = this._fixedCell = currentCell;
2324
2654
  }
2325
2655
 
2326
- this.selectMenu_split.close();
2327
- this.editor.focusEdge(currentCell);
2656
+ /**
2657
+ * @description Handles column operations such as insert and delete.
2658
+ * @param {"insert-left"|"insert-right"|"delete"} command The column operation to perform.
2659
+ */
2660
+ #OnColumnEdit(command) {
2661
+ switch (command) {
2662
+ case 'insert-left':
2663
+ this.editTable('cell', 'left');
2664
+ break;
2665
+ case 'insert-right':
2666
+ this.editTable('cell', 'right');
2667
+ break;
2668
+ case 'delete':
2669
+ this.editTable('cell', null);
2670
+ }
2328
2671
 
2329
- this._deleteStyleSelectedCells();
2330
- this.history.push(false);
2672
+ this._historyPush();
2673
+ }
2331
2674
 
2332
- this.setController(currentCell);
2333
- this._selectedCell = this._fixedCell = currentCell;
2334
- }
2675
+ /**
2676
+ * @description Handles row operations such as insert and delete.
2677
+ * @param {"insert-above"|"insert-below"|"delete"} command The row operation to perform.
2678
+ */
2679
+ #OnRowEdit(command) {
2680
+ switch (command) {
2681
+ case 'insert-above':
2682
+ this.editTable('row', 'up');
2683
+ break;
2684
+ case 'insert-below':
2685
+ this.editTable('row', 'down');
2686
+ break;
2687
+ case 'delete':
2688
+ this.editTable('row', null);
2689
+ }
2335
2690
 
2336
- function OnColumnEdit(command) {
2337
- switch (command) {
2338
- case 'insert-left':
2339
- this.editTable('cell', 'left');
2340
- break;
2341
- case 'insert-right':
2342
- this.editTable('cell', 'right');
2343
- break;
2344
- case 'delete':
2345
- this.editTable('cell', null);
2691
+ this._historyPush();
2346
2692
  }
2347
2693
 
2348
- this._historyPush();
2349
- }
2694
+ /**
2695
+ * @description Handles mouse movement within the table picker.
2696
+ * @param {MouseEvent} e The mouse event.
2697
+ */
2698
+ #OnMouseMoveTablePicker(e) {
2699
+ e.stopPropagation();
2350
2700
 
2351
- function OnRowEdit(command) {
2352
- switch (command) {
2353
- case 'insert-above':
2354
- this.editTable('row', 'up');
2355
- break;
2356
- case 'insert-below':
2357
- this.editTable('row', 'down');
2358
- break;
2359
- case 'delete':
2360
- this.editTable('row', null);
2361
- }
2701
+ let x = Math.ceil(e.offsetX / 18);
2702
+ let y = Math.ceil(e.offsetY / 18);
2703
+ x = x < 1 ? 1 : x;
2704
+ y = y < 1 ? 1 : y;
2362
2705
 
2363
- this._historyPush();
2364
- }
2706
+ if (this.options.get('_rtl')) {
2707
+ this.tableHighlight.style.left = x * 18 - 13 + 'px';
2708
+ x = 11 - x;
2709
+ }
2365
2710
 
2366
- function OnMouseMoveTablePicker(e) {
2367
- e.stopPropagation();
2711
+ this.tableHighlight.style.width = x + 'em';
2712
+ this.tableHighlight.style.height = y + 'em';
2368
2713
 
2369
- let x = Math.ceil(e.offsetX / 18);
2370
- let y = Math.ceil(e.offsetY / 18);
2371
- x = x < 1 ? 1 : x;
2372
- y = y < 1 ? 1 : y;
2714
+ const x_u = x < 5 ? 5 : x > 8 ? 10 : x + 2;
2715
+ const y_u = y < 5 ? 5 : y > 8 ? 10 : y + 2;
2716
+ this.tableUnHighlight.style.width = x_u + 'em';
2717
+ this.tableUnHighlight.style.height = y_u + 'em';
2373
2718
 
2374
- if (this.options.get('_rtl')) {
2375
- this.tableHighlight.style.left = x * 18 - 13 + 'px';
2376
- x = 11 - x;
2719
+ dom.utils.changeTxt(this.tableDisplay, x + ' x ' + y);
2720
+ this._tableXY = [x, y];
2377
2721
  }
2378
2722
 
2379
- this.tableHighlight.style.width = x + 'em';
2380
- this.tableHighlight.style.height = y + 'em';
2381
-
2382
- const x_u = x < 5 ? 5 : x > 8 ? 10 : x + 2;
2383
- const y_u = y < 5 ? 5 : y > 8 ? 10 : y + 2;
2384
- this.tableUnHighlight.style.width = x_u + 'em';
2385
- this.tableUnHighlight.style.height = y_u + 'em';
2723
+ /**
2724
+ * @description Executes the selected action when the table picker is clicked.
2725
+ */
2726
+ #OnClickTablePicker() {
2727
+ this.action();
2728
+ }
2386
2729
 
2387
- domUtils.changeTxt(this.tableDisplay, x + ' x ' + y);
2388
- this._tableXY = [x, y];
2389
- }
2730
+ /**
2731
+ * @description Handles multi-selection of table cells.
2732
+ * @param {MouseEvent} e The mouse event.
2733
+ */
2734
+ #OnCellMultiSelect(e) {
2735
+ this.editor._preventBlur = true;
2736
+ const target = /** @type {HTMLTableCellElement} */ (dom.query.getParentElement(dom.query.getEventTarget(e), dom.check.isTableCell));
2390
2737
 
2391
- function OnClickTablePicker() {
2392
- this.action();
2393
- }
2738
+ if (this._shift) {
2739
+ if (target === this._fixedCell) {
2740
+ this._shift = false;
2741
+ this._deleteStyleSelectedCells();
2742
+ this._toggleEditor(true);
2743
+ this.__removeGlobalEvents();
2744
+ return;
2745
+ } else {
2746
+ this._toggleEditor(false);
2747
+ }
2748
+ } else if (!this._ref) {
2749
+ if (target === this._fixedCell) return;
2750
+ else this._toggleEditor(false);
2751
+ }
2394
2752
 
2395
- function CreateCells(nodeName, cnt, returnElement) {
2396
- nodeName = nodeName.toLowerCase();
2753
+ if (!target || target === this._selectedCell || this._fixedCellName !== target.nodeName || this._selectedTable !== dom.query.getParentElement(target, 'TABLE')) {
2754
+ return;
2755
+ }
2397
2756
 
2398
- if (!returnElement) {
2399
- return `<${nodeName}><div><br></div></${nodeName}>`.repeat(cnt);
2400
- } else {
2401
- return domUtils.createElement(nodeName, null, '<div><br></div>');
2757
+ this._selectedCell = target;
2758
+ this._setMultiCells(this._fixedCell, target);
2402
2759
  }
2403
- }
2404
2760
 
2405
- function OnCellMultiSelect(e) {
2406
- this.editor._antiBlur = true;
2407
- const target = domUtils.getParentElement(e.target, domUtils.isTableCell);
2761
+ /**
2762
+ * @description Stops multi-selection of table cells.
2763
+ * @param {MouseEvent} e The mouse event.
2764
+ */
2765
+ #OffCellMultiSelect(e) {
2766
+ e.stopPropagation();
2408
2767
 
2409
- if (this._shift) {
2410
- if (target === this._fixedCell) {
2411
- this._shift = false;
2412
- this._deleteStyleSelectedCells();
2413
- this._toggleEditor(true);
2768
+ if (!this._shift) {
2414
2769
  this.__removeGlobalEvents();
2415
- return;
2416
- } else {
2417
- this._toggleEditor(false);
2770
+ this._toggleEditor(true);
2771
+ } else if (this.__globalEvents.touchOff) {
2772
+ this.__globalEvents.touchOff = this.eventManager.removeGlobalEvent(this.__globalEvents.touchOff);
2418
2773
  }
2419
- } else if (!this._ref) {
2420
- if (target === this._fixedCell) return;
2421
- else this._toggleEditor(false);
2774
+
2775
+ if (!this._fixedCell || !this._selectedTable) return;
2776
+
2777
+ this._setMergeSplitButton(!!this._fixedCell, !!this._selectedCell);
2778
+ this._selectedCells = Array.from(this._selectedTable.querySelectorAll('.se-selected-table-cell'));
2779
+
2780
+ const focusCell = this._selectedCells?.length > 0 ? this._selectedCell : this._fixedCell;
2781
+ this._setController(focusCell);
2422
2782
  }
2423
2783
 
2424
- if (!target || target === this._selectedCell || this._fixedCellName !== target.nodeName || this._selectedTable !== domUtils.getParentElement(target, 'TABLE')) {
2425
- return;
2784
+ /**
2785
+ * @description Handles the removal of shift-based selection.
2786
+ */
2787
+ #OffCellShift() {
2788
+ if (!this._ref) this._closeController();
2426
2789
  }
2427
2790
 
2428
- this._selectedCell = target;
2429
- this._setMultiCells(this._fixedCell, target);
2791
+ /**
2792
+ * @description Handles the removal of touch-based selection.
2793
+ */
2794
+ #OffCellTouch() {
2795
+ this.close();
2796
+ }
2430
2797
  }
2431
2798
 
2432
- function OffCellMultiSelect(e) {
2433
- e.stopPropagation();
2799
+ /**
2800
+ * @private
2801
+ * @description Checks if the given node is a resizable table element.
2802
+ * @param {Node} node The DOM node to check.
2803
+ * @returns {boolean} True if the node is a table-related resizable element.
2804
+ */
2805
+ function IsResizeEls(node) {
2806
+ return /^(TD|TH|TR)$/i.test(node?.nodeName);
2807
+ }
2434
2808
 
2435
- if (!this._shift) {
2436
- this.__removeGlobalEvents();
2437
- this._toggleEditor(true);
2438
- } else if (this.__globalEvents.touchOff) {
2439
- this.__globalEvents.touchOff = this.eventManager.removeGlobalEvent(this.__globalEvents.touchOff);
2440
- }
2809
+ /**
2810
+ * @private
2811
+ * @description Checks if a table cell is at its edge based on the mouse event.
2812
+ * @param {MouseEvent} event The mouse event.
2813
+ * @param {Element} tableCell The table cell to check.
2814
+ * @returns {Object} An object containing edge detection details.
2815
+ */
2816
+ function CheckCellEdge(event, tableCell) {
2817
+ const startX = event.clientX;
2818
+ const startWidth = numbers.get(_w.getComputedStyle(tableCell).width, CELL_DECIMAL_END);
2819
+ const rect = tableCell.getBoundingClientRect();
2820
+ const offsetX = Math.round(startX - rect.left);
2821
+ const isLeft = offsetX <= CELL_SELECT_MARGIN;
2822
+ const is = isLeft || startWidth - offsetX <= CELL_SELECT_MARGIN;
2441
2823
 
2442
- if (!this._fixedCell || !this._selectedTable) return;
2824
+ return {
2825
+ is,
2826
+ isLeft,
2827
+ startX
2828
+ };
2829
+ }
2443
2830
 
2444
- this.setMergeSplitButton(this._fixedCell, this._selectedCell);
2445
- this._selectedCells = Array.from(this._selectedTable.querySelectorAll('.se-selected-table-cell'));
2831
+ /**
2832
+ * @private
2833
+ * @description Checks if a row is at its edge based on the mouse event.
2834
+ * @param {MouseEvent} event The mouse event.
2835
+ * @param {Element} tableCell The table row cell to check.
2836
+ * @returns {Object} An object containing row edge detection details.
2837
+ */
2838
+ function CheckRowEdge(event, tableCell) {
2839
+ const startY = event.clientY;
2840
+ const startHeight = numbers.get(_w.getComputedStyle(tableCell).height, CELL_DECIMAL_END);
2841
+ const rect = tableCell.getBoundingClientRect();
2842
+ const is = Math.ceil(startHeight + rect.top - startY) <= ROW_SELECT_MARGIN;
2446
2843
 
2447
- const focusCell = this._selectedCells?.length > 0 ? this._selectedCell : this._fixedCell;
2448
- this.setController(focusCell);
2844
+ return {
2845
+ is,
2846
+ startY
2847
+ };
2449
2848
  }
2450
2849
 
2451
- function OffCellShift() {
2452
- if (!this._ref) this._closeController();
2850
+ /**
2851
+ * @private
2852
+ * @description Creates table cells as elements strings.
2853
+ * @param {string} nodeName The tag name of the cell (TD or TH).
2854
+ * @param {number} cnt The number of cells to create.
2855
+ * @returns {string} The created cells.
2856
+ */
2857
+ function CreateCellsString(nodeName, cnt) {
2858
+ nodeName = nodeName.toLowerCase();
2859
+ return `<${nodeName}><div><br></div></${nodeName}>`.repeat(cnt);
2453
2860
  }
2454
2861
 
2455
- function OffCellTouch() {
2456
- this.close();
2862
+ /**
2863
+ * @private
2864
+ * @description Creates table cells as element HTML.
2865
+ * @param {string} nodeName The tag name of the cell (TD or TH).
2866
+ * @returns {HTMLTableCellElement} The created cells.
2867
+ */
2868
+ function CreateCellsHTML(nodeName) {
2869
+ nodeName = nodeName.toLowerCase();
2870
+ return /** @type {HTMLTableCellElement} */ (dom.utils.createElement(nodeName, null, '<div><br></div>'));
2457
2871
  }
2458
2872
 
2873
+ /**
2874
+ * @private
2875
+ * @description Gets the maximum number of columns in a table.
2876
+ * @param {HTMLTableElement} table The table element.
2877
+ * @returns {number} The maximum number of columns in the table.
2878
+ */
2459
2879
  function GetMaxColumns(table) {
2880
+ const rows = table.rows;
2460
2881
  let maxColumns = 0;
2461
2882
 
2462
- for (const row of table.rows) {
2883
+ for (let i = 0, len = rows.length; i < len; i++) {
2884
+ const cells = rows[i].cells;
2463
2885
  let columnCount = 0;
2464
- for (const cell of row.cells) {
2465
- columnCount += cell.colSpan;
2886
+
2887
+ for (let j = 0, jLen = cells.length; j < jLen; j++) {
2888
+ columnCount += cells[j].colSpan;
2466
2889
  }
2890
+
2467
2891
  maxColumns = Math.max(maxColumns, columnCount);
2468
2892
  }
2469
2893
 
2470
2894
  return maxColumns;
2471
2895
  }
2472
2896
 
2897
+ /**
2898
+ * @private
2899
+ * @description Handles border style changes in table properties.
2900
+ * @param {string} command The border style command.
2901
+ */
2473
2902
  function OnPropsBorderEdit(command) {
2474
2903
  this.propTargets.border_style.textContent = command;
2475
2904
  this._disableBorderProps(command === BORDER_LIST[0]);
2476
2905
  this.selectMenu_props_border.close();
2477
2906
  }
2478
2907
 
2908
+ /**
2909
+ * @private
2910
+ * @description Handles border format changes in table properties.
2911
+ * @param {string} defaultCommand The default border format command.
2912
+ * @param {string} command The new border format command.
2913
+ */
2479
2914
  function OnPropsBorderFormatEdit(defaultCommand, command) {
2480
2915
  const { border_format } = this.propTargets;
2481
2916
 
2482
2917
  border_format.setAttribute('se-border-format', command);
2483
2918
  border_format.firstElementChild.innerHTML = this.icons[BORDER_FORMATS[command]];
2484
- if (command !== defaultCommand) domUtils.addClass(border_format, 'active');
2485
- else domUtils.removeClass(border_format, 'active');
2919
+ if (command !== defaultCommand) dom.utils.addClass(border_format, 'active');
2920
+ else dom.utils.removeClass(border_format, 'active');
2486
2921
 
2487
2922
  this.selectMenu_props_border_format.close();
2488
2923
  this.selectMenu_props_border_format_oneCell.close();
@@ -2490,7 +2925,7 @@ function OnPropsBorderFormatEdit(defaultCommand, command) {
2490
2925
 
2491
2926
  // init element
2492
2927
  function CreateSplitMenu(lang) {
2493
- const menus = domUtils.createElement(
2928
+ const menus = dom.utils.createElement(
2494
2929
  'DIV',
2495
2930
  null,
2496
2931
  /*html*/ `
@@ -2506,7 +2941,7 @@ function CreateSplitMenu(lang) {
2506
2941
  }
2507
2942
 
2508
2943
  function CreateColumnMenu(lang, icons) {
2509
- const menus = domUtils.createElement(
2944
+ const menus = dom.utils.createElement(
2510
2945
  'DIV',
2511
2946
  null,
2512
2947
  /*html*/ `
@@ -2525,7 +2960,7 @@ function CreateColumnMenu(lang, icons) {
2525
2960
  }
2526
2961
 
2527
2962
  function CreateRowMenu(lang, icons) {
2528
- const menus = domUtils.createElement(
2963
+ const menus = dom.utils.createElement(
2529
2964
  'DIV',
2530
2965
  null,
2531
2966
  /*html*/ `
@@ -2554,7 +2989,7 @@ function CreateBorderMenu() {
2554
2989
  </div>`;
2555
2990
  }
2556
2991
 
2557
- const menus = domUtils.createElement('DIV', null, html);
2992
+ const menus = dom.utils.createElement('DIV', null, html);
2558
2993
  return { items: BORDER_LIST, menus: menus.querySelectorAll('div') };
2559
2994
  }
2560
2995
 
@@ -2575,7 +3010,7 @@ function CreateBorderFormatMenu(langs, icons, indideFormats) {
2575
3010
  </button>`;
2576
3011
  }
2577
3012
 
2578
- const menus = domUtils.createElement('DIV', null, html);
3013
+ const menus = dom.utils.createElement('DIV', null, html);
2579
3014
  return { items, menus: menus.querySelectorAll('button') };
2580
3015
  }
2581
3016
 
@@ -2588,7 +3023,7 @@ function CreateHTML() {
2588
3023
  </div>
2589
3024
  <div class="se-table-size-display">1 x 1</div>`;
2590
3025
 
2591
- return domUtils.createElement('DIV', { class: 'se-dropdown se-selector-table' }, html);
3026
+ return dom.utils.createElement('DIV', { class: 'se-dropdown se-selector-table' }, html);
2592
3027
  }
2593
3028
 
2594
3029
  function CreateHTML_controller_table({ lang, icons }) {
@@ -2633,9 +3068,13 @@ function CreateHTML_controller_table({ lang, icons }) {
2633
3068
  </button>
2634
3069
  </div>`;
2635
3070
 
2636
- return domUtils.createElement('DIV', { class: 'se-controller se-controller-table' }, html);
3071
+ return dom.utils.createElement('DIV', { class: 'se-controller se-controller-table' }, html);
2637
3072
  }
2638
3073
 
3074
+ /**
3075
+ * @param {__se__EditorCore} editor
3076
+ * @returns {{ html: HTMLElement, splitButton: HTMLButtonElement, columnButton: HTMLButtonElement, rowButton: HTMLButtonElement, mergeButton: HTMLButtonElement }}
3077
+ */
2639
3078
  function CreateHTML_controller_cell({ lang, icons }, cellControllerTop) {
2640
3079
  const html = /*html*/ `
2641
3080
  <div class="se-arrow se-arrow-${cellControllerTop ? 'down se-visible-hidden' : 'up'}"></div>
@@ -2672,9 +3111,44 @@ function CreateHTML_controller_cell({ lang, icons }, cellControllerTop) {
2672
3111
  </button>
2673
3112
  </div>`;
2674
3113
 
2675
- return domUtils.createElement('DIV', { class: 'se-controller se-controller-table-cell' }, html);
3114
+ const content = dom.utils.createElement('DIV', { class: 'se-controller se-controller-table-cell' }, html);
3115
+
3116
+ return {
3117
+ html: content,
3118
+ splitButton: content.querySelector('[data-command="onsplit"]'),
3119
+ columnButton: content.querySelector('[data-command="oncolumn"]'),
3120
+ rowButton: content.querySelector('[data-command="onrow"]'),
3121
+ mergeButton: content.querySelector('[data-command="merge"]')
3122
+ };
2676
3123
  }
2677
3124
 
3125
+ /**
3126
+
3127
+ */
3128
+
3129
+ /**
3130
+ * @typedef {Object} TableCtrlProps
3131
+ * @property {HTMLElement} html
3132
+ * @property {HTMLElement} controller_props_title
3133
+ * @property {HTMLButtonElement} borderButton
3134
+ * @property {HTMLButtonElement} borderFormatButton
3135
+ * @property {HTMLElement} cell_alignment
3136
+ * @property {HTMLElement} cell_alignment_vertical
3137
+ * @property {HTMLElement} cell_alignment_table_text
3138
+ * @property {HTMLButtonElement} border_style
3139
+ * @property {HTMLInputElement} border_color
3140
+ * @property {HTMLInputElement} border_width
3141
+ * @property {HTMLInputElement} back_color
3142
+ * @property {HTMLInputElement} font_color
3143
+ * @property {HTMLButtonElement} palette_border_button
3144
+ * @property {HTMLButtonElement} font_bold
3145
+ * @property {HTMLButtonElement} font_underline
3146
+ * @property {HTMLButtonElement} font_italic
3147
+ * @property {HTMLButtonElement} font_strike
3148
+ *
3149
+ * @param {__se__EditorCore} editor - Editor instance
3150
+ * @returns {TableCtrlProps}
3151
+ */
2678
3152
  function CreateHTML_controller_properties({ lang, icons, options }) {
2679
3153
  const alignItems = options.get('_rtl') ? ['right', 'center', 'left', 'justify'] : ['left', 'center', 'right', 'justify'];
2680
3154
  let alignHtml = '';
@@ -2682,14 +3156,12 @@ function CreateHTML_controller_properties({ lang, icons, options }) {
2682
3156
  item = alignItems[i];
2683
3157
  text = lang['align' + item.charAt(0).toUpperCase() + item.slice(1)];
2684
3158
  alignHtml += /*html*/ `
2685
- <li>
2686
- <button type="button" class="se-btn se-btn-list se-tooltip" data-command="props_align" data-value="${item}" title="${text}" aria-label="${text}">
2687
- ${icons['align_' + item]}
2688
- <span class="se-tooltip-inner">
2689
- <span class="se-tooltip-text">${text}</span>
2690
- </span>
2691
- </button>
2692
- </li>`;
3159
+ <button type="button" class="se-btn se-tooltip" data-command="props_align" data-value="${item}" title="${text}" aria-label="${text}">
3160
+ ${icons['align_' + item]}
3161
+ <span class="se-tooltip-inner">
3162
+ <span class="se-tooltip-text">${text}</span>
3163
+ </span>
3164
+ </button>`;
2693
3165
  }
2694
3166
 
2695
3167
  // vertical align html
@@ -2699,14 +3171,12 @@ function CreateHTML_controller_properties({ lang, icons, options }) {
2699
3171
  item = verticalAligns[i];
2700
3172
  text = lang['align' + item.charAt(0).toUpperCase() + item.slice(1)];
2701
3173
  verticalAlignHtml += /*html*/ `
2702
- <li>
2703
- <button type="button" class="se-btn se-btn-list se-tooltip" data-command="props_align_vertical" data-value="${item}" title="${text}" aria-label="${text}">
2704
- ${icons['align_' + item]}
2705
- <span class="se-tooltip-inner">
2706
- <span class="se-tooltip-text">${text}</span>
2707
- </span>
2708
- </button>
2709
- </li>`;
3174
+ <button type="button" class="se-btn se-tooltip" data-command="props_align_vertical" data-value="${item}" title="${text}" aria-label="${text}">
3175
+ ${icons['align_' + item]}
3176
+ <span class="se-tooltip-inner">
3177
+ <span class="se-tooltip-text">${text}</span>
3178
+ </span>
3179
+ </button>`;
2710
3180
  }
2711
3181
 
2712
3182
  const html = /*html*/ `
@@ -2789,12 +3259,14 @@ function CreateHTML_controller_properties({ lang, icons, options }) {
2789
3259
  </div>
2790
3260
 
2791
3261
  <div class="se-table-props-align">
2792
- <label>${lang.align}</label>
2793
- <div class="se-form-group se-form-w0 se-list-inner __se__a_h">
2794
- <ul class="se-form-group se-form-w0">${alignHtml}</ul>
2795
- </div>
2796
- <div class="se-form-group se-form-w0 se-list-inner __se__a_v">
2797
- <ul class="se-form-group se-form-w0">${verticalAlignHtml}</ul>
3262
+ <label>${lang.align} <span class="__se__a_table_t">( ${lang.table} )</span></label>
3263
+ <div class="se-form-group se-form-w0 se-list-inner">
3264
+ <div class="__se__a_h">
3265
+ ${alignHtml}
3266
+ </div>
3267
+ <div class="__se__a_v">
3268
+ ${verticalAlignHtml}
3269
+ </div>
2798
3270
  </div>
2799
3271
  </div>
2800
3272
  </div>
@@ -2804,7 +3276,27 @@ function CreateHTML_controller_properties({ lang, icons, options }) {
2804
3276
  </div>
2805
3277
  </div>`;
2806
3278
 
2807
- return domUtils.createElement('DIV', { class: 'se-controller se-table-props' }, html);
3279
+ const content = dom.utils.createElement('DIV', { class: 'se-controller se-table-props' }, html);
3280
+
3281
+ return {
3282
+ html: content,
3283
+ controller_props_title: content.querySelector('.se-controller-title'),
3284
+ borderButton: content.querySelector('[data-command="props_onborder_style"]'),
3285
+ borderFormatButton: content.querySelector('[data-command="props_onborder_format"]'),
3286
+ cell_alignment: content.querySelector('.se-table-props-align .__se__a_h'),
3287
+ cell_alignment_vertical: content.querySelector('.se-table-props-align .__se__a_v'),
3288
+ cell_alignment_table_text: content.querySelector('.se-table-props-align .__se__a_table_t'),
3289
+ border_style: content.querySelector('[data-command="props_onborder_style"] .se-txt'),
3290
+ border_color: content.querySelector('.__se_border_color'),
3291
+ border_width: content.querySelector('.__se__border_size'),
3292
+ back_color: content.querySelector('.__se_back_color'),
3293
+ font_color: content.querySelector('.__se_font_color'),
3294
+ palette_border_button: content.querySelector('[data-command="props_onpalette"][data-value="border"]'),
3295
+ font_bold: content.querySelector('[data-command="props_font_style"][data-value="bold"]'),
3296
+ font_underline: content.querySelector('[data-command="props_font_style"][data-value="underline"]'),
3297
+ font_italic: content.querySelector('[data-command="props_font_style"][data-value="italic"]'),
3298
+ font_strike: content.querySelector('[data-command="props_font_style"][data-value="strike"]')
3299
+ };
2808
3300
  }
2809
3301
 
2810
3302
  export default Table;