suneditor 3.0.0-alpha.9 → 3.0.0-beta.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CONTRIBUTING.md +170 -22
- package/{LICENSE.txt → LICENSE} +9 -9
- package/README.md +168 -30
- package/dist/suneditor.min.css +1 -1
- package/dist/suneditor.min.js +1 -1
- package/package.json +47 -21
- package/src/assets/design/color.css +121 -0
- package/src/assets/design/index.css +3 -0
- package/src/assets/design/size.css +35 -0
- package/src/assets/design/typography.css +37 -0
- package/src/assets/icons/defaultIcons.js +232 -0
- package/src/assets/suneditor-contents.css +181 -46
- package/src/assets/suneditor.css +1403 -650
- package/src/core/base/eventHandlers/handler_toolbar.js +35 -14
- package/src/core/base/eventHandlers/handler_ww_clipboard.js +23 -4
- package/src/core/base/eventHandlers/handler_ww_dragDrop.js +49 -10
- package/src/core/base/eventHandlers/handler_ww_key_input.js +422 -224
- package/src/core/base/eventHandlers/handler_ww_mouse.js +83 -36
- package/src/core/base/eventManager.js +520 -179
- package/src/core/base/history.js +95 -41
- package/src/core/class/char.js +26 -11
- package/src/core/class/component.js +345 -137
- package/src/core/class/format.js +683 -519
- package/src/core/class/html.js +485 -305
- package/src/core/class/menu.js +133 -47
- package/src/core/class/nodeTransform.js +90 -71
- package/src/core/class/offset.js +408 -92
- package/src/core/class/selection.js +216 -106
- package/src/core/class/shortcuts.js +68 -8
- package/src/core/class/toolbar.js +106 -116
- package/src/core/class/ui.js +422 -0
- package/src/core/class/viewer.js +178 -74
- package/src/core/editor.js +496 -389
- package/src/core/section/actives.js +123 -27
- package/src/core/section/constructor.js +615 -206
- package/src/core/section/context.js +28 -23
- package/src/core/section/documentType.js +561 -0
- package/src/editorInjector/_classes.js +19 -5
- package/src/editorInjector/_core.js +71 -7
- package/src/editorInjector/index.js +63 -1
- package/src/events.js +622 -0
- package/src/helper/clipboard.js +59 -0
- package/src/helper/converter.js +202 -26
- package/src/helper/dom/domCheck.js +304 -0
- package/src/helper/dom/domQuery.js +669 -0
- package/src/helper/dom/domUtils.js +557 -0
- package/src/helper/dom/index.js +12 -0
- package/src/helper/env.js +46 -56
- package/src/helper/index.js +10 -4
- package/src/helper/keyCodeMap.js +183 -0
- package/src/helper/numbers.js +12 -8
- package/src/helper/unicode.js +9 -5
- package/src/langs/ckb.js +74 -4
- package/src/langs/cs.js +72 -2
- package/src/langs/da.js +73 -3
- package/src/langs/de.js +73 -4
- package/src/langs/en.js +23 -3
- package/src/langs/es.js +73 -4
- package/src/langs/fa.js +75 -3
- package/src/langs/fr.js +73 -3
- package/src/langs/he.js +73 -4
- package/src/langs/hu.js +230 -0
- package/src/langs/index.js +7 -3
- package/src/langs/it.js +70 -1
- package/src/langs/ja.js +72 -4
- package/src/langs/km.js +230 -0
- package/src/langs/ko.js +22 -2
- package/src/langs/lv.js +74 -5
- package/src/langs/nl.js +73 -4
- package/src/langs/pl.js +73 -4
- package/src/langs/pt_br.js +70 -1
- package/src/langs/ro.js +74 -5
- package/src/langs/ru.js +73 -4
- package/src/langs/se.js +73 -4
- package/src/langs/tr.js +73 -1
- package/src/langs/{ua.js → uk.js} +75 -6
- package/src/langs/ur.js +77 -8
- package/src/langs/zh_cn.js +74 -5
- package/src/modules/ApiManager.js +77 -54
- package/src/modules/Browser.js +667 -0
- package/src/modules/ColorPicker.js +162 -102
- package/src/modules/Controller.js +273 -142
- package/src/modules/Figure.js +925 -484
- package/src/modules/FileManager.js +121 -69
- package/src/modules/HueSlider.js +113 -61
- package/src/modules/Modal.js +291 -122
- package/src/modules/ModalAnchorEditor.js +383 -234
- package/src/modules/SelectMenu.js +270 -168
- package/src/modules/_DragHandle.js +2 -1
- package/src/modules/index.js +3 -3
- package/src/plugins/browser/audioGallery.js +83 -0
- package/src/plugins/browser/fileBrowser.js +103 -0
- package/src/plugins/browser/fileGallery.js +83 -0
- package/src/plugins/browser/imageGallery.js +81 -0
- package/src/plugins/browser/videoGallery.js +103 -0
- package/src/plugins/command/blockquote.js +40 -27
- package/src/plugins/command/exportPDF.js +134 -0
- package/src/plugins/command/fileUpload.js +229 -162
- package/src/plugins/command/list_bulleted.js +83 -47
- package/src/plugins/command/list_numbered.js +83 -47
- package/src/plugins/dropdown/align.js +66 -54
- package/src/plugins/dropdown/backgroundColor.js +63 -49
- package/src/plugins/dropdown/font.js +71 -47
- package/src/plugins/dropdown/fontColor.js +63 -48
- package/src/plugins/dropdown/formatBlock.js +70 -33
- package/src/plugins/dropdown/hr.js +92 -51
- package/src/plugins/dropdown/layout.js +37 -26
- package/src/plugins/dropdown/lineHeight.js +54 -38
- package/src/plugins/dropdown/list.js +60 -45
- package/src/plugins/dropdown/paragraphStyle.js +51 -30
- package/src/plugins/dropdown/table.js +2003 -813
- package/src/plugins/dropdown/template.js +38 -26
- package/src/plugins/dropdown/textStyle.js +43 -31
- package/src/plugins/field/mention.js +147 -86
- package/src/plugins/index.js +32 -6
- package/src/plugins/input/fontSize.js +161 -108
- package/src/plugins/input/pageNavigator.js +70 -0
- package/src/plugins/modal/audio.js +358 -173
- package/src/plugins/modal/drawing.js +531 -0
- package/src/plugins/modal/embed.js +886 -0
- package/src/plugins/modal/image.js +674 -362
- package/src/plugins/modal/link.js +100 -71
- package/src/plugins/modal/math.js +367 -167
- package/src/plugins/modal/video.js +691 -335
- package/src/plugins/popup/anchor.js +222 -0
- package/src/suneditor.js +50 -13
- package/src/themes/dark.css +122 -0
- package/src/typedef.js +130 -0
- package/types/assets/icons/defaultIcons.d.ts +153 -0
- package/types/core/base/eventHandlers/handler_toolbar.d.ts +41 -0
- package/types/core/base/eventHandlers/handler_ww_clipboard.d.ts +40 -0
- package/types/core/base/eventHandlers/handler_ww_dragDrop.d.ts +35 -0
- package/types/core/base/eventHandlers/handler_ww_key_input.d.ts +45 -0
- package/types/core/base/eventHandlers/handler_ww_mouse.d.ts +39 -0
- package/types/core/base/eventManager.d.ts +385 -0
- package/types/core/base/history.d.ts +81 -0
- package/types/core/class/char.d.ts +60 -0
- package/types/core/class/component.d.ts +212 -0
- package/types/core/class/format.d.ts +616 -0
- package/types/core/class/html.d.ts +422 -0
- package/types/core/class/menu.d.ts +126 -0
- package/types/core/class/nodeTransform.d.ts +93 -0
- package/types/core/class/offset.d.ts +522 -0
- package/types/core/class/selection.d.ts +188 -0
- package/types/core/class/shortcuts.d.ts +142 -0
- package/types/core/class/toolbar.d.ts +189 -0
- package/types/core/class/ui.d.ts +164 -0
- package/types/core/class/viewer.d.ts +140 -0
- package/types/core/editor.d.ts +610 -0
- package/types/core/section/actives.d.ts +46 -0
- package/types/core/section/constructor.d.ts +777 -0
- package/types/core/section/context.d.ts +45 -0
- package/types/core/section/documentType.d.ts +178 -0
- package/types/editorInjector/_classes.d.ts +41 -0
- package/types/editorInjector/_core.d.ts +92 -0
- package/types/editorInjector/index.d.ts +71 -0
- package/types/events.d.ts +273 -0
- package/types/helper/clipboard.d.ts +12 -0
- package/types/helper/converter.d.ts +197 -0
- package/types/helper/dom/domCheck.d.ts +189 -0
- package/types/helper/dom/domQuery.d.ts +223 -0
- package/types/helper/dom/domUtils.d.ts +226 -0
- package/types/helper/dom/index.d.ts +9 -0
- package/types/helper/env.d.ts +132 -0
- package/types/helper/index.d.ts +174 -0
- package/types/helper/keyCodeMap.d.ts +110 -0
- package/types/helper/numbers.d.ts +46 -0
- package/types/helper/unicode.d.ts +28 -0
- package/types/index.d.ts +120 -0
- package/{typings/Lang.d.ts → types/langs/_Lang.d.ts} +173 -103
- package/types/langs/ckb.d.ts +3 -0
- package/types/langs/cs.d.ts +3 -0
- package/types/langs/da.d.ts +3 -0
- package/types/langs/de.d.ts +3 -0
- package/types/langs/en.d.ts +3 -0
- package/types/langs/es.d.ts +3 -0
- package/types/langs/fa.d.ts +3 -0
- package/types/langs/fr.d.ts +3 -0
- package/types/langs/he.d.ts +3 -0
- package/types/langs/hu.d.ts +3 -0
- package/types/langs/index.d.ts +54 -0
- package/types/langs/it.d.ts +3 -0
- package/types/langs/ja.d.ts +3 -0
- package/types/langs/km.d.ts +3 -0
- package/types/langs/ko.d.ts +3 -0
- package/types/langs/lv.d.ts +3 -0
- package/types/langs/nl.d.ts +3 -0
- package/types/langs/pl.d.ts +3 -0
- package/types/langs/pt_br.d.ts +3 -0
- package/types/langs/ro.d.ts +3 -0
- package/types/langs/ru.d.ts +3 -0
- package/types/langs/se.d.ts +3 -0
- package/types/langs/tr.d.ts +3 -0
- package/types/langs/uk.d.ts +3 -0
- package/types/langs/ur.d.ts +3 -0
- package/types/langs/zh_cn.d.ts +3 -0
- package/types/modules/ApiManager.d.ts +125 -0
- package/types/modules/Browser.d.ts +326 -0
- package/types/modules/ColorPicker.d.ts +131 -0
- package/types/modules/Controller.d.ts +251 -0
- package/types/modules/Figure.d.ts +517 -0
- package/types/modules/FileManager.d.ts +202 -0
- package/types/modules/HueSlider.d.ts +136 -0
- package/types/modules/Modal.d.ts +111 -0
- package/types/modules/ModalAnchorEditor.d.ts +236 -0
- package/types/modules/SelectMenu.d.ts +194 -0
- package/types/modules/_DragHandle.d.ts +7 -0
- package/types/modules/index.d.ts +26 -0
- package/types/plugins/browser/audioGallery.d.ts +55 -0
- package/types/plugins/browser/fileBrowser.d.ts +64 -0
- package/types/plugins/browser/fileGallery.d.ts +55 -0
- package/types/plugins/browser/imageGallery.d.ts +51 -0
- package/types/plugins/browser/videoGallery.d.ts +57 -0
- package/types/plugins/command/blockquote.d.ts +28 -0
- package/types/plugins/command/exportPDF.d.ts +46 -0
- package/types/plugins/command/fileUpload.d.ts +156 -0
- package/types/plugins/command/list_bulleted.d.ts +46 -0
- package/types/plugins/command/list_numbered.d.ts +46 -0
- package/types/plugins/dropdown/align.d.ts +60 -0
- package/types/plugins/dropdown/backgroundColor.d.ts +63 -0
- package/types/plugins/dropdown/font.d.ts +54 -0
- package/types/plugins/dropdown/fontColor.d.ts +63 -0
- package/types/plugins/dropdown/formatBlock.d.ts +54 -0
- package/types/plugins/dropdown/hr.d.ts +71 -0
- package/types/plugins/dropdown/layout.d.ts +40 -0
- package/types/plugins/dropdown/lineHeight.d.ts +50 -0
- package/types/plugins/dropdown/list.d.ts +39 -0
- package/types/plugins/dropdown/paragraphStyle.d.ts +54 -0
- package/types/plugins/dropdown/table.d.ts +627 -0
- package/types/plugins/dropdown/template.d.ts +40 -0
- package/types/plugins/dropdown/textStyle.d.ts +41 -0
- package/types/plugins/field/mention.d.ts +102 -0
- package/types/plugins/index.d.ts +107 -0
- package/types/plugins/input/fontSize.d.ts +170 -0
- package/types/plugins/input/pageNavigator.d.ts +28 -0
- package/types/plugins/modal/audio.d.ts +269 -0
- package/types/plugins/modal/drawing.d.ts +246 -0
- package/types/plugins/modal/embed.d.ts +387 -0
- package/types/plugins/modal/image.d.ts +451 -0
- package/types/plugins/modal/link.d.ts +128 -0
- package/types/plugins/modal/math.d.ts +193 -0
- package/types/plugins/modal/video.d.ts +485 -0
- package/types/plugins/popup/anchor.d.ts +56 -0
- package/types/suneditor.d.ts +51 -0
- package/types/typedef.d.ts +233 -0
- package/.eslintignore +0 -7
- package/.eslintrc.json +0 -64
- package/src/assets/icons/_default.js +0 -194
- package/src/core/base/events.js +0 -320
- package/src/core/class/notice.js +0 -42
- package/src/helper/domUtils.js +0 -1177
- package/src/modules/FileBrowser.js +0 -271
- package/src/plugins/command/exportPdf.js +0 -168
- package/src/plugins/fileBrowser/imageGallery.js +0 -81
- package/src/themes/test.css +0 -61
- package/typings/CommandPlugin.d.ts +0 -8
- package/typings/DialogPlugin.d.ts +0 -20
- package/typings/FileBrowserPlugin.d.ts +0 -30
- package/typings/Module.d.ts +0 -15
- package/typings/Plugin.d.ts +0 -42
- package/typings/SubmenuPlugin.d.ts +0 -8
- package/typings/_classes.d.ts +0 -17
- package/typings/_colorPicker.d.ts +0 -60
- package/typings/_core.d.ts +0 -55
- package/typings/align.d.ts +0 -5
- package/typings/audio.d.ts +0 -5
- package/typings/backgroundColor.d.ts +0 -5
- package/typings/blockquote.d.ts +0 -5
- package/typings/char.d.ts +0 -39
- package/typings/component.d.ts +0 -38
- package/typings/context.d.ts +0 -39
- package/typings/converter.d.ts +0 -33
- package/typings/dialog.d.ts +0 -28
- package/typings/domUtils.d.ts +0 -361
- package/typings/editor.d.ts +0 -7
- package/typings/editor.ts +0 -542
- package/typings/env.d.ts +0 -70
- package/typings/eventManager.d.ts +0 -37
- package/typings/events.d.ts +0 -262
- package/typings/fileBrowser.d.ts +0 -42
- package/typings/fileManager.d.ts +0 -67
- package/typings/font.d.ts +0 -5
- package/typings/fontColor.d.ts +0 -5
- package/typings/fontSize.d.ts +0 -5
- package/typings/format.d.ts +0 -191
- package/typings/formatBlock.d.ts +0 -5
- package/typings/history.d.ts +0 -48
- package/typings/horizontalRule.d.ts +0 -5
- package/typings/image.d.ts +0 -5
- package/typings/imageGallery.d.ts +0 -5
- package/typings/index.d.ts +0 -21
- package/typings/index.modules.d.ts +0 -11
- package/typings/index.plugins.d.ts +0 -58
- package/typings/lineHeight.d.ts +0 -5
- package/typings/link.d.ts +0 -5
- package/typings/list.d.ts +0 -5
- package/typings/math.d.ts +0 -5
- package/typings/mediaContainer.d.ts +0 -25
- package/typings/mention.d.ts +0 -5
- package/typings/node.d.ts +0 -57
- package/typings/notice.d.ts +0 -16
- package/typings/numbers.d.ts +0 -29
- package/typings/offset.d.ts +0 -24
- package/typings/options.d.ts +0 -589
- package/typings/paragraphStyle.d.ts +0 -5
- package/typings/resizing.d.ts +0 -141
- package/typings/selection.d.ts +0 -94
- package/typings/shortcuts.d.ts +0 -13
- package/typings/suneditor.d.ts +0 -9
- package/typings/table.d.ts +0 -5
- package/typings/template.d.ts +0 -5
- package/typings/textStyle.d.ts +0 -5
- package/typings/toolbar.d.ts +0 -32
- package/typings/unicode.d.ts +0 -25
- package/typings/video.d.ts +0 -5
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import EditorInjector from '../../editorInjector';
|
|
2
|
-
import {
|
|
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,420 @@ const DEFAULT_COLOR_LIST = [
|
|
|
61
61
|
'#000000'
|
|
62
62
|
];
|
|
63
63
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
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
|
-
});
|
|
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
|
+
}
|
|
105
81
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
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_cell = new Controller(this, controller_cell.html, { position: this.cellControllerTop ? 'top' : 'bottom' });
|
|
119
|
+
this.controller_table = new Controller(this, controller_table, { position: 'top' });
|
|
120
|
+
if (this.cellControllerTop) {
|
|
121
|
+
this.controller_cell.sibling = this.controller_table.form;
|
|
122
|
+
this.controller_cell.siblingPosition = 'top';
|
|
115
123
|
}
|
|
116
|
-
|
|
124
|
+
// props
|
|
125
|
+
const propsTargetForms = [this.controller_table.form, this.controller_cell.form];
|
|
126
|
+
this.controller_props = new Controller(this, controller_props.html, { position: 'bottom', parents: propsTargetForms, isInsideForm: true });
|
|
127
|
+
this.controller_props_title = controller_props.controller_props_title;
|
|
128
|
+
// color picker
|
|
129
|
+
const colorForm = dom.utils.createElement('DIV', { class: 'se-controller se-list-layer' }, null);
|
|
130
|
+
this.colorPicker = new ColorPicker(this, '', {
|
|
131
|
+
colorList: pluginOptions.colorList || DEFAULT_COLOR_LIST,
|
|
132
|
+
splitNum: 5,
|
|
133
|
+
disableRemove: true,
|
|
134
|
+
hueSliderOptions: { controllerOptions: { parents: [colorForm], isOutsideForm: true } }
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
colorForm.appendChild(this.colorPicker.target);
|
|
138
|
+
this.controller_colorPicker = new Controller(this, colorForm, {
|
|
139
|
+
position: 'bottom',
|
|
140
|
+
parents: [this.controller_props.form].concat(propsTargetForms),
|
|
141
|
+
isInsideForm: true,
|
|
142
|
+
isWWTarget: false,
|
|
143
|
+
initMethod: () => {
|
|
144
|
+
this.colorPicker.hueSlider.close();
|
|
145
|
+
dom.utils.removeClass(this.controller_colorPicker.currentTarget, 'on');
|
|
146
|
+
}
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
this.figure = new Figure(this, null, {});
|
|
150
|
+
|
|
151
|
+
this.sliderType = '';
|
|
152
|
+
|
|
153
|
+
// members - SelectMenu [cells]
|
|
154
|
+
const openCellMenuFunc = _CellFormZIndex.bind(this, true);
|
|
155
|
+
const closeCellMenuFunc = _CellFormZIndex.bind(this, false);
|
|
156
|
+
// members - SelectMenu - split
|
|
157
|
+
const splitMenu = CreateSplitMenu(this.lang);
|
|
158
|
+
this.splitButton = controller_cell.splitButton;
|
|
159
|
+
this.selectMenu_split = new SelectMenu(this, { checkList: false, position: 'bottom-center', openMethod: openCellMenuFunc, closeMethod: closeCellMenuFunc });
|
|
160
|
+
this.selectMenu_split.on(this.splitButton, this.#OnSplitCells.bind(this));
|
|
161
|
+
this.selectMenu_split.create(splitMenu.items, splitMenu.menus);
|
|
162
|
+
|
|
163
|
+
// members - SelectMenu - column
|
|
164
|
+
const columnMenu = CreateColumnMenu(this.lang, this.icons);
|
|
165
|
+
const columnButton = controller_cell.columnButton;
|
|
166
|
+
this.selectMenu_column = new SelectMenu(this, { checkList: false, position: 'bottom-center', openMethod: openCellMenuFunc, closeMethod: closeCellMenuFunc });
|
|
167
|
+
this.selectMenu_column.on(columnButton, this.#OnColumnEdit.bind(this));
|
|
168
|
+
this.selectMenu_column.create(columnMenu.items, columnMenu.menus);
|
|
169
|
+
|
|
170
|
+
// members - SelectMenu - row
|
|
171
|
+
const rownMenu = CreateRowMenu(this.lang, this.icons);
|
|
172
|
+
const rowButton = controller_cell.rowButton;
|
|
173
|
+
this.selectMenu_row = new SelectMenu(this, { checkList: false, position: 'bottom-center', openMethod: openCellMenuFunc, closeMethod: closeCellMenuFunc });
|
|
174
|
+
this.selectMenu_row.on(rowButton, this.#OnRowEdit.bind(this));
|
|
175
|
+
this.selectMenu_row.create(rownMenu.items, rownMenu.menus);
|
|
176
|
+
|
|
177
|
+
// members - SelectMenu - properties - border style
|
|
178
|
+
const borderMenu = CreateBorderMenu();
|
|
179
|
+
const borderButton = controller_props.borderButton;
|
|
180
|
+
this.selectMenu_props_border = new SelectMenu(this, { checkList: false, position: 'bottom-center' });
|
|
181
|
+
this.selectMenu_props_border.on(borderButton, OnPropsBorderEdit.bind(this));
|
|
182
|
+
this.selectMenu_props_border.create(borderMenu.items, borderMenu.menus);
|
|
183
|
+
|
|
184
|
+
// members - SelectMenu - properties - border format
|
|
185
|
+
const borderFormatMenu = CreateBorderFormatMenu(this.lang, this.icons, []);
|
|
186
|
+
const borderFormatButton = controller_props.borderFormatButton;
|
|
187
|
+
this.selectMenu_props_border_format = new SelectMenu(this, { checkList: false, position: 'bottom-left', dir: 'ltr', splitNum: 5 });
|
|
188
|
+
this.selectMenu_props_border_format.on(borderFormatButton, OnPropsBorderFormatEdit.bind(this, 'all'));
|
|
189
|
+
this.selectMenu_props_border_format.create(borderFormatMenu.items, borderFormatMenu.menus);
|
|
190
|
+
|
|
191
|
+
const borderFormatMenu_oneCell = CreateBorderFormatMenu(this.lang, this.icons, BORDER_FORMAT_INSIDE);
|
|
192
|
+
this.selectMenu_props_border_format_oneCell = new SelectMenu(this, { checkList: false, position: 'bottom-left', dir: 'ltr', splitNum: 6 });
|
|
193
|
+
this.selectMenu_props_border_format_oneCell.on(borderFormatButton, OnPropsBorderFormatEdit.bind(this, 'outside'));
|
|
194
|
+
this.selectMenu_props_border_format_oneCell.create(borderFormatMenu_oneCell.items, borderFormatMenu_oneCell.menus);
|
|
195
|
+
|
|
196
|
+
// memberts - elements..
|
|
197
|
+
this.maxText = this.lang.maxSize;
|
|
198
|
+
this.minText = this.lang.minSize;
|
|
199
|
+
this.propTargets = {
|
|
200
|
+
cell_alignment: controller_props.cell_alignment,
|
|
201
|
+
cell_alignment_vertical: controller_props.cell_alignment_vertical,
|
|
202
|
+
cell_alignment_table_text: controller_props.cell_alignment_table_text,
|
|
203
|
+
border_format: borderFormatButton,
|
|
204
|
+
border_style: controller_props.border_style,
|
|
205
|
+
border_color: controller_props.border_color,
|
|
206
|
+
border_width: controller_props.border_width,
|
|
207
|
+
back_color: controller_props.back_color,
|
|
208
|
+
font_color: controller_props.font_color,
|
|
209
|
+
palette_border_button: controller_props.palette_border_button,
|
|
210
|
+
font_bold: controller_props.font_bold,
|
|
211
|
+
font_underline: controller_props.font_underline,
|
|
212
|
+
font_italic: controller_props.font_italic,
|
|
213
|
+
font_strike: controller_props.font_strike
|
|
214
|
+
};
|
|
215
|
+
this._propsCache = [];
|
|
216
|
+
this._currentFontStyles = [];
|
|
217
|
+
this._propsAlignCache = '';
|
|
218
|
+
this._propsVerticalAlignCache = '';
|
|
219
|
+
this._typeCache = '';
|
|
220
|
+
|
|
221
|
+
/** @type {HTMLElement} */
|
|
222
|
+
this.tableHighlight = menu.querySelector('.se-table-size-highlighted');
|
|
223
|
+
/** @type {HTMLElement} */
|
|
224
|
+
this.tableUnHighlight = menu.querySelector('.se-table-size-unhighlighted');
|
|
225
|
+
/** @type {HTMLElement} */
|
|
226
|
+
this.tableDisplay = menu.querySelector('.se-table-size-display');
|
|
227
|
+
/** @type {HTMLButtonElement} */
|
|
228
|
+
this.resizeButton = controller_table.querySelector('._se_table_resize');
|
|
229
|
+
/** @type {HTMLSpanElement} */
|
|
230
|
+
this.resizeText = controller_table.querySelector('._se_table_resize > span > span');
|
|
231
|
+
/** @type {HTMLButtonElement} */
|
|
232
|
+
this.columnFixedButton = controller_table.querySelector('._se_table_fixed_column');
|
|
233
|
+
/** @type {HTMLButtonElement} */
|
|
234
|
+
this.headerButton = controller_table.querySelector('._se_table_header');
|
|
235
|
+
/** @type {HTMLButtonElement} */
|
|
236
|
+
this.captionButton = controller_table.querySelector('._se_table_caption');
|
|
237
|
+
/** @type {HTMLButtonElement} */
|
|
238
|
+
this.mergeButton = controller_cell.mergeButton;
|
|
239
|
+
/** @type {HTMLButtonElement} */
|
|
240
|
+
this.unmergeButton = controller_cell.unmergeButton;
|
|
241
|
+
|
|
242
|
+
// members - private
|
|
243
|
+
this._resizing = false;
|
|
244
|
+
this._resizeLine = null;
|
|
245
|
+
this._resizeLinePrev = null;
|
|
117
246
|
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
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
|
-
};
|
|
247
|
+
/** @type {HTMLElement} */
|
|
248
|
+
this._figure = null;
|
|
249
|
+
/**
|
|
250
|
+
* @description Same value a "this._selectedTable", but it maintain prev table element
|
|
251
|
+
* @type {HTMLTableElement}
|
|
252
|
+
*/
|
|
253
|
+
this._element = null;
|
|
254
|
+
/** @type {HTMLTableCellElement} */
|
|
255
|
+
this._tdElement = null;
|
|
256
|
+
/** @type {HTMLTableRowElement} */
|
|
257
|
+
this._trElement = null;
|
|
258
|
+
/** @type {HTMLTableRowElement[]|HTMLCollectionOf<HTMLTableRowElement>} */
|
|
259
|
+
this._trElements = null;
|
|
239
260
|
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
261
|
+
this._tableXY = [];
|
|
262
|
+
this._maxWidth = true;
|
|
263
|
+
this._fixedColumn = false;
|
|
264
|
+
this._physical_cellCnt = 0;
|
|
265
|
+
this._logical_cellCnt = 0;
|
|
266
|
+
this._cellCnt = 0;
|
|
267
|
+
this._rowCnt = 0;
|
|
268
|
+
this._rowIndex = 0;
|
|
269
|
+
this._physical_cellIndex = 0;
|
|
270
|
+
this._logical_cellIndex = 0;
|
|
271
|
+
this._current_colSpan = 0;
|
|
272
|
+
this._current_rowSpan = 0;
|
|
273
|
+
|
|
274
|
+
// member - multi selecte
|
|
275
|
+
/** @type {HTMLTableElement} */
|
|
276
|
+
this._selectedTable = null;
|
|
277
|
+
/** @type {HTMLTableCellElement} */
|
|
278
|
+
this._fixedCell = null;
|
|
279
|
+
/** @type {HTMLTableCellElement} */
|
|
280
|
+
this._selectedCell = null;
|
|
281
|
+
/** @type {HTMLTableCellElement[]} */
|
|
282
|
+
this._selectedCells = null;
|
|
283
|
+
|
|
284
|
+
this._shift = false;
|
|
285
|
+
this.__s = false;
|
|
286
|
+
this._fixedCellName = null;
|
|
287
|
+
this._ref = null;
|
|
288
|
+
|
|
289
|
+
// member - global events
|
|
290
|
+
this._bindMultiOn = this.#OnCellMultiSelect.bind(this);
|
|
291
|
+
this._bindMultiOff = this.#OffCellMultiSelect.bind(this);
|
|
292
|
+
this._bindShiftOff = this.#OffCellShift.bind(this);
|
|
293
|
+
this._bindTouchOff = this.#OffCellTouch.bind(this);
|
|
294
|
+
this.__globalEvents = {
|
|
295
|
+
on: null,
|
|
296
|
+
off: null,
|
|
297
|
+
shiftOff: null,
|
|
298
|
+
touchOff: null,
|
|
299
|
+
resize: null,
|
|
300
|
+
resizeStop: null,
|
|
301
|
+
resizeKeyDown: null
|
|
302
|
+
};
|
|
303
|
+
|
|
304
|
+
// init
|
|
305
|
+
this.menu.initDropdownTarget(Table, menu);
|
|
306
|
+
this.eventManager.addEvent(commandArea, 'mousemove', this.#OnMouseMoveTablePicker.bind(this));
|
|
307
|
+
this.eventManager.addEvent(commandArea, 'click', this.#OnClickTablePicker.bind(this));
|
|
308
|
+
}
|
|
245
309
|
|
|
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
310
|
/**
|
|
255
|
-
* @
|
|
311
|
+
* @editorMethod Editor.core
|
|
312
|
+
* @description Executes the main execution method of the plugin.
|
|
313
|
+
* - Called when an item in the "dropdown" menu is clicked.
|
|
256
314
|
*/
|
|
257
315
|
action() {
|
|
258
|
-
const oTable =
|
|
316
|
+
const oTable = dom.utils.createElement('TABLE');
|
|
259
317
|
const x = this._tableXY[0];
|
|
260
318
|
const y = this._tableXY[1];
|
|
261
319
|
|
|
262
|
-
const body = `<tbody>${`<tr>${
|
|
320
|
+
const body = `<tbody>${`<tr>${CreateCellsString('td', x)}</tr>`.repeat(y)}</tbody>`;
|
|
263
321
|
const colGroup = `<colgroup>${`<col style="width: ${numbers.get(100 / x, CELL_DECIMAL_END)}%;">`.repeat(x)}</colgroup>`;
|
|
264
322
|
oTable.innerHTML = colGroup + body;
|
|
265
323
|
|
|
266
|
-
|
|
324
|
+
// scroll
|
|
325
|
+
let scrollTypeClass = '';
|
|
326
|
+
if (this.figureScroll) {
|
|
327
|
+
scrollTypeClass = ` se-scroll-figure-${this.figureScroll}`;
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
const figure = dom.utils.createElement('FIGURE', { class: 'se-flex-component se-input-component' + scrollTypeClass });
|
|
267
331
|
figure.appendChild(oTable);
|
|
268
332
|
|
|
269
|
-
if (this.component.insert(figure, false, false)) {
|
|
333
|
+
if (this.component.insert(figure, { skipCharCount: false, skipSelection: false, skipHistory: false })) {
|
|
270
334
|
this._resetTablePicker();
|
|
271
335
|
const target = oTable.querySelector('td div');
|
|
272
336
|
this.selection.setRange(target, 0, target, 0);
|
|
273
337
|
}
|
|
274
|
-
}
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
/**
|
|
341
|
+
* @editorMethod Editor.component
|
|
342
|
+
* @description Executes the method that is called when a component of a plugin is selected.
|
|
343
|
+
* @param {HTMLElement} target Target component element
|
|
344
|
+
*/
|
|
345
|
+
select(target) {
|
|
346
|
+
this._figureOpen(target);
|
|
347
|
+
if (!this._figure) this.setTableInfo(target);
|
|
348
|
+
|
|
349
|
+
const targetWidth = this._figure?.style.width || '100%';
|
|
350
|
+
this._maxWidth = targetWidth === '100%';
|
|
351
|
+
this._fixedColumn = dom.utils.hasClass(target, 'se-table-layout-fixed') || target.style.tableLayout === 'fixed';
|
|
352
|
+
this._setTableStyle(this._maxWidth ? 'width|column' : 'width', true);
|
|
353
|
+
|
|
354
|
+
if (_DragHandle.get('__overInfo') === ON_OVER_COMPONENT) return;
|
|
355
|
+
|
|
356
|
+
if (!this._tdElement) return;
|
|
357
|
+
this.setCellInfo(this._tdElement, true);
|
|
358
|
+
|
|
359
|
+
// controller open
|
|
360
|
+
const btnDisabled = this._selectedCells?.length > 1;
|
|
361
|
+
const figureEl = dom.query.getParentElement(target, dom.check.isFigure);
|
|
362
|
+
this.controller_table.open(figureEl, null, { isWWTarget: false, initMethod: null, addOffset: null, disabled: btnDisabled });
|
|
363
|
+
|
|
364
|
+
if (!this._fixedCell) return;
|
|
365
|
+
|
|
366
|
+
this._setUnMergeButton();
|
|
367
|
+
this.controller_cell.open(this._tdElement, this.cellControllerTop ? figureEl : null, { isWWTarget: false, initMethod: null, addOffset: null, disabled: btnDisabled });
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
/**
|
|
371
|
+
* @editorMethod Editor.component
|
|
372
|
+
* @description Executes the method that is called when a component copy is requested.
|
|
373
|
+
* @param {__se__PluginCopyComponentParams} params
|
|
374
|
+
* @returns {boolean|void}
|
|
375
|
+
*/
|
|
376
|
+
onCopyComponent({ event, cloneContainer }) {
|
|
377
|
+
/** @type {NodeListOf<HTMLTableCellElement>} */
|
|
378
|
+
const selectedCells = cloneContainer.querySelectorAll('.se-selected-table-cell');
|
|
379
|
+
dom.utils.removeClass(selectedCells, 'se-selected-table-cell|se-selected-cell-focus');
|
|
380
|
+
|
|
381
|
+
if (selectedCells.length > 0) {
|
|
382
|
+
SetClipboardSelectedTableCells(event, cloneContainer, selectedCells);
|
|
383
|
+
this.editor.ui.showToast(this.lang.message_copy_success, 550);
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
/**
|
|
388
|
+
* @editorMethod Editor.EventManager
|
|
389
|
+
* @description Executes the event function of "copy".
|
|
390
|
+
* @param {__se__PluginPasteParams} params
|
|
391
|
+
* @returns {boolean|void}
|
|
392
|
+
*/
|
|
393
|
+
onPaste({ event, doc }) {
|
|
394
|
+
/** @type {HTMLTableCellElement} */
|
|
395
|
+
const targetCell = dom.query.getParentElement(dom.query.getEventTarget(event), dom.check.isTableCell);
|
|
396
|
+
if (!targetCell) return;
|
|
397
|
+
|
|
398
|
+
const domParserBody = doc.body;
|
|
399
|
+
if (domParserBody.childElementCount !== 1) return;
|
|
400
|
+
|
|
401
|
+
const componentInfo = this.component.get(domParserBody.firstElementChild);
|
|
402
|
+
if (componentInfo.pluginName !== Table.key) return;
|
|
403
|
+
|
|
404
|
+
const copyTable = /** @type {HTMLTableElement} */ (componentInfo.target);
|
|
405
|
+
this.pasteTableCellMatrix(copyTable, targetCell);
|
|
406
|
+
|
|
407
|
+
return true;
|
|
408
|
+
}
|
|
275
409
|
|
|
276
410
|
/**
|
|
277
|
-
* @
|
|
411
|
+
* @editorMethod Editor.core
|
|
412
|
+
* @description This method is used to validate and preserve the format of the component within the editor.
|
|
413
|
+
* - It ensures that the structure and attributes of the element are maintained and secure.
|
|
414
|
+
* - The method checks if the element is already wrapped in a valid container and updates its attributes if necessary.
|
|
415
|
+
* - If the element isn't properly contained, a new container is created to retain the format.
|
|
416
|
+
* @returns {{query: string, method: (element: HTMLTableElement) => void}} The format retention object containing the query and method to process the element.
|
|
417
|
+
* - query: The selector query to identify the relevant elements (in this case, 'audio').
|
|
418
|
+
* - method:The function to execute on the element to validate and preserve its format.
|
|
419
|
+
* - The function takes the element as an argument, checks if it is contained correctly, and applies necessary adjustments.
|
|
278
420
|
*/
|
|
279
421
|
retainFormat() {
|
|
280
422
|
return {
|
|
281
423
|
query: 'table',
|
|
282
424
|
method: (element) => {
|
|
283
425
|
const ColgroupEl = element.querySelector('colgroup');
|
|
284
|
-
let FigureEl =
|
|
426
|
+
let FigureEl = dom.check.isFigure(element.parentNode) ? element.parentNode : null;
|
|
285
427
|
if (ColgroupEl && FigureEl) return;
|
|
286
428
|
|
|
287
429
|
// create colgroup
|
|
288
430
|
if (!ColgroupEl) {
|
|
289
431
|
const maxCount = GetMaxColumns(element);
|
|
290
|
-
const colGroup =
|
|
432
|
+
const colGroup = dom.utils.createElement('colgroup', null, `<col style="width: ${numbers.get(100 / maxCount, CELL_DECIMAL_END)}%;">`.repeat(maxCount));
|
|
291
433
|
element.insertBefore(colGroup, element.firstElementChild);
|
|
292
434
|
}
|
|
293
435
|
|
|
294
436
|
// figure
|
|
295
437
|
if (!FigureEl) {
|
|
296
|
-
FigureEl =
|
|
438
|
+
FigureEl = dom.utils.createElement('FIGURE', { class: 'se-flex-component se-input-component' });
|
|
297
439
|
element.parentNode.insertBefore(FigureEl, element);
|
|
298
440
|
FigureEl.appendChild(element);
|
|
299
441
|
} else {
|
|
300
|
-
|
|
442
|
+
dom.utils.addClass(FigureEl, 'se-flex-component|se-input-component');
|
|
301
443
|
}
|
|
302
444
|
|
|
303
445
|
// scroll
|
|
304
446
|
if (!this.figureScroll) {
|
|
305
|
-
|
|
447
|
+
dom.utils.removeClass(FigureEl, this.figureScrollList.join('|'));
|
|
306
448
|
} else {
|
|
307
449
|
const scrollTypeClass = `se-scroll-figure-${this.figureScroll}`;
|
|
308
|
-
|
|
309
|
-
|
|
450
|
+
dom.utils.addClass(FigureEl, scrollTypeClass);
|
|
451
|
+
dom.utils.removeClass(FigureEl, this.figureScrollList.filter((v) => v !== scrollTypeClass).join('|'));
|
|
310
452
|
}
|
|
311
453
|
}
|
|
312
454
|
};
|
|
313
|
-
}
|
|
455
|
+
}
|
|
314
456
|
|
|
315
457
|
/**
|
|
316
|
-
* @
|
|
317
|
-
* @
|
|
458
|
+
* @editorMethod Editor.core
|
|
459
|
+
* @description Executes the method called when the rtl, ltr mode changes. ("editor.setDir")
|
|
460
|
+
* @param {string} dir Direction ("rtl" or "ltr")
|
|
318
461
|
*/
|
|
319
462
|
setDir(dir) {
|
|
320
463
|
this.tableHighlight.style.left = dir === 'rtl' ? 10 * 18 - 13 + 'px' : '';
|
|
321
464
|
this._resetTablePicker();
|
|
322
|
-
this._resetPropsAlign(
|
|
323
|
-
}
|
|
465
|
+
this._resetPropsAlign();
|
|
466
|
+
}
|
|
324
467
|
|
|
468
|
+
/**
|
|
469
|
+
* @editorMethod Editor.EventManager
|
|
470
|
+
* @description Executes the event function of "mousemove".
|
|
471
|
+
* @param {__se__PluginMouseEventInfo} params
|
|
472
|
+
*/
|
|
325
473
|
onMouseMove({ event }) {
|
|
326
474
|
if (this._resizing) return;
|
|
327
|
-
|
|
475
|
+
|
|
476
|
+
const eventTarget = dom.query.getEventTarget(event);
|
|
477
|
+
const target = dom.query.getParentElement(eventTarget, IsResizeEls);
|
|
328
478
|
if (!target || this._fixedCell) {
|
|
329
479
|
this.__hideResizeLine();
|
|
330
480
|
return;
|
|
@@ -336,7 +486,7 @@ Table.prototype = {
|
|
|
336
486
|
this.__removeGlobalEvents();
|
|
337
487
|
if (this._resizeLine?.style.display === 'block') this._resizeLine.style.display = 'none';
|
|
338
488
|
this._resizeLine = this.editor.frameContext.get('wrapper').querySelector(RESIZE_CELL_CLASS);
|
|
339
|
-
this._setResizeLinePosition(
|
|
489
|
+
this._setResizeLinePosition(dom.query.getParentElement(target, dom.check.isTable), target, this._resizeLine, cellEdge.isLeft);
|
|
340
490
|
this._resizeLine.style.display = 'block';
|
|
341
491
|
return;
|
|
342
492
|
}
|
|
@@ -344,35 +494,45 @@ Table.prototype = {
|
|
|
344
494
|
const rowEdge = CheckRowEdge(event, target);
|
|
345
495
|
if (rowEdge.is) {
|
|
346
496
|
this.__removeGlobalEvents();
|
|
347
|
-
this._element =
|
|
497
|
+
this._element = dom.query.getParentElement(target, dom.check.isTable);
|
|
348
498
|
this._element.style.cursor = 'ns-resize';
|
|
349
499
|
if (this._resizeLine?.style.display === 'block') this._resizeLine.style.display = 'none';
|
|
350
500
|
this._resizeLine = this.editor.frameContext.get('wrapper').querySelector(RESIZE_ROW_CLASS);
|
|
351
|
-
this._setResizeRowPosition(
|
|
501
|
+
this._setResizeRowPosition(dom.query.getParentElement(target, dom.check.isTable), target, this._resizeLine);
|
|
352
502
|
this._resizeLine.style.display = 'block';
|
|
353
503
|
return;
|
|
354
504
|
}
|
|
355
505
|
|
|
356
506
|
if (this._element) this._element.style.cursor = '';
|
|
357
507
|
this.__hideResizeLine();
|
|
358
|
-
}
|
|
508
|
+
}
|
|
359
509
|
|
|
510
|
+
/**
|
|
511
|
+
* @editorMethod Editor.EventManager
|
|
512
|
+
* @description Executes the event function of "scroll".
|
|
513
|
+
*/
|
|
360
514
|
onScroll() {
|
|
361
515
|
if (this._resizeLine?.style.display !== 'block') return;
|
|
362
516
|
// delete resize line position
|
|
363
517
|
if (this._element) this._element.style.cursor = '';
|
|
364
518
|
this._resizeLine.style.display = 'none';
|
|
365
|
-
}
|
|
519
|
+
}
|
|
366
520
|
|
|
367
521
|
/**
|
|
368
|
-
* @
|
|
369
|
-
* @
|
|
522
|
+
* @editorMethod Editor.EventManager
|
|
523
|
+
* @description Executes the event function of "mousedown".
|
|
524
|
+
* @param {__se__PluginMouseEventInfo} params
|
|
370
525
|
*/
|
|
371
526
|
onMouseDown({ event }) {
|
|
372
|
-
this._ref = null;
|
|
373
|
-
const
|
|
527
|
+
this._ref = this._selectedCell = null;
|
|
528
|
+
const eventTarget = dom.query.getEventTarget(event);
|
|
529
|
+
const target = /** @type {HTMLTableCellElement} */ (dom.query.getParentElement(eventTarget, IsResizeEls));
|
|
374
530
|
if (!target) return;
|
|
375
531
|
|
|
532
|
+
if (!this.cellControllerTop) {
|
|
533
|
+
this.controller_cell.hide();
|
|
534
|
+
}
|
|
535
|
+
|
|
376
536
|
const cellEdge = CheckCellEdge(event, target);
|
|
377
537
|
if (cellEdge.is) {
|
|
378
538
|
try {
|
|
@@ -381,7 +541,7 @@ Table.prototype = {
|
|
|
381
541
|
const colIndex = this._logical_cellIndex - (cellEdge.isLeft ? 1 : 0);
|
|
382
542
|
|
|
383
543
|
// ready
|
|
384
|
-
this.
|
|
544
|
+
this.ui.enableBackWrapper('ew-resize');
|
|
385
545
|
if (!this._resizeLine) this._resizeLine = this.editor.frameContext.get('wrapper').querySelector(RESIZE_CELL_CLASS);
|
|
386
546
|
this._resizeLinePrev = this.editor.frameContext.get('wrapper').querySelector(RESIZE_CELL_PREV_CLASS);
|
|
387
547
|
|
|
@@ -393,9 +553,12 @@ Table.prototype = {
|
|
|
393
553
|
|
|
394
554
|
const col = this._element.querySelector('colgroup').querySelectorAll('col')[colIndex < 0 ? 0 : colIndex];
|
|
395
555
|
this._startCellResizing(col, cellEdge.startX, numbers.get(_w.getComputedStyle(col).width, CELL_DECIMAL_END), cellEdge.isLeft);
|
|
556
|
+
this._toggleEditor(false);
|
|
396
557
|
} catch (err) {
|
|
397
558
|
console.warn('[SUNEDITOR.plugins.table.error]', err);
|
|
398
559
|
this.__removeGlobalEvents();
|
|
560
|
+
} finally {
|
|
561
|
+
this._fixedCell = this._selectedCell = null;
|
|
399
562
|
}
|
|
400
563
|
|
|
401
564
|
return;
|
|
@@ -404,11 +567,12 @@ Table.prototype = {
|
|
|
404
567
|
const rowEdge = CheckRowEdge(event, target);
|
|
405
568
|
if (rowEdge.is) {
|
|
406
569
|
try {
|
|
407
|
-
|
|
570
|
+
/** @type {HTMLTableRowElement} */
|
|
571
|
+
let row = dom.query.getParentElement(target, dom.check.isTableRow);
|
|
408
572
|
let rowSpan = target.rowSpan;
|
|
409
573
|
if (rowSpan > 1) {
|
|
410
|
-
while (
|
|
411
|
-
row = row.nextElementSibling;
|
|
574
|
+
while (dom.check.isTableRow(row) && rowSpan > 1) {
|
|
575
|
+
row = /** @type {HTMLTableRowElement} */ (row.nextElementSibling);
|
|
412
576
|
--rowSpan;
|
|
413
577
|
}
|
|
414
578
|
}
|
|
@@ -417,67 +581,87 @@ Table.prototype = {
|
|
|
417
581
|
this.setRowInfo(row);
|
|
418
582
|
|
|
419
583
|
// ready
|
|
420
|
-
this.
|
|
584
|
+
this.ui.enableBackWrapper('ns-resize');
|
|
421
585
|
if (!this._resizeLine) this._resizeLine = this.editor.frameContext.get('wrapper').querySelector(RESIZE_ROW_CLASS);
|
|
422
586
|
this._resizeLinePrev = this.editor.frameContext.get('wrapper').querySelector(RESIZE_ROW_PREV_CLASS);
|
|
423
587
|
|
|
424
588
|
this._startRowResizing(row, rowEdge.startY, numbers.get(_w.getComputedStyle(row).height, CELL_DECIMAL_END));
|
|
589
|
+
this._toggleEditor(false);
|
|
425
590
|
} catch (err) {
|
|
426
591
|
console.warn('[SUNEDITOR.plugins.table.error]', err);
|
|
427
592
|
this.__removeGlobalEvents();
|
|
593
|
+
} finally {
|
|
594
|
+
this._fixedCell = this._selectedCell = null;
|
|
428
595
|
}
|
|
429
596
|
|
|
430
597
|
return;
|
|
431
598
|
}
|
|
432
599
|
|
|
433
|
-
if (
|
|
600
|
+
if (this._shift && target !== this._fixedCell) return;
|
|
434
601
|
|
|
435
602
|
this._deleteStyleSelectedCells();
|
|
436
603
|
if (/^TR$/i.test(target.nodeName)) return;
|
|
437
604
|
|
|
438
|
-
this
|
|
439
|
-
}
|
|
605
|
+
this.#StyleSelectCells(target, false);
|
|
606
|
+
}
|
|
440
607
|
|
|
441
608
|
/**
|
|
442
|
-
* @
|
|
609
|
+
* @editorMethod Editor.EventManager
|
|
610
|
+
* @description Executes the event function of "mouseup".
|
|
443
611
|
*/
|
|
444
612
|
onMouseUp() {
|
|
445
613
|
this._shift = false;
|
|
446
|
-
|
|
614
|
+
if (!this.cellControllerTop) {
|
|
615
|
+
this.controller_cell.resetPosition(this._fixedCell);
|
|
616
|
+
}
|
|
617
|
+
}
|
|
447
618
|
|
|
448
619
|
/**
|
|
449
|
-
* @
|
|
620
|
+
* @editorMethod Editor.EventManager
|
|
621
|
+
* @description Executes the event function of "mouseleave".
|
|
450
622
|
*/
|
|
451
623
|
onMouseLeave() {
|
|
452
624
|
this.__hideResizeLine();
|
|
453
|
-
}
|
|
625
|
+
}
|
|
454
626
|
|
|
455
627
|
/**
|
|
456
|
-
* @
|
|
457
|
-
* @
|
|
458
|
-
* @param {
|
|
459
|
-
* @param {Element} line Current line element
|
|
628
|
+
* @editorMethod Editor.EventManager
|
|
629
|
+
* @description Executes the event function of "keydown".
|
|
630
|
+
* @param {__se__PluginKeyEventInfo} params
|
|
460
631
|
*/
|
|
461
632
|
onKeyDown({ event, range, line }) {
|
|
462
633
|
this._ref = null;
|
|
463
|
-
if (this.editor.selectMenuOn || this._resizing) return;
|
|
464
634
|
|
|
465
|
-
const keyCode = event.
|
|
635
|
+
const keyCode = event.code;
|
|
636
|
+
const isTab = keyCodeMap.isTab(keyCode);
|
|
637
|
+
if (this.editor.selectMenuOn || this._resizing || (!isTab && this.__s) || keyCodeMap.isCtrl(event)) return;
|
|
638
|
+
|
|
639
|
+
if (!this.cellControllerTop) {
|
|
640
|
+
this.controller_cell.hide();
|
|
641
|
+
}
|
|
642
|
+
|
|
643
|
+
this.__s = keyCodeMap.isShift(event);
|
|
644
|
+
|
|
466
645
|
// table tabkey
|
|
467
|
-
if (
|
|
468
|
-
|
|
469
|
-
|
|
646
|
+
if (isTab) {
|
|
647
|
+
this._deleteStyleSelectedCells();
|
|
648
|
+
const tableCell = dom.query.getParentElement(line, dom.check.isTableCell);
|
|
649
|
+
if (tableCell && range.collapsed && dom.check.isEdgePoint(range.startContainer, range.startOffset)) {
|
|
470
650
|
this._closeController();
|
|
471
651
|
|
|
472
|
-
const shift =
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
652
|
+
const shift = this.__s;
|
|
653
|
+
this._shift = this.__s = false;
|
|
654
|
+
|
|
655
|
+
/** @type {HTMLTableElement} */
|
|
656
|
+
const table = dom.query.getParentElement(tableCell, 'table');
|
|
657
|
+
/** @type {HTMLTableCellElement[]} */
|
|
658
|
+
const cells = dom.query.getListChildren(table, dom.check.isTableCell);
|
|
659
|
+
const idx = shift ? dom.utils.prevIndex(cells, tableCell) : dom.utils.nextIndex(cells, tableCell);
|
|
476
660
|
|
|
477
661
|
if (idx === cells.length && !shift) {
|
|
478
|
-
if (!
|
|
662
|
+
if (!dom.query.getParentElement(tableCell, 'thead')) {
|
|
479
663
|
const rows = table.rows;
|
|
480
|
-
const newRow = this.insertBodyRow(table, rows.length,
|
|
664
|
+
const newRow = this.insertBodyRow(table, rows.length, this._cellCnt);
|
|
481
665
|
const firstTd = newRow.querySelector('td div');
|
|
482
666
|
this.selection.setRange(firstTd, 0, firstTd, 0);
|
|
483
667
|
}
|
|
@@ -488,13 +672,13 @@ Table.prototype = {
|
|
|
488
672
|
return false;
|
|
489
673
|
}
|
|
490
674
|
|
|
491
|
-
if (idx === -1 && shift) return;
|
|
675
|
+
if (idx === -1 && shift) return false;
|
|
492
676
|
|
|
493
|
-
|
|
677
|
+
const moveCell = cells[idx];
|
|
494
678
|
if (!moveCell) return;
|
|
495
679
|
|
|
496
|
-
|
|
497
|
-
this.selection.setRange(
|
|
680
|
+
const rangeCell = moveCell.firstElementChild || moveCell;
|
|
681
|
+
this.selection.setRange(rangeCell, 0, rangeCell, 0);
|
|
498
682
|
|
|
499
683
|
event.preventDefault();
|
|
500
684
|
event.stopPropagation();
|
|
@@ -504,9 +688,9 @@ Table.prototype = {
|
|
|
504
688
|
}
|
|
505
689
|
|
|
506
690
|
let cell = null;
|
|
507
|
-
if (!event
|
|
508
|
-
cell =
|
|
509
|
-
if (!
|
|
691
|
+
if (!keyCodeMap.isShift(event)) {
|
|
692
|
+
cell = dom.query.getParentElement(line, dom.check.isTableCell);
|
|
693
|
+
if (!dom.utils.hasClass(cell, 'se-selected-cell-focus')) return;
|
|
510
694
|
|
|
511
695
|
this._deleteStyleSelectedCells();
|
|
512
696
|
this._toggleEditor(true);
|
|
@@ -518,43 +702,46 @@ Table.prototype = {
|
|
|
518
702
|
|
|
519
703
|
if (this._shift || this._ref) return;
|
|
520
704
|
|
|
521
|
-
cell = cell ||
|
|
705
|
+
cell = /** @type {HTMLTableCellElement} */ (cell || dom.query.getParentElement(line, dom.check.isTableCell));
|
|
522
706
|
if (cell) {
|
|
707
|
+
this.__s = false;
|
|
523
708
|
this._fixedCell = cell;
|
|
524
709
|
this._closeController();
|
|
525
|
-
this
|
|
710
|
+
this.#StyleSelectCells(cell, event.shiftKey);
|
|
526
711
|
return false;
|
|
527
712
|
}
|
|
528
|
-
}
|
|
713
|
+
}
|
|
529
714
|
|
|
530
715
|
/**
|
|
531
|
-
* @
|
|
532
|
-
* @
|
|
533
|
-
* @param {
|
|
534
|
-
* @param {Element} line Current line element
|
|
716
|
+
* @editorMethod Editor.EventManager
|
|
717
|
+
* @description Executes the event function of "keyup".
|
|
718
|
+
* @param {__se__PluginKeyEventInfo} params
|
|
535
719
|
*/
|
|
536
720
|
onKeyUp({ line }) {
|
|
537
|
-
|
|
721
|
+
this.__s = false;
|
|
722
|
+
if (this._shift && dom.query.getParentElement(line, dom.check.isTableCell) === this._fixedCell) {
|
|
538
723
|
this._deleteStyleSelectedCells();
|
|
539
724
|
this._toggleEditor(true);
|
|
540
725
|
this.__removeGlobalEvents();
|
|
541
726
|
}
|
|
542
727
|
this._shift = false;
|
|
543
|
-
}
|
|
728
|
+
}
|
|
544
729
|
|
|
545
730
|
/**
|
|
546
|
-
* @
|
|
731
|
+
* @editorMethod Modules.ColorPicker
|
|
732
|
+
* @description Executes the method called when a button of "ColorPicker" module is clicked.
|
|
733
|
+
* @param {string} color - Color code (hex)
|
|
547
734
|
*/
|
|
548
735
|
colorPickerAction(color) {
|
|
549
736
|
const target = this.propTargets[`${this.sliderType}_color`];
|
|
550
737
|
target.style.borderColor = target.value = color;
|
|
551
738
|
this.controller_colorPicker.close();
|
|
552
|
-
}
|
|
739
|
+
}
|
|
553
740
|
|
|
554
741
|
/**
|
|
555
|
-
* @
|
|
556
|
-
* @
|
|
557
|
-
* @
|
|
742
|
+
* @editorMethod Modules.Controller
|
|
743
|
+
* @description Executes the method that is called when a button is clicked in the "controller".
|
|
744
|
+
* @param {HTMLButtonElement} target Target button element
|
|
558
745
|
*/
|
|
559
746
|
controllerAction(target) {
|
|
560
747
|
const command = target.getAttribute('data-command');
|
|
@@ -614,7 +801,7 @@ Table.prototype = {
|
|
|
614
801
|
this._onColorPalette(target, value, value === 'border' ? border_color : value === 'back' ? back_color : font_color);
|
|
615
802
|
break;
|
|
616
803
|
case 'props_font_style':
|
|
617
|
-
|
|
804
|
+
dom.utils.toggleClass(this.propTargets[`font_${value}`], 'on');
|
|
618
805
|
break;
|
|
619
806
|
case 'props_submit':
|
|
620
807
|
this._submitProps(target);
|
|
@@ -627,7 +814,7 @@ Table.prototype = {
|
|
|
627
814
|
// alignment
|
|
628
815
|
this._setAlignProps(this.propTargets.cell_alignment, this._propsAlignCache, true);
|
|
629
816
|
this._setAlignProps(this.propTargets.cell_alignment_vertical, this._propsVerticalAlignCache, true);
|
|
630
|
-
if (
|
|
817
|
+
if (dom.check.isTable(propsCache[0][0]) && this._figure) {
|
|
631
818
|
this._figure.style.float = this._propsAlignCache;
|
|
632
819
|
}
|
|
633
820
|
break;
|
|
@@ -642,24 +829,31 @@ Table.prototype = {
|
|
|
642
829
|
this._setAlignProps(this.propTargets.cell_alignment_vertical, target.getAttribute('data-value'), false);
|
|
643
830
|
break;
|
|
644
831
|
case 'merge':
|
|
645
|
-
this.mergeCells();
|
|
832
|
+
this.mergeCells(this._selectedCells);
|
|
833
|
+
break;
|
|
834
|
+
case 'unmerge':
|
|
835
|
+
this.unmergeCells(this._selectedCells);
|
|
646
836
|
break;
|
|
647
837
|
case 'resize':
|
|
648
838
|
this._maxWidth = !this._maxWidth;
|
|
649
|
-
this.
|
|
839
|
+
this._setTableStyle('width', false);
|
|
650
840
|
this._historyPush();
|
|
651
|
-
this.component.select(this._element, Table.key, true);
|
|
841
|
+
this.component.select(this._element, Table.key, { isInput: true });
|
|
652
842
|
break;
|
|
653
843
|
case 'layout':
|
|
654
844
|
this._fixedColumn = !this._fixedColumn;
|
|
655
|
-
this.
|
|
845
|
+
this._setTableStyle('column', false);
|
|
656
846
|
this._historyPush();
|
|
657
|
-
this.component.select(this._element, Table.key, true);
|
|
847
|
+
this.component.select(this._element, Table.key, { isInput: true });
|
|
848
|
+
break;
|
|
849
|
+
case 'copy':
|
|
850
|
+
this.component.copy(this._figure);
|
|
658
851
|
break;
|
|
659
852
|
case 'remove': {
|
|
660
853
|
const emptyDiv = this._figure?.parentNode;
|
|
661
|
-
|
|
662
|
-
|
|
854
|
+
dom.utils.removeItem(this._figure);
|
|
855
|
+
|
|
856
|
+
this._closeTableSelectInfo();
|
|
663
857
|
|
|
664
858
|
if (emptyDiv !== this.editor.frameContext.get('wysiwyg'))
|
|
665
859
|
this.nodeTransform.removeAllParents(
|
|
@@ -680,12 +874,13 @@ Table.prototype = {
|
|
|
680
874
|
}
|
|
681
875
|
|
|
682
876
|
if (!/^(remove|props_|on|open|merge)/.test(command)) {
|
|
683
|
-
this.
|
|
877
|
+
this._setCellControllerPosition(this._tdElement, this._shift);
|
|
684
878
|
}
|
|
685
|
-
}
|
|
879
|
+
}
|
|
686
880
|
|
|
687
881
|
/**
|
|
688
|
-
* @
|
|
882
|
+
* @editorMethod Modules.Controller
|
|
883
|
+
* @description Executes the method called when the "controller" is closed.
|
|
689
884
|
*/
|
|
690
885
|
close() {
|
|
691
886
|
this.__removeGlobalEvents();
|
|
@@ -694,7 +889,6 @@ Table.prototype = {
|
|
|
694
889
|
|
|
695
890
|
this._figure = null;
|
|
696
891
|
this._element = null;
|
|
697
|
-
// this._tdElement = null;
|
|
698
892
|
this._trElement = null;
|
|
699
893
|
this._trElements = null;
|
|
700
894
|
this._tableXY = [];
|
|
@@ -719,56 +913,63 @@ Table.prototype = {
|
|
|
719
913
|
this._fixedCellName = null;
|
|
720
914
|
|
|
721
915
|
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
|
-
|
|
723
|
-
}
|
|
724
|
-
|
|
725
|
-
selectCells(tdElement, shift) {
|
|
726
|
-
if (!this._shift && !this._ref) this.__removeGlobalEvents();
|
|
727
|
-
|
|
728
|
-
this._shift = shift;
|
|
729
|
-
this._fixedCell = tdElement;
|
|
730
|
-
this._fixedCellName = tdElement.nodeName;
|
|
731
|
-
this._selectedTable = domUtils.getParentElement(tdElement, 'TABLE');
|
|
916
|
+
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');
|
|
917
|
+
}
|
|
732
918
|
|
|
733
|
-
|
|
734
|
-
|
|
919
|
+
/**
|
|
920
|
+
* @description Selects a group of table cells and sets internal state related to multi-cell selection.
|
|
921
|
+
* @param {HTMLTableCellElement[]} cells - An array of table cell elements to be selected.
|
|
922
|
+
*/
|
|
923
|
+
selectCells(cells) {
|
|
924
|
+
const firstCell = cells[0];
|
|
925
|
+
const lastCell = dom.query.findVisualLastCell(cells);
|
|
735
926
|
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
}
|
|
927
|
+
this._selectedCells = cells;
|
|
928
|
+
this._fixedCell = firstCell;
|
|
929
|
+
this._selectedCell = lastCell;
|
|
930
|
+
this._fixedCellName = firstCell.nodeName;
|
|
931
|
+
this._selectedTable = dom.query.getParentElement(firstCell, 'TABLE');
|
|
742
932
|
|
|
743
|
-
this.
|
|
744
|
-
|
|
745
|
-
},
|
|
933
|
+
this._setMultiCells(firstCell, lastCell);
|
|
934
|
+
}
|
|
746
935
|
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
936
|
+
/**
|
|
937
|
+
* @description Sets the table and figure elements based on the provided cell element, and stores references to them for later use.
|
|
938
|
+
* @param {Node} element The target table cell (`<td>`) element from which the table info will be extracted.
|
|
939
|
+
* @returns {HTMLTableElement} The `<table>` element that is the parent of the provided `element`.
|
|
940
|
+
*/
|
|
941
|
+
setTableInfo(element) {
|
|
942
|
+
const table = (this._element = this._selectedTable = dom.query.getParentElement(element, 'TABLE'));
|
|
943
|
+
this._figure = dom.query.getParentElement(table, dom.check.isFigure) || table;
|
|
944
|
+
return /** @type {HTMLTableElement} */ (table);
|
|
945
|
+
}
|
|
752
946
|
|
|
947
|
+
/**
|
|
948
|
+
* @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.
|
|
949
|
+
* @param {HTMLTableCellElement} tdElement The target table cell (`<td>`) element from which table information will be extracted.
|
|
950
|
+
* @param {boolean} reset A flag indicating whether to reset the cell information. If `true`, the cell information will be reset and recalculated.
|
|
951
|
+
*/
|
|
753
952
|
setCellInfo(tdElement, reset) {
|
|
754
|
-
const table = this.
|
|
755
|
-
|
|
953
|
+
const table = this.setTableInfo(tdElement);
|
|
954
|
+
if (!table) return;
|
|
955
|
+
this._fixedCell = tdElement;
|
|
956
|
+
this._trElement = /** @type {HTMLTableRowElement} */ (tdElement.parentNode);
|
|
756
957
|
|
|
757
958
|
// hedaer
|
|
758
|
-
if (table.querySelector('thead'))
|
|
759
|
-
else
|
|
959
|
+
if (table.querySelector('thead')) dom.utils.addClass(this.headerButton, 'active');
|
|
960
|
+
else dom.utils.removeClass(this.headerButton, 'active');
|
|
760
961
|
|
|
761
962
|
// caption
|
|
762
|
-
if (table.querySelector('caption'))
|
|
763
|
-
else
|
|
963
|
+
if (table.querySelector('caption')) dom.utils.addClass(this.captionButton, 'active');
|
|
964
|
+
else dom.utils.removeClass(this.captionButton, 'active');
|
|
764
965
|
|
|
765
966
|
if (reset || this._physical_cellCnt === 0) {
|
|
766
967
|
if (this._tdElement !== tdElement) {
|
|
767
968
|
this._tdElement = tdElement;
|
|
768
|
-
this._trElement = tdElement.parentNode;
|
|
969
|
+
this._trElement = /** @type {HTMLTableRowElement} */ (tdElement.parentNode);
|
|
769
970
|
}
|
|
770
971
|
|
|
771
|
-
if (!this._selectedCells
|
|
972
|
+
if (!this._selectedCells?.length) this._selectedCells = [tdElement];
|
|
772
973
|
|
|
773
974
|
const rows = (this._trElements = table.rows);
|
|
774
975
|
const cellIndex = tdElement.cellIndex;
|
|
@@ -784,7 +985,7 @@ Table.prototype = {
|
|
|
784
985
|
|
|
785
986
|
// cell cnt, physical cell index
|
|
786
987
|
this._physical_cellCnt = this._trElement.cells.length;
|
|
787
|
-
this._logical_cellCnt = cellCnt;
|
|
988
|
+
this._logical_cellCnt = this._cellCnt = cellCnt;
|
|
788
989
|
this._physical_cellIndex = cellIndex;
|
|
789
990
|
|
|
790
991
|
// span
|
|
@@ -854,30 +1055,39 @@ Table.prototype = {
|
|
|
854
1055
|
rowSpanArr = null;
|
|
855
1056
|
spanIndex = null;
|
|
856
1057
|
}
|
|
857
|
-
}
|
|
1058
|
+
}
|
|
858
1059
|
|
|
1060
|
+
/**
|
|
1061
|
+
* @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.
|
|
1062
|
+
* @param {HTMLTableRowElement} trElement The target table row (`<tr>`) element from which row information will be extracted.
|
|
1063
|
+
*/
|
|
859
1064
|
setRowInfo(trElement) {
|
|
860
|
-
const table = this.
|
|
1065
|
+
const table = this.setTableInfo(trElement);
|
|
861
1066
|
const rows = (this._trElements = table.rows);
|
|
862
1067
|
this._rowCnt = rows.length;
|
|
863
1068
|
this._rowIndex = trElement.rowIndex;
|
|
864
|
-
}
|
|
1069
|
+
}
|
|
865
1070
|
|
|
1071
|
+
/**
|
|
1072
|
+
* @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.
|
|
1073
|
+
* @param {"row"|"cell"} type The type of element to edit ('row' or 'cell').
|
|
1074
|
+
* @param {?"up"|"down"|"left"|"right"} option The action to perform: 'up', 'down', 'left', 'right', or `null` for removing.
|
|
1075
|
+
*/
|
|
866
1076
|
editTable(type, option) {
|
|
867
1077
|
const table = this._element;
|
|
868
1078
|
const isRow = type === 'row';
|
|
869
1079
|
|
|
870
1080
|
if (isRow) {
|
|
871
|
-
const tableAttr = this._trElement.
|
|
1081
|
+
const tableAttr = this._trElement.parentElement;
|
|
872
1082
|
if (/^THEAD$/i.test(tableAttr.nodeName)) {
|
|
873
1083
|
if (option === 'up') {
|
|
874
1084
|
return;
|
|
875
1085
|
} else if (!tableAttr.nextElementSibling || !/^TBODY$/i.test(tableAttr.nextElementSibling.nodeName)) {
|
|
876
1086
|
if (!option) {
|
|
877
|
-
|
|
878
|
-
this.
|
|
1087
|
+
dom.utils.removeItem(this._figure);
|
|
1088
|
+
this._closeTableSelectInfo();
|
|
879
1089
|
} else {
|
|
880
|
-
table.innerHTML += '<tbody><tr>' +
|
|
1090
|
+
table.innerHTML += '<tbody><tr>' + CreateCellsString('td', this._logical_cellCnt) + '</tr></tbody>';
|
|
881
1091
|
}
|
|
882
1092
|
return;
|
|
883
1093
|
}
|
|
@@ -910,7 +1120,7 @@ Table.prototype = {
|
|
|
910
1120
|
} else {
|
|
911
1121
|
// edit row
|
|
912
1122
|
this.setCellInfo(option === 'up' ? selectedCells[0] : selectedCells[selectedCells.length - 1], true);
|
|
913
|
-
this.editRow(option, positionCell);
|
|
1123
|
+
this.editRow(option, null, positionCell);
|
|
914
1124
|
}
|
|
915
1125
|
} else {
|
|
916
1126
|
// multi - cell
|
|
@@ -944,7 +1154,7 @@ Table.prototype = {
|
|
|
944
1154
|
}
|
|
945
1155
|
|
|
946
1156
|
this.setCellInfo(option === 'left' ? selectedCells[0] : rightCell || selectedCells[0], true);
|
|
947
|
-
this.editCell(option, positionCell);
|
|
1157
|
+
this.editCell(option, null, positionCell);
|
|
948
1158
|
}
|
|
949
1159
|
}
|
|
950
1160
|
|
|
@@ -959,16 +1169,28 @@ Table.prototype = {
|
|
|
959
1169
|
const children = table.children;
|
|
960
1170
|
for (let i = 0; i < children.length; i++) {
|
|
961
1171
|
if (children[i].children.length === 0) {
|
|
962
|
-
|
|
1172
|
+
dom.utils.removeItem(children[i]);
|
|
963
1173
|
i--;
|
|
964
1174
|
}
|
|
965
1175
|
}
|
|
966
1176
|
|
|
967
|
-
if (table.children.length === 0)
|
|
1177
|
+
if (table.children.length === 0) dom.utils.removeItem(table);
|
|
968
1178
|
}
|
|
969
|
-
}
|
|
1179
|
+
}
|
|
1180
|
+
|
|
1181
|
+
/**
|
|
1182
|
+
* @description Edits a table row, either adding, removing, the row
|
|
1183
|
+
* @param {?string} option The action to perform on the row ("up"|"down"|null)
|
|
1184
|
+
* - null: to remove the row
|
|
1185
|
+
* - 'up': to insert the row up
|
|
1186
|
+
* - 'down': to insert the row down, or null to remove.
|
|
1187
|
+
* @param {?HTMLTableCellElement=} targetCell Target cell, (default: current selected cell)
|
|
1188
|
+
* @param {?HTMLTableCellElement=} [positionResetElement] The element to reset the position of (optional). This can be the cell that triggered the row edit.
|
|
1189
|
+
*/
|
|
1190
|
+
editRow(option, targetCell, positionResetElement) {
|
|
1191
|
+
this._deleteStyleSelectedCells();
|
|
1192
|
+
if (targetCell) this.setCellInfo(targetCell, true);
|
|
970
1193
|
|
|
971
|
-
editRow(option, positionResetElement) {
|
|
972
1194
|
const remove = !option;
|
|
973
1195
|
const up = option === 'up';
|
|
974
1196
|
const originRowIndex = this._rowIndex;
|
|
@@ -1008,7 +1230,7 @@ Table.prototype = {
|
|
|
1008
1230
|
|
|
1009
1231
|
if (cell.rowSpan > 1) {
|
|
1010
1232
|
cell.rowSpan -= 1;
|
|
1011
|
-
spanCells.push({ cell: cell.cloneNode(false), index: logcalIndex });
|
|
1233
|
+
spanCells.push({ cell: /** @type {HTMLTableCellElement} */ (cell.cloneNode(false)), index: logcalIndex });
|
|
1012
1234
|
}
|
|
1013
1235
|
}
|
|
1014
1236
|
|
|
@@ -1047,13 +1269,25 @@ Table.prototype = {
|
|
|
1047
1269
|
}
|
|
1048
1270
|
|
|
1049
1271
|
if (!remove) {
|
|
1050
|
-
this.
|
|
1272
|
+
this._setCellControllerPosition(positionResetElement || this._tdElement, true);
|
|
1051
1273
|
} else {
|
|
1052
1274
|
this._closeController();
|
|
1053
1275
|
}
|
|
1054
|
-
}
|
|
1276
|
+
}
|
|
1277
|
+
|
|
1278
|
+
/**
|
|
1279
|
+
* @description Edits a table cell(column), either adding, removing, or modifying the cell based on the provided option.
|
|
1280
|
+
* @param {?string} option The action to perform on the cell ("left"|"right"|null)
|
|
1281
|
+
* - null: to remove the cell
|
|
1282
|
+
* - left: to insert a new cell to the left
|
|
1283
|
+
* - right: to insert a new cell to the right
|
|
1284
|
+
* @param {?HTMLTableCellElement=} targetCell Target cell, (default: current selected cell)
|
|
1285
|
+
* @param {?HTMLTableCellElement=} positionResetElement The element to reset the position of (optional). This can be the cell that triggered the column edit.
|
|
1286
|
+
* @returns {HTMLTableCellElement} Target table cell
|
|
1287
|
+
*/
|
|
1288
|
+
editCell(option, targetCell, positionResetElement) {
|
|
1289
|
+
if (targetCell) this.setCellInfo(targetCell, true);
|
|
1055
1290
|
|
|
1056
|
-
editCell(option, positionResetElement) {
|
|
1057
1291
|
const remove = !option;
|
|
1058
1292
|
const left = option === 'left';
|
|
1059
1293
|
const colSpan = this._current_colSpan;
|
|
@@ -1172,7 +1406,7 @@ Table.prototype = {
|
|
|
1172
1406
|
}
|
|
1173
1407
|
|
|
1174
1408
|
if (insertIndex !== null && cells.length > 0) {
|
|
1175
|
-
newCell =
|
|
1409
|
+
newCell = CreateCellsHTML(cells[0].nodeName);
|
|
1176
1410
|
newCell = row.insertBefore(newCell, cells[insertIndex]);
|
|
1177
1411
|
}
|
|
1178
1412
|
}
|
|
@@ -1182,16 +1416,16 @@ Table.prototype = {
|
|
|
1182
1416
|
if (colgroup) {
|
|
1183
1417
|
const cols = colgroup.querySelectorAll('col');
|
|
1184
1418
|
if (remove) {
|
|
1185
|
-
|
|
1419
|
+
dom.utils.removeItem(cols[insertIndex]);
|
|
1186
1420
|
} else {
|
|
1187
1421
|
let totalW = 0;
|
|
1188
1422
|
for (let i = 0, len = cols.length, w; i < len; i++) {
|
|
1189
1423
|
w = numbers.get(cols[i].style.width);
|
|
1190
|
-
w -= Math.round((w * len * 0.1) / 2
|
|
1424
|
+
w -= Math.round((w * len * 0.1) / 2);
|
|
1191
1425
|
totalW += w;
|
|
1192
1426
|
cols[i].style.width = `${w}%`;
|
|
1193
1427
|
}
|
|
1194
|
-
const newCol =
|
|
1428
|
+
const newCol = dom.utils.createElement('col', { style: `width:${100 - totalW}%` });
|
|
1195
1429
|
colgroup.insertBefore(newCol, cols[insertIndex]);
|
|
1196
1430
|
}
|
|
1197
1431
|
}
|
|
@@ -1199,12 +1433,12 @@ Table.prototype = {
|
|
|
1199
1433
|
if (remove) {
|
|
1200
1434
|
let removeFirst, removeEnd;
|
|
1201
1435
|
for (let r = 0, rLen = removeCell.length, row; r < rLen; r++) {
|
|
1202
|
-
row = removeCell[r].parentNode;
|
|
1203
|
-
|
|
1436
|
+
row = /** @type {HTMLTableRowElement} */ (removeCell[r].parentNode);
|
|
1437
|
+
dom.utils.removeItem(removeCell[r]);
|
|
1204
1438
|
if (row.cells.length === 0) {
|
|
1205
|
-
if (!removeFirst) removeFirst =
|
|
1206
|
-
removeEnd =
|
|
1207
|
-
|
|
1439
|
+
if (!removeFirst) removeFirst = dom.utils.getArrayIndex(rows, row);
|
|
1440
|
+
removeEnd = dom.utils.getArrayIndex(rows, row);
|
|
1441
|
+
dom.utils.removeItem(row);
|
|
1208
1442
|
}
|
|
1209
1443
|
}
|
|
1210
1444
|
|
|
@@ -1215,19 +1449,339 @@ Table.prototype = {
|
|
|
1215
1449
|
|
|
1216
1450
|
this._closeController();
|
|
1217
1451
|
} else {
|
|
1218
|
-
this.
|
|
1452
|
+
this._setCellControllerPosition(positionResetElement || this._tdElement, true);
|
|
1453
|
+
}
|
|
1454
|
+
|
|
1455
|
+
return positionResetElement || this._tdElement;
|
|
1456
|
+
}
|
|
1457
|
+
|
|
1458
|
+
/**
|
|
1459
|
+
* @description Updates the target table's cells with the data from the copied table.
|
|
1460
|
+
* @param {HTMLTableElement} copyTable The table containing the copied data.
|
|
1461
|
+
* @param {HTMLTableCellElement} targetTD The starting cell in the target table where data will be pasted.
|
|
1462
|
+
*/
|
|
1463
|
+
pasteTableCellMatrix(copyTable, targetTD) {
|
|
1464
|
+
if (!copyTable || !targetTD) return;
|
|
1465
|
+
|
|
1466
|
+
// --- copy info ---
|
|
1467
|
+
const copyRows = copyTable.rows;
|
|
1468
|
+
let rowCnt = 0;
|
|
1469
|
+
const colIndexMap = [];
|
|
1470
|
+
for (let row = 0; row < copyRows.length; row++) {
|
|
1471
|
+
const cells = copyRows[row].cells;
|
|
1472
|
+
let logicalCol = 0;
|
|
1473
|
+
|
|
1474
|
+
for (let i = 0; i < cells.length; i++) {
|
|
1475
|
+
const cell = cells[i];
|
|
1476
|
+
|
|
1477
|
+
while (colIndexMap[row]?.[logicalCol]) {
|
|
1478
|
+
logicalCol++;
|
|
1479
|
+
}
|
|
1480
|
+
|
|
1481
|
+
const rowspan = cell.rowSpan || 1;
|
|
1482
|
+
const colspan = cell.colSpan || 1;
|
|
1483
|
+
|
|
1484
|
+
if (logicalCol === 0) {
|
|
1485
|
+
rowCnt += rowspan;
|
|
1486
|
+
}
|
|
1487
|
+
|
|
1488
|
+
// rowspan map
|
|
1489
|
+
for (let r = 0; r < rowspan; r++) {
|
|
1490
|
+
for (let c = 0; c < colspan; c++) {
|
|
1491
|
+
if (!colIndexMap[row + r]) colIndexMap[row + r] = [];
|
|
1492
|
+
colIndexMap[row + r][logicalCol + c] = true;
|
|
1493
|
+
}
|
|
1494
|
+
}
|
|
1495
|
+
|
|
1496
|
+
logicalCol += colspan;
|
|
1497
|
+
}
|
|
1498
|
+
}
|
|
1499
|
+
|
|
1500
|
+
let logicalColCount = 0;
|
|
1501
|
+
for (let i = 0, cells = copyRows[0].cells, len = cells.length; i < len; i++) {
|
|
1502
|
+
const cell = cells[i];
|
|
1503
|
+
logicalColCount += cell.colSpan || 1;
|
|
1504
|
+
}
|
|
1505
|
+
|
|
1506
|
+
const copyInfo = {
|
|
1507
|
+
rowCnt: rowCnt,
|
|
1508
|
+
logicalCellCnt: logicalColCount
|
|
1509
|
+
};
|
|
1510
|
+
|
|
1511
|
+
// --- target info ---
|
|
1512
|
+
this._deleteStyleSelectedCells();
|
|
1513
|
+
const originTable = targetTD.closest('table');
|
|
1514
|
+
const { cloneTable, clonedSelectedCells } = this.#cloneTable(originTable, [targetTD]);
|
|
1515
|
+
|
|
1516
|
+
const targetTable = cloneTable;
|
|
1517
|
+
targetTD = clonedSelectedCells[0];
|
|
1518
|
+
let targetRows = targetTable.rows;
|
|
1519
|
+
this.setTableInfo(targetTable);
|
|
1520
|
+
this.setCellInfo(targetTD, true);
|
|
1521
|
+
|
|
1522
|
+
const targetInfo = {
|
|
1523
|
+
physicalCellCnt: this._physical_cellCnt,
|
|
1524
|
+
logicalCellCnt: this._logical_cellCnt,
|
|
1525
|
+
rowCnt: this._rowCnt,
|
|
1526
|
+
rowInex: this._rowIndex,
|
|
1527
|
+
physicalCellIndex: this._physical_cellIndex,
|
|
1528
|
+
logicalCellIndex: this._logical_cellIndex,
|
|
1529
|
+
currentColSpan: this._current_colSpan,
|
|
1530
|
+
currentRowSpan: this._current_rowSpan
|
|
1531
|
+
};
|
|
1532
|
+
|
|
1533
|
+
// --- [expand] target table ---
|
|
1534
|
+
const addRowCnt = copyInfo.rowCnt - (targetInfo.rowCnt - (targetInfo.rowInex + 1)) - 1;
|
|
1535
|
+
const addColCnt = copyInfo.logicalCellCnt - (targetInfo.logicalCellCnt - (targetInfo.logicalCellIndex + 1)) - 1;
|
|
1536
|
+
targetInfo.rowCnt += addRowCnt;
|
|
1537
|
+
targetInfo.logicalCellCnt += addColCnt;
|
|
1538
|
+
targetInfo.physicalCellCnt += addColCnt;
|
|
1539
|
+
|
|
1540
|
+
if (addRowCnt > 0 || addColCnt > 0) {
|
|
1541
|
+
const lastRow = targetRows[targetRows.length - 1];
|
|
1542
|
+
const lastCell = lastRow.cells[lastRow.cells.length - 1];
|
|
1543
|
+
for (let i = 0; i < addRowCnt; i++) {
|
|
1544
|
+
this.editRow('down', lastCell);
|
|
1545
|
+
}
|
|
1546
|
+
for (let i = 0; i < addColCnt; i++) {
|
|
1547
|
+
this.editCell('right', lastCell);
|
|
1548
|
+
}
|
|
1549
|
+
targetRows = this._trElements = targetTable.rows;
|
|
1550
|
+
}
|
|
1551
|
+
|
|
1552
|
+
// --- [Un_merge] cells ---
|
|
1553
|
+
const startRowIndex = targetInfo.rowInex;
|
|
1554
|
+
const cellIndex = targetInfo.logicalCellIndex;
|
|
1555
|
+
const cellEndIndex = cellIndex + copyInfo.logicalCellCnt - 1;
|
|
1556
|
+
const unmergeCells = [];
|
|
1557
|
+
const un_mergeRowSpanMap = [];
|
|
1558
|
+
|
|
1559
|
+
for (let r = 0, len = startRowIndex + copyInfo.rowCnt; r < len; r++) {
|
|
1560
|
+
const cells = targetRows[r]?.cells;
|
|
1561
|
+
if (!cells) continue;
|
|
1562
|
+
|
|
1563
|
+
let logicalIndex = 0;
|
|
1564
|
+
let cellIndexInRow = 0;
|
|
1565
|
+
|
|
1566
|
+
for (let c = 0; c < cells.length; c++) {
|
|
1567
|
+
while (un_mergeRowSpanMap[r]?.[logicalIndex]) {
|
|
1568
|
+
logicalIndex++;
|
|
1569
|
+
}
|
|
1570
|
+
|
|
1571
|
+
const cell = cells[cellIndexInRow++];
|
|
1572
|
+
if (!cell) break;
|
|
1573
|
+
|
|
1574
|
+
const cs = cell.colSpan || 1;
|
|
1575
|
+
const rs = cell.rowSpan || 1;
|
|
1576
|
+
const logicalStart = logicalIndex;
|
|
1577
|
+
const logicalEnd = logicalIndex + cs - 1;
|
|
1578
|
+
|
|
1579
|
+
// rowSpan map
|
|
1580
|
+
if (rs > 1 || cs > 1) {
|
|
1581
|
+
for (let rsOffset = 1; rsOffset < rs; rsOffset++) {
|
|
1582
|
+
const rowIndex = r + rsOffset;
|
|
1583
|
+
if (!un_mergeRowSpanMap[rowIndex]) un_mergeRowSpanMap[rowIndex] = [];
|
|
1584
|
+
for (let csOffset = 0; csOffset < cs; csOffset++) {
|
|
1585
|
+
un_mergeRowSpanMap[rowIndex][logicalIndex + csOffset] = true;
|
|
1586
|
+
}
|
|
1587
|
+
}
|
|
1588
|
+
}
|
|
1589
|
+
|
|
1590
|
+
const isOverlap = logicalStart <= cellEndIndex && logicalEnd >= cellIndex;
|
|
1591
|
+
if (isOverlap && (cs > 1 || rs > 1)) {
|
|
1592
|
+
unmergeCells.push(cell);
|
|
1593
|
+
}
|
|
1594
|
+
|
|
1595
|
+
logicalIndex += cs;
|
|
1596
|
+
}
|
|
1597
|
+
}
|
|
1598
|
+
|
|
1599
|
+
if (unmergeCells.length > 0) {
|
|
1600
|
+
this.unmergeCells(unmergeCells, true);
|
|
1601
|
+
targetRows = this._trElements = targetTable.rows;
|
|
1219
1602
|
}
|
|
1220
|
-
},
|
|
1221
1603
|
|
|
1604
|
+
// --- [merge] cells ---
|
|
1605
|
+
const mergeGroups = [];
|
|
1606
|
+
const copyCowSpanMap = [];
|
|
1607
|
+
const targetRowSpanMap = [];
|
|
1608
|
+
for (let r = 0, len = copyInfo.rowCnt; r < len; r++) {
|
|
1609
|
+
const cells = copyRows[r]?.cells;
|
|
1610
|
+
if (!cells) break;
|
|
1611
|
+
|
|
1612
|
+
let copyIndex = 0;
|
|
1613
|
+
for (let c = 0; c < cells.length; c++) {
|
|
1614
|
+
const cell = cells[c];
|
|
1615
|
+
const cs = cell.colSpan || 1;
|
|
1616
|
+
const rs = cell.rowSpan || 1;
|
|
1617
|
+
|
|
1618
|
+
while (copyCowSpanMap[r]?.[copyIndex]) {
|
|
1619
|
+
copyIndex++;
|
|
1620
|
+
}
|
|
1621
|
+
|
|
1622
|
+
for (let rsOffset = 1; rsOffset < rs; rsOffset++) {
|
|
1623
|
+
const rowIndex = r + rsOffset;
|
|
1624
|
+
if (!copyCowSpanMap[rowIndex]) copyCowSpanMap[rowIndex] = [];
|
|
1625
|
+
for (let csOffset = 0; csOffset < cs; csOffset++) {
|
|
1626
|
+
copyCowSpanMap[rowIndex][copyIndex + csOffset] = true;
|
|
1627
|
+
}
|
|
1628
|
+
}
|
|
1629
|
+
|
|
1630
|
+
if (cs <= 1 && rs <= 1) {
|
|
1631
|
+
copyIndex += cs;
|
|
1632
|
+
continue;
|
|
1633
|
+
}
|
|
1634
|
+
|
|
1635
|
+
const cStart = copyIndex + targetInfo.logicalCellIndex;
|
|
1636
|
+
const cEnd = cStart + cs - 1;
|
|
1637
|
+
const mergeCells = [];
|
|
1638
|
+
|
|
1639
|
+
for (let targetR = targetInfo.rowInex + r, tRowCnt = targetR + rs, rowOffset = 0; targetR < tRowCnt; targetR++, rowOffset++) {
|
|
1640
|
+
const targetRow = targetRows[targetR];
|
|
1641
|
+
const targetCells = targetRow.cells;
|
|
1642
|
+
|
|
1643
|
+
let logicalIndex = 0;
|
|
1644
|
+
let targetIndex = 0;
|
|
1645
|
+
|
|
1646
|
+
while (targetIndex < targetCells.length && logicalIndex <= cEnd) {
|
|
1647
|
+
while (targetRowSpanMap[targetR]?.[logicalIndex]) {
|
|
1648
|
+
logicalIndex++;
|
|
1649
|
+
}
|
|
1650
|
+
|
|
1651
|
+
const tCell = targetCells[targetIndex++];
|
|
1652
|
+
const tcs = tCell.colSpan || 1;
|
|
1653
|
+
const trs = tCell.rowSpan || 1;
|
|
1654
|
+
const logicalStart = logicalIndex;
|
|
1655
|
+
const logicalEnd = logicalIndex + tcs - 1;
|
|
1656
|
+
|
|
1657
|
+
// rowSpan map
|
|
1658
|
+
if (trs > 1) {
|
|
1659
|
+
for (let rsOffset = 1; rsOffset < trs; rsOffset++) {
|
|
1660
|
+
const rIndex = targetR + rsOffset;
|
|
1661
|
+
if (!targetRowSpanMap[rIndex]) targetRowSpanMap[rIndex] = [];
|
|
1662
|
+
for (let i = 0; i < tcs; i++) {
|
|
1663
|
+
targetRowSpanMap[rIndex][logicalIndex + i] = true;
|
|
1664
|
+
}
|
|
1665
|
+
}
|
|
1666
|
+
}
|
|
1667
|
+
|
|
1668
|
+
if (logicalEnd >= cStart && logicalStart <= cEnd) {
|
|
1669
|
+
mergeCells.push(tCell);
|
|
1670
|
+
}
|
|
1671
|
+
|
|
1672
|
+
logicalIndex += tcs;
|
|
1673
|
+
}
|
|
1674
|
+
}
|
|
1675
|
+
|
|
1676
|
+
if (mergeCells.length > 0) {
|
|
1677
|
+
mergeGroups.push(mergeCells);
|
|
1678
|
+
}
|
|
1679
|
+
|
|
1680
|
+
copyIndex += cs;
|
|
1681
|
+
}
|
|
1682
|
+
}
|
|
1683
|
+
|
|
1684
|
+
if (mergeGroups.length > 0) {
|
|
1685
|
+
for (const mc of mergeGroups) {
|
|
1686
|
+
this._ref = null;
|
|
1687
|
+
this._trElements = targetTable.rows;
|
|
1688
|
+
this.mergeCells(mc, true);
|
|
1689
|
+
}
|
|
1690
|
+
targetRows = this._trElements = targetTable.rows;
|
|
1691
|
+
}
|
|
1692
|
+
|
|
1693
|
+
// --- [result] paste cell data ---
|
|
1694
|
+
const selectedCells = [];
|
|
1695
|
+
const rowSpanMap = [];
|
|
1696
|
+
for (let r = 0; r < copyInfo.rowCnt; r++) {
|
|
1697
|
+
const tr = targetRows[targetInfo.rowInex + r];
|
|
1698
|
+
const cr = copyRows[r];
|
|
1699
|
+
if (!tr || !cr) break;
|
|
1700
|
+
|
|
1701
|
+
const tCells = tr.cells;
|
|
1702
|
+
const cCells = cr.cells;
|
|
1703
|
+
|
|
1704
|
+
let tLogicalIndex = 0;
|
|
1705
|
+
let tIndex = 0;
|
|
1706
|
+
let cIndex = 0;
|
|
1707
|
+
|
|
1708
|
+
while (tIndex < tCells.length && cIndex < cCells.length && tLogicalIndex <= cellEndIndex) {
|
|
1709
|
+
while (rowSpanMap[r]?.[tLogicalIndex]) {
|
|
1710
|
+
tLogicalIndex++;
|
|
1711
|
+
}
|
|
1712
|
+
|
|
1713
|
+
const tCell = tCells[tIndex++];
|
|
1714
|
+
const cCell = cCells[cIndex];
|
|
1715
|
+
if (!tCell || !cCell) break;
|
|
1716
|
+
|
|
1717
|
+
const tcs = tCell.colSpan || 1;
|
|
1718
|
+
const trs = tCell.rowSpan || 1;
|
|
1719
|
+
|
|
1720
|
+
// rowSpan map
|
|
1721
|
+
if (trs > 1) {
|
|
1722
|
+
for (let rs = 1; rs < trs; rs++) {
|
|
1723
|
+
const rr = r + rs;
|
|
1724
|
+
if (!rowSpanMap[rr]) rowSpanMap[rr] = [];
|
|
1725
|
+
for (let cs = 0; cs < tcs; cs++) {
|
|
1726
|
+
rowSpanMap[rr][tLogicalIndex + cs] = true;
|
|
1727
|
+
}
|
|
1728
|
+
}
|
|
1729
|
+
}
|
|
1730
|
+
|
|
1731
|
+
if (tLogicalIndex >= cellIndex && tLogicalIndex + tcs - 1 <= cellEndIndex) {
|
|
1732
|
+
tCell.innerHTML = cCell.innerHTML;
|
|
1733
|
+
selectedCells.push(tCell);
|
|
1734
|
+
cIndex++;
|
|
1735
|
+
}
|
|
1736
|
+
|
|
1737
|
+
tLogicalIndex += tcs;
|
|
1738
|
+
}
|
|
1739
|
+
}
|
|
1740
|
+
|
|
1741
|
+
// replace table
|
|
1742
|
+
originTable.replaceWith(targetTable);
|
|
1743
|
+
this._closeTableSelectInfo();
|
|
1744
|
+
this.setTableInfo(targetTable);
|
|
1745
|
+
|
|
1746
|
+
// select cell
|
|
1747
|
+
this.selectCells(selectedCells);
|
|
1748
|
+
this._setMergeSplitButton();
|
|
1749
|
+
this._setUnMergeButton();
|
|
1750
|
+
this.#focusEdge(selectedCells[0]);
|
|
1751
|
+
|
|
1752
|
+
// history push
|
|
1753
|
+
this._historyPush();
|
|
1754
|
+
}
|
|
1755
|
+
|
|
1756
|
+
/**
|
|
1757
|
+
* @description Inserts a new row into the table at the specified index to it.
|
|
1758
|
+
* @param {HTMLTableElement} table The table element to insert the row into.
|
|
1759
|
+
* @param {number} rowIndex The index at which to insert the new row.
|
|
1760
|
+
* @param {number} cellCnt The number of cells to create in the new row.
|
|
1761
|
+
* @returns {HTMLTableRowElement} The newly inserted row element.
|
|
1762
|
+
*/
|
|
1222
1763
|
insertBodyRow(table, rowIndex, cellCnt) {
|
|
1223
1764
|
const newRow = table.insertRow(rowIndex);
|
|
1224
|
-
newRow.innerHTML =
|
|
1765
|
+
newRow.innerHTML = CreateCellsString('td', cellCnt);
|
|
1225
1766
|
return newRow;
|
|
1226
|
-
}
|
|
1767
|
+
}
|
|
1768
|
+
|
|
1769
|
+
/**
|
|
1770
|
+
* @description Merges the selected table cells into one cell by combining their contents and adjusting their row and column spans.
|
|
1771
|
+
* - This method removes the selected cells, consolidates their contents, and applies the appropriate row and column spans to the merged cell.
|
|
1772
|
+
* @param {HTMLTableCellElement[]} selectedCells Cells array
|
|
1773
|
+
* @param {boolean} [skipPostProcess=false] - If true, skips table cloning, cell re-selection, history stack push, and rendering.
|
|
1774
|
+
*/
|
|
1775
|
+
mergeCells(selectedCells, skipPostProcess = false) {
|
|
1776
|
+
const originTable = selectedCells[0].closest('table');
|
|
1777
|
+
const { cloneTable, clonedSelectedCells } = skipPostProcess ? { cloneTable: originTable, clonedSelectedCells: selectedCells } : this.#cloneTable(originTable, selectedCells);
|
|
1778
|
+
|
|
1779
|
+
this.setTableInfo(cloneTable);
|
|
1780
|
+
selectedCells = clonedSelectedCells;
|
|
1781
|
+
this._ref = null;
|
|
1782
|
+
this._setMultiCells(selectedCells[0], dom.query.findVisualLastCell(selectedCells));
|
|
1227
1783
|
|
|
1228
|
-
mergeCells() {
|
|
1229
1784
|
const ref = this._ref;
|
|
1230
|
-
const selectedCells = this._selectedCells;
|
|
1231
1785
|
const mergeCell = selectedCells[0];
|
|
1232
1786
|
|
|
1233
1787
|
let emptyRowFirst = null;
|
|
@@ -1239,17 +1793,17 @@ Table.prototype = {
|
|
|
1239
1793
|
|
|
1240
1794
|
for (let i = 1, len = selectedCells.length, cell, ch; i < len; i++) {
|
|
1241
1795
|
cell = selectedCells[i];
|
|
1242
|
-
if (row !== cell.parentNode) row = cell.parentNode;
|
|
1796
|
+
if (row !== cell.parentNode) row = /** @type {HTMLTableRowElement} */ (cell.parentNode);
|
|
1243
1797
|
|
|
1244
1798
|
ch = cell.children;
|
|
1245
1799
|
for (let c = 0, cLen = ch.length; c < cLen; c++) {
|
|
1246
|
-
if (this.format.isLine(ch[c]) &&
|
|
1247
|
-
|
|
1800
|
+
if (this.format.isLine(ch[c]) && dom.check.isZeroWidth(ch[c].textContent)) {
|
|
1801
|
+
dom.utils.removeItem(ch[c]);
|
|
1248
1802
|
}
|
|
1249
1803
|
}
|
|
1250
1804
|
|
|
1251
1805
|
mergeHTML += cell.innerHTML;
|
|
1252
|
-
|
|
1806
|
+
dom.utils.removeItem(cell);
|
|
1253
1807
|
|
|
1254
1808
|
if (row.cells.length === 0) {
|
|
1255
1809
|
if (!emptyRowFirst) emptyRowFirst = row;
|
|
@@ -1260,8 +1814,8 @@ Table.prototype = {
|
|
|
1260
1814
|
|
|
1261
1815
|
if (emptyRowFirst) {
|
|
1262
1816
|
const rows = this._trElements;
|
|
1263
|
-
const rowIndexFirst =
|
|
1264
|
-
const rowIndexLast =
|
|
1817
|
+
const rowIndexFirst = dom.utils.getArrayIndex(rows, emptyRowFirst);
|
|
1818
|
+
const rowIndexLast = dom.utils.getArrayIndex(rows, emptyRowLast || emptyRowFirst);
|
|
1265
1819
|
const removeRows = [];
|
|
1266
1820
|
|
|
1267
1821
|
for (let i = 0, cells; i <= rowIndexLast; i++) {
|
|
@@ -1281,7 +1835,7 @@ Table.prototype = {
|
|
|
1281
1835
|
}
|
|
1282
1836
|
|
|
1283
1837
|
for (let i = 0, len = removeRows.length; i < len; i++) {
|
|
1284
|
-
|
|
1838
|
+
dom.utils.removeItem(removeRows[i]);
|
|
1285
1839
|
}
|
|
1286
1840
|
}
|
|
1287
1841
|
|
|
@@ -1289,53 +1843,171 @@ Table.prototype = {
|
|
|
1289
1843
|
mergeCell.colSpan = cs;
|
|
1290
1844
|
mergeCell.rowSpan = rs;
|
|
1291
1845
|
|
|
1292
|
-
|
|
1293
|
-
this.setController(mergeCell);
|
|
1846
|
+
if (skipPostProcess) return;
|
|
1294
1847
|
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1848
|
+
// replace table
|
|
1849
|
+
originTable.replaceWith(cloneTable);
|
|
1850
|
+
this._closeTableSelectInfo();
|
|
1298
1851
|
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
const active = domUtils.hasClass(btn, 'active');
|
|
1302
|
-
const table = this._element;
|
|
1852
|
+
this._setMergeSplitButton();
|
|
1853
|
+
this._setController(mergeCell);
|
|
1303
1854
|
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1855
|
+
this.#focusEdge(mergeCell);
|
|
1856
|
+
|
|
1857
|
+
// history push
|
|
1858
|
+
this._historyPush();
|
|
1859
|
+
}
|
|
1860
|
+
|
|
1861
|
+
/**
|
|
1862
|
+
* @description Unmerges a table cell that has been merged using rowspan and/or colspan.
|
|
1863
|
+
* @param {HTMLTableCellElement[]} selectedCells - Cells array
|
|
1864
|
+
* @param {boolean} [skipPostProcess=false] - If true, skips table cloning, cell re-selection, history stack push, and rendering.
|
|
1865
|
+
*/
|
|
1866
|
+
unmergeCells(selectedCells, skipPostProcess = false) {
|
|
1867
|
+
if (!selectedCells?.length) return;
|
|
1868
|
+
|
|
1869
|
+
const originTable = selectedCells[0].closest('table');
|
|
1870
|
+
const { cloneTable, clonedSelectedCells } = skipPostProcess ? { cloneTable: originTable, clonedSelectedCells: selectedCells } : this.#cloneTable(originTable, selectedCells);
|
|
1871
|
+
|
|
1872
|
+
this._ref = null;
|
|
1873
|
+
this.setTableInfo(cloneTable);
|
|
1874
|
+
selectedCells = clonedSelectedCells;
|
|
1875
|
+
|
|
1876
|
+
let firstCell = selectedCells[0];
|
|
1877
|
+
let lastCell = dom.query.findVisualLastCell(selectedCells);
|
|
1878
|
+
let newLastCell = null;
|
|
1879
|
+
|
|
1880
|
+
const table = firstCell.closest('table');
|
|
1881
|
+
const rows = table.rows;
|
|
1882
|
+
|
|
1883
|
+
for (const cell of selectedCells) {
|
|
1884
|
+
const tr = /** @type {HTMLTableRowElement} */ (cell.parentElement);
|
|
1885
|
+
const rowIndex = tr.rowIndex;
|
|
1886
|
+
const colIndex = cell.cellIndex;
|
|
1887
|
+
const rowspan = cell.rowSpan;
|
|
1888
|
+
const colspan = cell.colSpan;
|
|
1889
|
+
|
|
1890
|
+
if (rowspan === 1 && colspan === 1) continue;
|
|
1891
|
+
|
|
1892
|
+
this.setCellInfo(cell, true);
|
|
1893
|
+
|
|
1894
|
+
const originalHTML = cell.innerHTML;
|
|
1895
|
+
cell.remove();
|
|
1896
|
+
|
|
1897
|
+
for (let r = 0; r < rowspan; r++) {
|
|
1898
|
+
const targetRow = rows[rowIndex + r];
|
|
1899
|
+
|
|
1900
|
+
for (let c = 0; c < colspan; c++) {
|
|
1901
|
+
const newCell = CreateCellsHTML('td');
|
|
1902
|
+
|
|
1903
|
+
if (r === 0 && c === 0) {
|
|
1904
|
+
if (firstCell === cell) firstCell = newCell;
|
|
1905
|
+
if (lastCell === cell) lastCell = newCell;
|
|
1906
|
+
newCell.innerHTML = originalHTML;
|
|
1907
|
+
targetRow.insertBefore(newCell, targetRow.cells[colIndex]);
|
|
1908
|
+
} else {
|
|
1909
|
+
targetRow.insertBefore(newCell, targetRow.cells[colIndex + c]);
|
|
1910
|
+
newLastCell = newCell;
|
|
1911
|
+
}
|
|
1912
|
+
}
|
|
1913
|
+
}
|
|
1914
|
+
}
|
|
1915
|
+
|
|
1916
|
+
this._selectedCells = null;
|
|
1917
|
+
|
|
1918
|
+
if (skipPostProcess) return;
|
|
1919
|
+
|
|
1920
|
+
// replace table
|
|
1921
|
+
originTable.replaceWith(cloneTable);
|
|
1922
|
+
this._closeTableSelectInfo();
|
|
1923
|
+
this.setTableInfo(cloneTable);
|
|
1924
|
+
|
|
1925
|
+
// set info
|
|
1926
|
+
if (firstCell !== lastCell) {
|
|
1927
|
+
lastCell = !newLastCell || lastCell.closest('tr').rowIndex > newLastCell.closest('tr').rowIndex || lastCell.cellIndex > newLastCell.cellIndex ? lastCell : newLastCell;
|
|
1928
|
+
this._setMultiCells(firstCell, lastCell);
|
|
1929
|
+
this._selectedCells = Array.from(table.querySelectorAll('.se-selected-table-cell'));
|
|
1930
|
+
} else {
|
|
1931
|
+
this.setCellInfo(lastCell, true);
|
|
1932
|
+
}
|
|
1933
|
+
|
|
1934
|
+
this._fixedCell = firstCell;
|
|
1935
|
+
this._selectedCell = lastCell;
|
|
1936
|
+
dom.utils.addClass(lastCell, 'se-selected-cell-focus');
|
|
1937
|
+
|
|
1938
|
+
this._setUnMergeButton();
|
|
1939
|
+
this.controller_cell.resetPosition(lastCell);
|
|
1940
|
+
|
|
1941
|
+
// history push
|
|
1942
|
+
this._historyPush();
|
|
1943
|
+
}
|
|
1944
|
+
|
|
1945
|
+
/**
|
|
1946
|
+
* @description Find merged cells
|
|
1947
|
+
* @param {HTMLTableCellElement[]} cells - Cells array
|
|
1948
|
+
*/
|
|
1949
|
+
findMergedCells(cells) {
|
|
1950
|
+
const mergedCells = [];
|
|
1951
|
+
cells?.forEach((cell) => {
|
|
1952
|
+
if (cell && (cell.rowSpan > 1 || cell.colSpan > 1)) {
|
|
1953
|
+
mergedCells.push(cell);
|
|
1954
|
+
}
|
|
1955
|
+
});
|
|
1956
|
+
return mergedCells;
|
|
1957
|
+
}
|
|
1958
|
+
|
|
1959
|
+
/**
|
|
1960
|
+
* @description Toggles the visibility of the table header (`<thead>`). If the header is present, it is removed; if absent, it is added.
|
|
1961
|
+
*/
|
|
1962
|
+
toggleHeader() {
|
|
1963
|
+
const btn = this.headerButton;
|
|
1964
|
+
const active = dom.utils.hasClass(btn, 'active');
|
|
1965
|
+
const table = this._element;
|
|
1966
|
+
|
|
1967
|
+
if (!active) {
|
|
1968
|
+
const header = dom.utils.createElement('THEAD');
|
|
1969
|
+
header.innerHTML = '<tr>' + CreateCellsString('th', this._logical_cellCnt) + '</tr>';
|
|
1307
1970
|
table.insertBefore(header, table.firstElementChild);
|
|
1308
1971
|
} else {
|
|
1309
|
-
|
|
1972
|
+
dom.utils.removeItem(table.querySelector('thead'));
|
|
1310
1973
|
}
|
|
1311
1974
|
|
|
1312
|
-
|
|
1975
|
+
dom.utils.toggleClass(btn, 'active');
|
|
1313
1976
|
|
|
1314
1977
|
if (/TH/i.test(this._tdElement.nodeName)) {
|
|
1315
1978
|
this._closeController();
|
|
1316
1979
|
} else {
|
|
1317
|
-
this.
|
|
1980
|
+
this._setCellControllerPosition(this._tdElement, false);
|
|
1318
1981
|
}
|
|
1319
|
-
}
|
|
1982
|
+
}
|
|
1320
1983
|
|
|
1984
|
+
/**
|
|
1985
|
+
* @description Toggles the visibility of the table caption (`<caption>`). If the caption is present, it is removed; if absent, it is added.
|
|
1986
|
+
*/
|
|
1321
1987
|
toggleCaption() {
|
|
1322
1988
|
const btn = this.captionButton;
|
|
1323
|
-
const active =
|
|
1989
|
+
const active = dom.utils.hasClass(btn, 'active');
|
|
1324
1990
|
const table = this._element;
|
|
1325
1991
|
|
|
1326
1992
|
if (!active) {
|
|
1327
|
-
const caption =
|
|
1993
|
+
const caption = dom.utils.createElement('CAPTION', { class: `se-table-caption-${this.captionPosition}` });
|
|
1328
1994
|
caption.innerHTML = '<div><br></div>';
|
|
1329
1995
|
table.insertBefore(caption, table.firstElementChild);
|
|
1330
1996
|
} else {
|
|
1331
|
-
|
|
1997
|
+
dom.utils.removeItem(table.querySelector('caption'));
|
|
1332
1998
|
}
|
|
1333
1999
|
|
|
1334
|
-
|
|
1335
|
-
this.
|
|
1336
|
-
}
|
|
2000
|
+
dom.utils.toggleClass(btn, 'active');
|
|
2001
|
+
this._setCellControllerPosition(this._tdElement, false);
|
|
2002
|
+
}
|
|
1337
2003
|
|
|
1338
|
-
|
|
2004
|
+
/**
|
|
2005
|
+
* @private
|
|
2006
|
+
* @description Updates table styles.
|
|
2007
|
+
* @param {string} styles - Styles to update.
|
|
2008
|
+
* @param {boolean} ondisplay - Whether to update display.
|
|
2009
|
+
*/
|
|
2010
|
+
_setTableStyle(styles, ondisplay) {
|
|
1339
2011
|
if (styles.includes('width')) {
|
|
1340
2012
|
const targets = this._figure;
|
|
1341
2013
|
if (!targets) return;
|
|
@@ -1351,92 +2023,114 @@ Table.prototype = {
|
|
|
1351
2023
|
if (!ondisplay) targets.style.width = '100%';
|
|
1352
2024
|
}
|
|
1353
2025
|
|
|
1354
|
-
|
|
1355
|
-
|
|
2026
|
+
dom.utils.changeElement(this.resizeButton.firstElementChild, sizeIcon);
|
|
2027
|
+
dom.utils.changeTxt(this.resizeText, text);
|
|
1356
2028
|
}
|
|
1357
2029
|
|
|
1358
2030
|
if (styles.includes('column')) {
|
|
1359
2031
|
if (!this._fixedColumn) {
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
|
|
2032
|
+
dom.utils.removeClass(this._element, 'se-table-layout-fixed');
|
|
2033
|
+
dom.utils.addClass(this._element, 'se-table-layout-auto');
|
|
2034
|
+
dom.utils.removeClass(this.columnFixedButton, 'active');
|
|
1363
2035
|
} else {
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
|
|
2036
|
+
dom.utils.removeClass(this._element, 'se-table-layout-auto');
|
|
2037
|
+
dom.utils.addClass(this._element, 'se-table-layout-fixed');
|
|
2038
|
+
dom.utils.addClass(this.columnFixedButton, 'active');
|
|
1367
2039
|
}
|
|
1368
2040
|
}
|
|
1369
|
-
}
|
|
2041
|
+
}
|
|
1370
2042
|
|
|
1371
|
-
|
|
1372
|
-
|
|
2043
|
+
/**
|
|
2044
|
+
* @private
|
|
2045
|
+
* @description Sets the merge/split button visibility.
|
|
2046
|
+
*/
|
|
2047
|
+
_setMergeSplitButton() {
|
|
2048
|
+
if (!this._ref) {
|
|
1373
2049
|
this.splitButton.style.display = 'block';
|
|
1374
2050
|
this.mergeButton.style.display = 'none';
|
|
1375
2051
|
} else {
|
|
1376
2052
|
this.splitButton.style.display = 'none';
|
|
1377
2053
|
this.mergeButton.style.display = 'block';
|
|
1378
2054
|
}
|
|
1379
|
-
}
|
|
2055
|
+
}
|
|
1380
2056
|
|
|
1381
2057
|
/**
|
|
1382
|
-
* @
|
|
1383
|
-
* @
|
|
2058
|
+
* @private
|
|
2059
|
+
* @description Sets the unmerge button visibility.
|
|
1384
2060
|
*/
|
|
1385
|
-
|
|
1386
|
-
this.
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
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
|
-
},
|
|
2061
|
+
_setUnMergeButton() {
|
|
2062
|
+
if (this.findMergedCells(!this._selectedCells?.length ? [this._fixedCell] : this._selectedCells).length > 0) {
|
|
2063
|
+
this.unmergeButton.disabled = false;
|
|
2064
|
+
} else {
|
|
2065
|
+
this.unmergeButton.disabled = true;
|
|
2066
|
+
}
|
|
2067
|
+
}
|
|
1405
2068
|
|
|
1406
|
-
|
|
2069
|
+
/**
|
|
2070
|
+
* @private
|
|
2071
|
+
* @description Sets the controller position for a cell.
|
|
2072
|
+
* @param {HTMLTableCellElement} tdElement - The target table cell.
|
|
2073
|
+
*/
|
|
2074
|
+
_setController(tdElement) {
|
|
1407
2075
|
if (!this.selection.get().isCollapsed && !this._selectedCell) {
|
|
1408
2076
|
this._deleteStyleSelectedCells();
|
|
1409
2077
|
return;
|
|
1410
2078
|
}
|
|
1411
2079
|
|
|
2080
|
+
this._setUnMergeButton();
|
|
2081
|
+
|
|
1412
2082
|
this._tdElement = tdElement;
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
this.
|
|
1416
|
-
|
|
2083
|
+
if (this._fixedCell === tdElement) dom.utils.addClass(tdElement, 'se-selected-cell-focus');
|
|
2084
|
+
if (!this._selectedCells?.length) this._selectedCells = [tdElement];
|
|
2085
|
+
const tableElement = this._selectedTable || this._element || dom.query.getParentElement(tdElement, 'TABLE');
|
|
2086
|
+
this.component.select(tableElement, Table.key, { isInput: true });
|
|
2087
|
+
}
|
|
1417
2088
|
|
|
1418
|
-
|
|
2089
|
+
/**
|
|
2090
|
+
* @private
|
|
2091
|
+
* @description Sets the position of the cell controller.
|
|
2092
|
+
* @param {HTMLTableCellElement} tdElement - The target table cell.
|
|
2093
|
+
* @param {boolean} reset - Whether to reset the controller position.
|
|
2094
|
+
*/
|
|
2095
|
+
_setCellControllerPosition(tdElement, reset) {
|
|
1419
2096
|
this.setCellInfo(tdElement, reset);
|
|
1420
|
-
this.controller_cell.resetPosition(this.cellControllerTop ?
|
|
1421
|
-
}
|
|
2097
|
+
this.controller_cell.resetPosition(this.cellControllerTop ? dom.query.getParentElement(tdElement, dom.check.isTable) : tdElement);
|
|
2098
|
+
}
|
|
1422
2099
|
|
|
2100
|
+
/**
|
|
2101
|
+
* @private
|
|
2102
|
+
* @description Adds a new entry to the history stack.
|
|
2103
|
+
*/
|
|
1423
2104
|
_historyPush() {
|
|
1424
2105
|
this._deleteStyleSelectedCells();
|
|
1425
2106
|
this.history.push(false);
|
|
1426
2107
|
this._recallStyleSelectedCells();
|
|
1427
|
-
}
|
|
2108
|
+
}
|
|
1428
2109
|
|
|
2110
|
+
/**
|
|
2111
|
+
* @private
|
|
2112
|
+
* @description Opens the figure.
|
|
2113
|
+
* @param {Node} target - The target figure element.
|
|
2114
|
+
*/
|
|
1429
2115
|
_figureOpen(target) {
|
|
1430
2116
|
this.figure.open(target, { nonResizing: true, nonSizeInfo: true, nonBorder: true, figureTarget: true, __fileManagerInfo: false });
|
|
1431
|
-
}
|
|
2117
|
+
}
|
|
1432
2118
|
|
|
2119
|
+
/**
|
|
2120
|
+
* @private
|
|
2121
|
+
* @description Starts resizing a table cell.
|
|
2122
|
+
* @param {HTMLElement} col The column element.
|
|
2123
|
+
* @param {number} startX The starting X position.
|
|
2124
|
+
* @param {number} startWidth The initial width of the column.
|
|
2125
|
+
* @param {boolean} isLeftEdge Whether the resizing is on the left edge.
|
|
2126
|
+
*/
|
|
1433
2127
|
_startCellResizing(col, startX, startWidth, isLeftEdge) {
|
|
1434
2128
|
this._setResizeLinePosition(this._figure, this._tdElement, this._resizeLinePrev, isLeftEdge);
|
|
1435
2129
|
this._resizeLinePrev.style.display = 'block';
|
|
1436
2130
|
const prevValue = col.style.width;
|
|
1437
|
-
const nextCol = col.nextElementSibling;
|
|
2131
|
+
const nextCol = /** @type {HTMLElement} */ (col.nextElementSibling);
|
|
1438
2132
|
const nextColPrevValue = nextCol.style.width;
|
|
1439
|
-
const realWidth =
|
|
2133
|
+
const realWidth = dom.utils.hasClass(this._element, 'se-table-layout-fixed') ? nextColPrevValue : converter.getWidthInPercentage(col);
|
|
1440
2134
|
|
|
1441
2135
|
if (_DragHandle.get('__dragHandler')) _DragHandle.get('__dragHandler').style.display = 'none';
|
|
1442
2136
|
this._addResizeGlobalEvents(
|
|
@@ -1457,16 +2151,31 @@ Table.prototype = {
|
|
|
1457
2151
|
() => {
|
|
1458
2152
|
this.__removeGlobalEvents();
|
|
1459
2153
|
this.history.push(true);
|
|
1460
|
-
|
|
1461
|
-
this.component.select(this._element, Table.key, true);
|
|
2154
|
+
this.component.select(this._element, Table.key, { isInput: true });
|
|
1462
2155
|
},
|
|
1463
2156
|
(e) => {
|
|
1464
2157
|
this._stopResize(col, prevValue, 'width', e);
|
|
1465
2158
|
this._stopResize(nextCol, nextColPrevValue, 'width', e);
|
|
1466
2159
|
}
|
|
1467
2160
|
);
|
|
1468
|
-
}
|
|
2161
|
+
}
|
|
1469
2162
|
|
|
2163
|
+
/**
|
|
2164
|
+
* @private
|
|
2165
|
+
* @description Resizes a table cell.
|
|
2166
|
+
* @param {HTMLElement} col The column element.
|
|
2167
|
+
* @param {HTMLElement} nextCol The next column element.
|
|
2168
|
+
* @param {HTMLElement} figure The table figure element.
|
|
2169
|
+
* @param {HTMLElement} tdEl The table cell element.
|
|
2170
|
+
* @param {HTMLElement} resizeLine The resize line element.
|
|
2171
|
+
* @param {boolean} isLeftEdge Whether the resizing is on the left edge.
|
|
2172
|
+
* @param {number} startX The starting X position.
|
|
2173
|
+
* @param {number} startWidth The initial width of the column.
|
|
2174
|
+
* @param {number} prevWidthPercent The previous width percentage.
|
|
2175
|
+
* @param {number} nextColWidthPercent The next column's width percentage.
|
|
2176
|
+
* @param {number} tableWidth The total width of the table.
|
|
2177
|
+
* @param {MouseEvent} e The mouse event.
|
|
2178
|
+
*/
|
|
1470
2179
|
_cellResize(col, nextCol, figure, tdEl, resizeLine, isLeftEdge, startX, startWidth, prevWidthPercent, nextColWidthPercent, tableWidth, e) {
|
|
1471
2180
|
const deltaX = e.clientX - startX;
|
|
1472
2181
|
const newWidthPx = startWidth + deltaX;
|
|
@@ -1478,8 +2187,15 @@ Table.prototype = {
|
|
|
1478
2187
|
nextCol.style.width = `${nextColWidthPercent + delta}%`;
|
|
1479
2188
|
this._setResizeLinePosition(figure, tdEl, resizeLine, isLeftEdge);
|
|
1480
2189
|
}
|
|
1481
|
-
}
|
|
2190
|
+
}
|
|
1482
2191
|
|
|
2192
|
+
/**
|
|
2193
|
+
* @private
|
|
2194
|
+
* @description Starts resizing a table row.
|
|
2195
|
+
* @param {HTMLElement} row The table row element.
|
|
2196
|
+
* @param {number} startY The starting Y position.
|
|
2197
|
+
* @param {number} startHeight The initial height of the row.
|
|
2198
|
+
*/
|
|
1483
2199
|
_startRowResizing(row, startY, startHeight) {
|
|
1484
2200
|
this._setResizeRowPosition(this._figure, row, this._resizeLinePrev);
|
|
1485
2201
|
this._resizeLinePrev.style.display = 'block';
|
|
@@ -1488,20 +2204,36 @@ Table.prototype = {
|
|
|
1488
2204
|
this._addResizeGlobalEvents(
|
|
1489
2205
|
this._rowResize.bind(this, row, this._figure, this._resizeLine, startY, startHeight),
|
|
1490
2206
|
() => {
|
|
1491
|
-
this.__removeGlobalEvents(
|
|
2207
|
+
this.__removeGlobalEvents();
|
|
1492
2208
|
this.history.push(true);
|
|
1493
2209
|
},
|
|
1494
2210
|
this._stopResize.bind(this, row, prevValue, 'height')
|
|
1495
2211
|
);
|
|
1496
|
-
}
|
|
2212
|
+
}
|
|
1497
2213
|
|
|
2214
|
+
/**
|
|
2215
|
+
* @private
|
|
2216
|
+
* @description Resizes a table row.
|
|
2217
|
+
* @param {HTMLElement} row The table row element.
|
|
2218
|
+
* @param {HTMLElement} figure The table figure element.
|
|
2219
|
+
* @param {HTMLElement} resizeLine The resize line element.
|
|
2220
|
+
* @param {number} startY The starting Y position.
|
|
2221
|
+
* @param {number} startHeight The initial height of the row.
|
|
2222
|
+
* @param {MouseEvent} e The mouse event.
|
|
2223
|
+
*/
|
|
1498
2224
|
_rowResize(row, figure, resizeLine, startY, startHeight, e) {
|
|
1499
2225
|
const deltaY = e.clientY - startY;
|
|
1500
2226
|
const newHeightPx = startHeight + deltaY;
|
|
1501
2227
|
row.style.height = `${newHeightPx}px`;
|
|
1502
2228
|
this._setResizeRowPosition(figure, row, resizeLine);
|
|
1503
|
-
}
|
|
2229
|
+
}
|
|
1504
2230
|
|
|
2231
|
+
/**
|
|
2232
|
+
* @private
|
|
2233
|
+
* @description Starts resizing the table figure.
|
|
2234
|
+
* @param {number} startX The starting X position.
|
|
2235
|
+
* @param {boolean} isLeftEdge Whether the resizing is on the left edge.
|
|
2236
|
+
*/
|
|
1505
2237
|
_startFigureResizing(startX, isLeftEdge) {
|
|
1506
2238
|
const figure = this._figure;
|
|
1507
2239
|
this._setResizeLinePosition(figure, figure, this._resizeLinePrev, isLeftEdge);
|
|
@@ -1514,12 +2246,23 @@ Table.prototype = {
|
|
|
1514
2246
|
() => {
|
|
1515
2247
|
this.__removeGlobalEvents();
|
|
1516
2248
|
// figure reopen
|
|
1517
|
-
this.component.select(this._element, Table.key, true);
|
|
2249
|
+
this.component.select(this._element, Table.key, { isInput: true });
|
|
1518
2250
|
},
|
|
1519
2251
|
this._stopResize.bind(this, figure, figure.style.width, 'width')
|
|
1520
2252
|
);
|
|
1521
|
-
}
|
|
2253
|
+
}
|
|
1522
2254
|
|
|
2255
|
+
/**
|
|
2256
|
+
* @private
|
|
2257
|
+
* @description Resizes the table figure.
|
|
2258
|
+
* @param {HTMLElement} figure The table figure element.
|
|
2259
|
+
* @param {HTMLElement} resizeLine The resize line element.
|
|
2260
|
+
* @param {boolean} isLeftEdge Whether the resizing is on the left edge.
|
|
2261
|
+
* @param {number} startX The starting X position.
|
|
2262
|
+
* @param {number} startWidth The initial width of the figure.
|
|
2263
|
+
* @param {number} constNum A constant number used for width calculation.
|
|
2264
|
+
* @param {MouseEvent} e The mouse event.
|
|
2265
|
+
*/
|
|
1523
2266
|
_figureResize(figure, resizeLine, isLeftEdge, startX, startWidth, constNum, e) {
|
|
1524
2267
|
const deltaX = isLeftEdge ? startX - e.clientX : e.clientX - startX;
|
|
1525
2268
|
const newWidthPx = startWidth + deltaX;
|
|
@@ -1529,78 +2272,128 @@ Table.prototype = {
|
|
|
1529
2272
|
figure.style.width = `${newWidthPercent}%`;
|
|
1530
2273
|
this._setResizeLinePosition(figure, figure, resizeLine, isLeftEdge);
|
|
1531
2274
|
}
|
|
1532
|
-
}
|
|
2275
|
+
}
|
|
1533
2276
|
|
|
2277
|
+
/**
|
|
2278
|
+
* @private
|
|
2279
|
+
* @description Sets the resize line position.
|
|
2280
|
+
* @param {HTMLElement} figure The table figure element.
|
|
2281
|
+
* @param {HTMLElement} target The target element.
|
|
2282
|
+
* @param {HTMLElement} resizeLine The resize line element.
|
|
2283
|
+
* @param {boolean} isLeftEdge Whether the resizing is on the left edge.
|
|
2284
|
+
*/
|
|
1534
2285
|
_setResizeLinePosition(figure, target, resizeLine, isLeftEdge) {
|
|
1535
2286
|
const tdOffset = this.offset.getLocal(target);
|
|
1536
2287
|
const tableOffset = this.offset.getLocal(figure);
|
|
1537
2288
|
resizeLine.style.left = `${tdOffset.left + (isLeftEdge ? 0 : target.offsetWidth)}px`;
|
|
1538
2289
|
resizeLine.style.top = `${tableOffset.top}px`;
|
|
1539
2290
|
resizeLine.style.height = `${figure.offsetHeight}px`;
|
|
1540
|
-
}
|
|
2291
|
+
}
|
|
1541
2292
|
|
|
2293
|
+
/**
|
|
2294
|
+
* @private
|
|
2295
|
+
* @description Sets the resize row position.
|
|
2296
|
+
* @param {HTMLElement} figure The table figure element.
|
|
2297
|
+
* @param {HTMLElement} target The target row element.
|
|
2298
|
+
* @param {HTMLElement} resizeLine The resize line element.
|
|
2299
|
+
*/
|
|
1542
2300
|
_setResizeRowPosition(figure, target, resizeLine) {
|
|
1543
2301
|
const rowOffset = this.offset.getLocal(target);
|
|
1544
2302
|
const tableOffset = this.offset.getLocal(figure);
|
|
1545
2303
|
resizeLine.style.top = `${rowOffset.top + target.offsetHeight}px`;
|
|
1546
2304
|
resizeLine.style.left = `${tableOffset.left}px`;
|
|
1547
2305
|
resizeLine.style.width = `${figure.offsetWidth}px`;
|
|
1548
|
-
}
|
|
2306
|
+
}
|
|
1549
2307
|
|
|
2308
|
+
/**
|
|
2309
|
+
* @private
|
|
2310
|
+
* @description Stops resizing the table.
|
|
2311
|
+
* @param {HTMLElement} target The target element.
|
|
2312
|
+
* @param {string} prevValue The previous style value.
|
|
2313
|
+
* @param {string} styleProp The CSS property being changed.
|
|
2314
|
+
* @param {KeyboardEvent} e The keyboard event.
|
|
2315
|
+
*/
|
|
1550
2316
|
_stopResize(target, prevValue, styleProp, e) {
|
|
1551
|
-
if (e.
|
|
2317
|
+
if (!keyCodeMap.isEsc(e.code)) return;
|
|
1552
2318
|
this.__removeGlobalEvents();
|
|
1553
2319
|
target.style[styleProp] = prevValue;
|
|
1554
2320
|
// figure reopen
|
|
1555
2321
|
if (styleProp === 'width') {
|
|
1556
|
-
this.component.select(this._element, Table.key, true);
|
|
2322
|
+
this.component.select(this._element, Table.key, { isInput: true });
|
|
1557
2323
|
}
|
|
1558
|
-
}
|
|
2324
|
+
}
|
|
1559
2325
|
|
|
2326
|
+
/**
|
|
2327
|
+
* @private
|
|
2328
|
+
* @description Deletes styles from selected table cells.
|
|
2329
|
+
*/
|
|
1560
2330
|
_deleteStyleSelectedCells() {
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
2331
|
+
dom.utils.removeClass([this._fixedCell, this._selectedCell], 'se-selected-cell-focus');
|
|
2332
|
+
const table = this._fixedCell?.closest('table');
|
|
2333
|
+
if (table) {
|
|
2334
|
+
const selectedCells = table.querySelectorAll('.se-selected-table-cell');
|
|
1564
2335
|
for (let i = 0, len = selectedCells.length; i < len; i++) {
|
|
1565
|
-
|
|
2336
|
+
dom.utils.removeClass(selectedCells[i], 'se-selected-table-cell');
|
|
1566
2337
|
}
|
|
1567
2338
|
}
|
|
1568
|
-
}
|
|
2339
|
+
}
|
|
1569
2340
|
|
|
2341
|
+
/**
|
|
2342
|
+
* @private
|
|
2343
|
+
* @description Restores styles for selected table cells.
|
|
2344
|
+
*/
|
|
1570
2345
|
_recallStyleSelectedCells() {
|
|
1571
2346
|
if (this._selectedCells) {
|
|
1572
2347
|
const selectedCells = this._selectedCells;
|
|
1573
2348
|
for (let i = 0, len = selectedCells.length; i < len; i++) {
|
|
1574
|
-
|
|
2349
|
+
dom.utils.addClass(selectedCells[i], 'se-selected-table-cell');
|
|
1575
2350
|
}
|
|
1576
2351
|
}
|
|
1577
|
-
}
|
|
2352
|
+
}
|
|
1578
2353
|
|
|
2354
|
+
/**
|
|
2355
|
+
* @private
|
|
2356
|
+
* @description Adds global event listeners for resizing.
|
|
2357
|
+
* @param {(...args: *) => void} resizeFn The function handling the resize event.
|
|
2358
|
+
* @param {(...args: *) => void} stopFn The function handling the stop event.
|
|
2359
|
+
* @param {(...args: *) => void} keyDownFn The function handling the keydown event.
|
|
2360
|
+
*/
|
|
1579
2361
|
_addResizeGlobalEvents(resizeFn, stopFn, keyDownFn) {
|
|
1580
2362
|
this.__globalEvents.resize = this.eventManager.addGlobalEvent('mousemove', resizeFn, false);
|
|
1581
2363
|
this.__globalEvents.resizeStop = this.eventManager.addGlobalEvent('mouseup', stopFn, false);
|
|
1582
2364
|
this.__globalEvents.resizeKeyDown = this.eventManager.addGlobalEvent('keydown', keyDownFn, false);
|
|
1583
2365
|
this._resizing = true;
|
|
1584
|
-
}
|
|
2366
|
+
}
|
|
1585
2367
|
|
|
2368
|
+
/**
|
|
2369
|
+
* @private
|
|
2370
|
+
* @description Enables or disables editor mode.
|
|
2371
|
+
* @param {boolean} enabled Whether to enable or disable the editor.
|
|
2372
|
+
*/
|
|
1586
2373
|
_toggleEditor(enabled) {
|
|
1587
2374
|
const wysiwyg = this.editor.frameContext.get('wysiwyg');
|
|
1588
|
-
wysiwyg.setAttribute('contenteditable', enabled);
|
|
1589
|
-
if (enabled)
|
|
1590
|
-
else
|
|
1591
|
-
}
|
|
2375
|
+
wysiwyg.setAttribute('contenteditable', enabled.toString());
|
|
2376
|
+
if (enabled) dom.utils.removeClass(wysiwyg, 'se-disabled');
|
|
2377
|
+
else dom.utils.addClass(wysiwyg, 'se-disabled');
|
|
2378
|
+
}
|
|
1592
2379
|
|
|
2380
|
+
/**
|
|
2381
|
+
* @private
|
|
2382
|
+
* @description Updates control properties.
|
|
2383
|
+
* @param {string} type The type of control property.
|
|
2384
|
+
*/
|
|
1593
2385
|
_setCtrlProps(type) {
|
|
1594
2386
|
this._typeCache = type;
|
|
1595
2387
|
const isTable = type === 'table';
|
|
1596
2388
|
const targets = isTable ? [this._element] : this._selectedCells;
|
|
1597
2389
|
if (!targets || targets.length === 0) return;
|
|
1598
2390
|
|
|
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;
|
|
2391
|
+
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
2392
|
const { border, backgroundColor, color, textAlign, verticalAlign, fontWeight, textDecoration, fontStyle } = _w.getComputedStyle(targets[0]);
|
|
1601
2393
|
const cellBorder = this._getBorderStyle(border);
|
|
1602
2394
|
|
|
1603
|
-
cell_alignment.querySelector('[data-value="justify"]').style.display = isTable ? 'none' : '';
|
|
2395
|
+
/** @type {HTMLElement} */ (cell_alignment.querySelector('[data-value="justify"]')).style.display = isTable ? 'none' : '';
|
|
2396
|
+
cell_alignment_table_text.style.display = isTable ? '' : 'none';
|
|
1604
2397
|
if (isTable) cell_alignment_vertical.style.display = 'none';
|
|
1605
2398
|
else cell_alignment_vertical.style.display = '';
|
|
1606
2399
|
|
|
@@ -1632,7 +2425,7 @@ Table.prototype = {
|
|
|
1632
2425
|
if (fontColor !== converter.rgb2hex(color)) fontColor = '';
|
|
1633
2426
|
if (align !== (isTable ? this._figure?.style.float : textAlign)) align = '';
|
|
1634
2427
|
if (align_v && align_v !== verticalAlign) align_v = '';
|
|
1635
|
-
if (bold && bold !== /.+/.test(fontWeight)) bold =
|
|
2428
|
+
if (bold && bold !== /.+/.test(fontWeight)) bold = false;
|
|
1636
2429
|
if (underline && underline !== /underline/i.test(textDecoration)) underline = false;
|
|
1637
2430
|
if (strike && strike !== /line-through/i.test(textDecoration)) strike = false;
|
|
1638
2431
|
if (italic && italic !== /italic/i.test(fontStyle)) italic = false;
|
|
@@ -1644,7 +2437,7 @@ Table.prototype = {
|
|
|
1644
2437
|
// border - format
|
|
1645
2438
|
border_format.firstElementChild.innerHTML = this.icons[BORDER_FORMATS[targets.length === 1 ? 'outside' : 'all']];
|
|
1646
2439
|
border_format.setAttribute('se-border-format', 'all');
|
|
1647
|
-
|
|
2440
|
+
dom.utils.removeClass(border_format, 'active');
|
|
1648
2441
|
|
|
1649
2442
|
// border - styles
|
|
1650
2443
|
b_style = b_style || BORDER_LIST[0];
|
|
@@ -1658,43 +2451,64 @@ Table.prototype = {
|
|
|
1658
2451
|
font_color.value = font_color.style.borderColor = fontColor;
|
|
1659
2452
|
|
|
1660
2453
|
// font style
|
|
1661
|
-
if (bold)
|
|
1662
|
-
if (underline)
|
|
1663
|
-
if (strike)
|
|
1664
|
-
if (italic)
|
|
2454
|
+
if (bold) dom.utils.addClass(font_bold, 'on');
|
|
2455
|
+
if (underline) dom.utils.addClass(font_underline, 'on');
|
|
2456
|
+
if (strike) dom.utils.addClass(font_strike, 'on');
|
|
2457
|
+
if (italic) dom.utils.addClass(font_italic, 'on');
|
|
1665
2458
|
|
|
1666
2459
|
// align
|
|
1667
2460
|
this._setAlignProps(cell_alignment, (this._propsAlignCache = align), true);
|
|
1668
2461
|
this._setAlignProps(cell_alignment_vertical, (this._propsVerticalAlignCache = align_v), true);
|
|
1669
|
-
}
|
|
2462
|
+
}
|
|
1670
2463
|
|
|
2464
|
+
/**
|
|
2465
|
+
* @private
|
|
2466
|
+
* @description Sets text alignment properties.
|
|
2467
|
+
* @param {Element} el The element to apply alignment to.
|
|
2468
|
+
* @param {string} align The alignment value.
|
|
2469
|
+
* @param {boolean} reset Whether to reset the alignment.
|
|
2470
|
+
*/
|
|
1671
2471
|
_setAlignProps(el, align, reset) {
|
|
1672
|
-
|
|
2472
|
+
dom.utils.removeClass(el.querySelectorAll('button'), 'on');
|
|
1673
2473
|
|
|
1674
2474
|
if (!reset && el.getAttribute('se-cell-align') === align) {
|
|
1675
2475
|
el.setAttribute('se-cell-align', '');
|
|
1676
2476
|
return;
|
|
1677
2477
|
}
|
|
1678
2478
|
|
|
1679
|
-
|
|
2479
|
+
dom.utils.addClass(el.querySelector(`[data-value="${align}"]`), 'on');
|
|
1680
2480
|
el.setAttribute('se-cell-align', align);
|
|
1681
|
-
}
|
|
2481
|
+
}
|
|
1682
2482
|
|
|
2483
|
+
/**
|
|
2484
|
+
* @private
|
|
2485
|
+
* @description Disables or enables border properties.
|
|
2486
|
+
* @param {boolean} disabled Whether to disable or enable border properties.
|
|
2487
|
+
*/
|
|
1683
2488
|
_disableBorderProps(disabled) {
|
|
1684
2489
|
const { border_color, border_width, palette_border_button } = this.propTargets;
|
|
1685
2490
|
if (disabled) {
|
|
1686
|
-
border_color.
|
|
1687
|
-
border_width.
|
|
1688
|
-
palette_border_button.
|
|
1689
|
-
border_width.
|
|
2491
|
+
border_color.disabled = true;
|
|
2492
|
+
border_width.disabled = true;
|
|
2493
|
+
palette_border_button.disabled = true;
|
|
2494
|
+
border_width.disabled = true;
|
|
1690
2495
|
} else {
|
|
1691
|
-
border_color.
|
|
1692
|
-
border_width.
|
|
1693
|
-
palette_border_button.
|
|
1694
|
-
border_width.
|
|
2496
|
+
border_color.disabled = false;
|
|
2497
|
+
border_width.disabled = false;
|
|
2498
|
+
palette_border_button.disabled = false;
|
|
2499
|
+
border_width.disabled = false;
|
|
1695
2500
|
}
|
|
1696
|
-
}
|
|
2501
|
+
}
|
|
1697
2502
|
|
|
2503
|
+
/**
|
|
2504
|
+
* @private
|
|
2505
|
+
* @description Gets the border style.
|
|
2506
|
+
* @param {string} borderStyle The border style string.
|
|
2507
|
+
* @returns {{w: string, s: string, c: string}} The parsed border style object.
|
|
2508
|
+
* - w: The border width.
|
|
2509
|
+
* - s: The border style.
|
|
2510
|
+
* - c: The border color.
|
|
2511
|
+
*/
|
|
1698
2512
|
_getBorderStyle(borderStyle) {
|
|
1699
2513
|
const parts = borderStyle.split(/\s(?![^()]*\))/);
|
|
1700
2514
|
let w = '',
|
|
@@ -1722,15 +2536,20 @@ Table.prototype = {
|
|
|
1722
2536
|
}
|
|
1723
2537
|
|
|
1724
2538
|
return { w, s, c: converter.rgb2hex(c) };
|
|
1725
|
-
}
|
|
2539
|
+
}
|
|
1726
2540
|
|
|
2541
|
+
/**
|
|
2542
|
+
* @private
|
|
2543
|
+
* @description Applies properties to table cells.
|
|
2544
|
+
* @param {HTMLButtonElement} target The target element.
|
|
2545
|
+
*/
|
|
1727
2546
|
_submitProps(target) {
|
|
1728
2547
|
try {
|
|
1729
|
-
target.
|
|
2548
|
+
target.disabled = true;
|
|
1730
2549
|
|
|
1731
2550
|
const isTable = this.controller_table.form.contains(this.controller_props.currentTarget);
|
|
1732
2551
|
const targets = isTable ? [this._element] : this._selectedCells;
|
|
1733
|
-
const tr = targets[0];
|
|
2552
|
+
const tr = /** @type {HTMLTableCellElement} */ (targets[0]);
|
|
1734
2553
|
const trStyles = _w.getComputedStyle(tr);
|
|
1735
2554
|
const { border_format, border_color, border_style, border_width, back_color, font_color, cell_alignment, cell_alignment_vertical } = this.propTargets;
|
|
1736
2555
|
|
|
@@ -1753,14 +2572,16 @@ Table.prototype = {
|
|
|
1753
2572
|
top: [],
|
|
1754
2573
|
right: [],
|
|
1755
2574
|
bottom: [],
|
|
1756
|
-
middle: []
|
|
2575
|
+
middle: [],
|
|
2576
|
+
all: null
|
|
1757
2577
|
};
|
|
1758
2578
|
|
|
1759
2579
|
if (!isTable) {
|
|
2580
|
+
const trRow = /** @type {HTMLTableRowElement} */ (tr.parentElement);
|
|
1760
2581
|
// --- target cells roof
|
|
1761
2582
|
let { rs, re, cs, ce } = this._ref || {
|
|
1762
|
-
rs:
|
|
1763
|
-
re:
|
|
2583
|
+
rs: trRow.rowIndex || 0,
|
|
2584
|
+
re: trRow.rowIndex || 0,
|
|
1764
2585
|
cs: tr.cellIndex || 0,
|
|
1765
2586
|
ce: tr.cellIndex || 0
|
|
1766
2587
|
};
|
|
@@ -1770,17 +2591,17 @@ Table.prototype = {
|
|
|
1770
2591
|
rs -= rs;
|
|
1771
2592
|
ce -= cs;
|
|
1772
2593
|
cs -= cs;
|
|
1773
|
-
let prevRow =
|
|
2594
|
+
let prevRow = /** @type {HTMLElement} */ (trRow);
|
|
1774
2595
|
for (let i = 0, cellCnt = 0, len = targets.length, e, es, rowIndex = 0, cellIndex, colspan, rowspan; i < len; i++, cellCnt++) {
|
|
1775
|
-
e = targets[i];
|
|
2596
|
+
e = /** @type {HTMLTableCellElement} */ (targets[i]);
|
|
1776
2597
|
colspan = e.colSpan;
|
|
1777
2598
|
rowspan = e.rowSpan;
|
|
1778
2599
|
cellIndex = e.cellIndex - cellStartIndex;
|
|
1779
2600
|
|
|
1780
|
-
if (prevRow !== e.
|
|
2601
|
+
if (prevRow !== e.parentElement) {
|
|
1781
2602
|
rowIndex++;
|
|
1782
2603
|
cellCnt = 0;
|
|
1783
|
-
prevRow = e.
|
|
2604
|
+
prevRow = e.parentElement;
|
|
1784
2605
|
}
|
|
1785
2606
|
|
|
1786
2607
|
let c = 0;
|
|
@@ -1789,6 +2610,7 @@ Table.prototype = {
|
|
|
1789
2610
|
c++;
|
|
1790
2611
|
}
|
|
1791
2612
|
|
|
2613
|
+
/* eslint-disable @typescript-eslint/no-unused-vars */
|
|
1792
2614
|
try {
|
|
1793
2615
|
if (rowspan > 1) {
|
|
1794
2616
|
const rowspanNum = rowspan - 1;
|
|
@@ -1801,6 +2623,7 @@ Table.prototype = {
|
|
|
1801
2623
|
} catch (err) {
|
|
1802
2624
|
// ignore error
|
|
1803
2625
|
}
|
|
2626
|
+
/* eslint-disable @typescript-eslint/no-unused-vars */
|
|
1804
2627
|
|
|
1805
2628
|
const isBottom = rowIndex + rowspan - 1 === re;
|
|
1806
2629
|
if (rowIndex === rs) cells.top.push(e);
|
|
@@ -1874,91 +2697,101 @@ Table.prototype = {
|
|
|
1874
2697
|
if (this._tdElement) {
|
|
1875
2698
|
this._recallStyleSelectedCells();
|
|
1876
2699
|
this.setCellInfo(this._tdElement, true);
|
|
1877
|
-
|
|
2700
|
+
dom.utils.addClass(this._tdElement, 'se-selected-cell-focus');
|
|
1878
2701
|
}
|
|
1879
2702
|
} catch (err) {
|
|
1880
2703
|
console.warn('[SUNEDITOR.plugins.table.setProps.error]', err);
|
|
1881
2704
|
} finally {
|
|
1882
|
-
target.
|
|
2705
|
+
target.disabled = false;
|
|
1883
2706
|
}
|
|
1884
|
-
}
|
|
2707
|
+
}
|
|
1885
2708
|
|
|
2709
|
+
/**
|
|
2710
|
+
* @private
|
|
2711
|
+
* @description Sets font styles.
|
|
2712
|
+
* @param {CSSStyleDeclaration} styles The style object to modify.
|
|
2713
|
+
*/
|
|
1886
2714
|
_setFontStyle(styles) {
|
|
1887
2715
|
const { font_bold, font_italic, font_strike, font_underline } = this.propTargets;
|
|
1888
|
-
styles.fontWeight =
|
|
1889
|
-
styles.fontStyle =
|
|
1890
|
-
styles.textDecoration = ((
|
|
1891
|
-
}
|
|
2716
|
+
styles.fontWeight = dom.utils.hasClass(font_bold, 'on') ? 'bold' : '';
|
|
2717
|
+
styles.fontStyle = dom.utils.hasClass(font_italic, 'on') ? 'italic' : '';
|
|
2718
|
+
styles.textDecoration = ((dom.utils.hasClass(font_strike, 'on') ? 'line-through ' : '') + (dom.utils.hasClass(font_underline, 'on') ? 'underline' : '')).trim();
|
|
2719
|
+
}
|
|
1892
2720
|
|
|
1893
2721
|
/**
|
|
1894
2722
|
* @private
|
|
1895
|
-
* @description
|
|
1896
|
-
* @param {
|
|
1897
|
-
* @param {"all"|"inside"|"horizon"|"vertical"|"outside"|"left"|"top"|"right"|"bottom"
|
|
1898
|
-
* @param {
|
|
1899
|
-
* @param {boolean} isTable table selected
|
|
2723
|
+
* @description Sets border format and styles.
|
|
2724
|
+
* @param {{left: Node[], top: Node[], right: Node[], bottom: Node[], all: Node[]}} cells The table cells categorized by border positions.
|
|
2725
|
+
* @param {string} borderKey Border style ("all"|"inside"|"horizon"|"vertical"|"outside"|"left"|"top"|"right"|"bottom")
|
|
2726
|
+
* @param {string} s The border style value.
|
|
1900
2727
|
*/
|
|
1901
2728
|
_setBorderStyles(cells, borderKey, s) {
|
|
1902
2729
|
const { left, top, right, bottom, all } = cells;
|
|
1903
2730
|
switch (borderKey) {
|
|
1904
2731
|
case 'inside':
|
|
1905
|
-
if (
|
|
1906
|
-
|
|
2732
|
+
if (all.length === 1) return;
|
|
2733
|
+
dom.utils.setStyle(
|
|
1907
2734
|
all.filter((c) => !bottom.includes(c)),
|
|
1908
2735
|
BORDER_NS.b,
|
|
1909
2736
|
s
|
|
1910
2737
|
);
|
|
1911
|
-
|
|
2738
|
+
dom.utils.setStyle(
|
|
1912
2739
|
all.filter((c) => !right.includes(c)),
|
|
1913
2740
|
BORDER_NS.r,
|
|
1914
2741
|
s
|
|
1915
2742
|
);
|
|
1916
2743
|
break;
|
|
1917
2744
|
case 'horizon':
|
|
1918
|
-
if (
|
|
1919
|
-
|
|
2745
|
+
if (all.length === 1) return;
|
|
2746
|
+
dom.utils.setStyle(
|
|
1920
2747
|
all.filter((c) => !bottom.includes(c)),
|
|
1921
2748
|
BORDER_NS.b,
|
|
1922
2749
|
s
|
|
1923
2750
|
);
|
|
1924
2751
|
break;
|
|
1925
2752
|
case 'vertical':
|
|
1926
|
-
if (
|
|
1927
|
-
|
|
2753
|
+
if (all.length === 1) return;
|
|
2754
|
+
dom.utils.setStyle(
|
|
1928
2755
|
all.filter((c) => !right.includes(c)),
|
|
1929
2756
|
BORDER_NS.r,
|
|
1930
2757
|
s
|
|
1931
2758
|
);
|
|
1932
2759
|
break;
|
|
1933
2760
|
case 'outside':
|
|
1934
|
-
|
|
1935
|
-
|
|
1936
|
-
|
|
1937
|
-
|
|
2761
|
+
dom.utils.setStyle(left, BORDER_NS.l, s);
|
|
2762
|
+
dom.utils.setStyle(top, BORDER_NS.t, s);
|
|
2763
|
+
dom.utils.setStyle(right, BORDER_NS.r, s);
|
|
2764
|
+
dom.utils.setStyle(bottom, BORDER_NS.b, s);
|
|
1938
2765
|
break;
|
|
1939
2766
|
case 'left':
|
|
1940
|
-
|
|
2767
|
+
dom.utils.setStyle(left, BORDER_NS.l, s);
|
|
1941
2768
|
break;
|
|
1942
2769
|
case 'top':
|
|
1943
|
-
|
|
2770
|
+
dom.utils.setStyle(top, BORDER_NS.t, s);
|
|
1944
2771
|
break;
|
|
1945
2772
|
case 'right':
|
|
1946
|
-
|
|
2773
|
+
dom.utils.setStyle(right, BORDER_NS.r, s);
|
|
1947
2774
|
break;
|
|
1948
2775
|
case 'bottom':
|
|
1949
|
-
|
|
2776
|
+
dom.utils.setStyle(bottom, BORDER_NS.b, s);
|
|
1950
2777
|
break;
|
|
1951
2778
|
}
|
|
1952
|
-
}
|
|
2779
|
+
}
|
|
1953
2780
|
|
|
2781
|
+
/**
|
|
2782
|
+
* @private
|
|
2783
|
+
* @description Selects multiple table cells and applies selection styles.
|
|
2784
|
+
* @param {Node} startCell The first cell in the selection.
|
|
2785
|
+
* @param {Node} endCell The last cell in the selection.
|
|
2786
|
+
*/
|
|
1954
2787
|
_setMultiCells(startCell, endCell) {
|
|
1955
2788
|
const rows = this._selectedTable.rows;
|
|
1956
2789
|
this._deleteStyleSelectedCells();
|
|
1957
2790
|
|
|
2791
|
+
dom.utils.addClass(startCell, 'se-selected-table-cell');
|
|
2792
|
+
|
|
1958
2793
|
if (startCell === endCell) {
|
|
1959
2794
|
if (!this._shift) return;
|
|
1960
|
-
} else {
|
|
1961
|
-
domUtils.addClass(startCell, 'se-selected-table-cell');
|
|
1962
2795
|
}
|
|
1963
2796
|
|
|
1964
2797
|
let findSelectedCell = true;
|
|
@@ -2034,7 +2867,7 @@ Table.prototype = {
|
|
|
2034
2867
|
break;
|
|
2035
2868
|
}
|
|
2036
2869
|
|
|
2037
|
-
|
|
2870
|
+
dom.utils.addClass(cell, 'se-selected-table-cell');
|
|
2038
2871
|
}
|
|
2039
2872
|
|
|
2040
2873
|
if (rs > 0) {
|
|
@@ -2054,8 +2887,12 @@ Table.prototype = {
|
|
|
2054
2887
|
});
|
|
2055
2888
|
rowSpanArr = [];
|
|
2056
2889
|
}
|
|
2057
|
-
}
|
|
2890
|
+
}
|
|
2058
2891
|
|
|
2892
|
+
/**
|
|
2893
|
+
* @private
|
|
2894
|
+
* @description Resets the table picker display.
|
|
2895
|
+
*/
|
|
2059
2896
|
_resetTablePicker() {
|
|
2060
2897
|
if (!this.tableHighlight) return;
|
|
2061
2898
|
|
|
@@ -2067,10 +2904,14 @@ Table.prototype = {
|
|
|
2067
2904
|
unHighlight.width = '10em';
|
|
2068
2905
|
unHighlight.height = '10em';
|
|
2069
2906
|
|
|
2070
|
-
|
|
2907
|
+
dom.utils.changeTxt(this.tableDisplay, '1 x 1');
|
|
2071
2908
|
this.menu.dropdownOff();
|
|
2072
|
-
}
|
|
2909
|
+
}
|
|
2073
2910
|
|
|
2911
|
+
/**
|
|
2912
|
+
* @private
|
|
2913
|
+
* @description Resets the alignment properties for table cells.
|
|
2914
|
+
*/
|
|
2074
2915
|
_resetPropsAlign() {
|
|
2075
2916
|
const { cell_alignment } = this.propTargets;
|
|
2076
2917
|
const left = cell_alignment.querySelector('[data-value="left"]');
|
|
@@ -2079,35 +2920,63 @@ Table.prototype = {
|
|
|
2079
2920
|
const r_parent = right.parentElement;
|
|
2080
2921
|
l_parent.appendChild(right);
|
|
2081
2922
|
r_parent.appendChild(left);
|
|
2082
|
-
}
|
|
2923
|
+
}
|
|
2083
2924
|
|
|
2925
|
+
/**
|
|
2926
|
+
* @private
|
|
2927
|
+
* @description Handles color selection from the color palette.
|
|
2928
|
+
* @param {Node} button The button triggering the color palette.
|
|
2929
|
+
* @param {string} type The type of color selection.
|
|
2930
|
+
* @param {HTMLInputElement} color Color text input element.
|
|
2931
|
+
*/
|
|
2084
2932
|
_onColorPalette(button, type, color) {
|
|
2085
2933
|
if (this.controller_colorPicker.isOpen && type === this.sliderType) {
|
|
2086
2934
|
this.controller_colorPicker.close();
|
|
2087
2935
|
} else {
|
|
2088
2936
|
this.sliderType = type;
|
|
2089
|
-
|
|
2937
|
+
dom.utils.addClass(button, 'on');
|
|
2090
2938
|
this.colorPicker.init(color?.value || '', button);
|
|
2091
2939
|
this.controller_colorPicker.open(button, null, { isWWTarget: false, initMethod: null, addOffset: null });
|
|
2092
2940
|
}
|
|
2093
|
-
}
|
|
2941
|
+
}
|
|
2094
2942
|
|
|
2943
|
+
/**
|
|
2944
|
+
* @private
|
|
2945
|
+
* @description Closes table-related controllers.
|
|
2946
|
+
*/
|
|
2095
2947
|
_closeController() {
|
|
2096
|
-
this.component.deselect();
|
|
2097
2948
|
this.controller_table.close();
|
|
2098
2949
|
this.controller_cell.close();
|
|
2099
|
-
}
|
|
2950
|
+
}
|
|
2100
2951
|
|
|
2952
|
+
/**
|
|
2953
|
+
* @private
|
|
2954
|
+
* @description Closes table-related controllers and table figure
|
|
2955
|
+
*/
|
|
2956
|
+
_closeTableSelectInfo() {
|
|
2957
|
+
this.component.deselect();
|
|
2958
|
+
this._closeController();
|
|
2959
|
+
}
|
|
2960
|
+
|
|
2961
|
+
/**
|
|
2962
|
+
* @private
|
|
2963
|
+
* @description Hides the resize line if it is visible.
|
|
2964
|
+
*/
|
|
2101
2965
|
__hideResizeLine() {
|
|
2102
2966
|
if (this._resizeLine) {
|
|
2103
2967
|
this._resizeLine.style.display = 'none';
|
|
2104
2968
|
this._resizeLine = null;
|
|
2105
2969
|
}
|
|
2106
|
-
}
|
|
2970
|
+
}
|
|
2107
2971
|
|
|
2972
|
+
/**
|
|
2973
|
+
* @private
|
|
2974
|
+
* @description Removes global event listeners and resets resize-related properties.
|
|
2975
|
+
*/
|
|
2108
2976
|
__removeGlobalEvents() {
|
|
2977
|
+
this._toggleEditor(true);
|
|
2109
2978
|
this._resizing = false;
|
|
2110
|
-
this.
|
|
2979
|
+
this.ui.disableBackWrapper();
|
|
2111
2980
|
this.__hideResizeLine();
|
|
2112
2981
|
if (this._resizeLinePrev) {
|
|
2113
2982
|
this._resizeLinePrev.style.display = 'none';
|
|
@@ -2117,380 +2986,635 @@ Table.prototype = {
|
|
|
2117
2986
|
for (const k in globalEvents) {
|
|
2118
2987
|
if (globalEvents[k]) globalEvents[k] = this.eventManager.removeGlobalEvent(globalEvents[k]);
|
|
2119
2988
|
}
|
|
2120
|
-
}
|
|
2121
|
-
|
|
2122
|
-
constructor: Table
|
|
2123
|
-
};
|
|
2989
|
+
}
|
|
2124
2990
|
|
|
2125
|
-
|
|
2126
|
-
|
|
2127
|
-
}
|
|
2991
|
+
/**
|
|
2992
|
+
* @description Clone a table element and map selected cells to the cloned table
|
|
2993
|
+
* @param {HTMLTableElement} table <table> element
|
|
2994
|
+
* @param {HTMLTableCellElement[]} selectedCells Selected cells array
|
|
2995
|
+
* @returns {{ cloneTable: HTMLTableElement, clonedSelectedCells: HTMLTableCellElement[] }}
|
|
2996
|
+
*/
|
|
2997
|
+
#cloneTable(table, selectedCells) {
|
|
2998
|
+
/** @type {HTMLTableElement} */
|
|
2999
|
+
const cloneTable = dom.utils.clone(table, true);
|
|
3000
|
+
|
|
3001
|
+
const originalCells = Array.from(table.querySelectorAll('td, th'));
|
|
3002
|
+
const clonedCells = Array.from(cloneTable.querySelectorAll('td, th'));
|
|
3003
|
+
|
|
3004
|
+
const clonedSelectedCells = /** @type {HTMLTableCellElement[]} */ (
|
|
3005
|
+
selectedCells
|
|
3006
|
+
.map((cell) => {
|
|
3007
|
+
const index = originalCells.indexOf(cell);
|
|
3008
|
+
return index > -1 ? clonedCells[index] : null;
|
|
3009
|
+
})
|
|
3010
|
+
.filter((cell) => cell !== null)
|
|
3011
|
+
);
|
|
2128
3012
|
|
|
2129
|
-
|
|
2130
|
-
|
|
2131
|
-
|
|
2132
|
-
|
|
2133
|
-
|
|
2134
|
-
const isLeft = offsetX <= CELL_SELECT_MARGIN;
|
|
2135
|
-
const is = isLeft || startWidth - offsetX <= CELL_SELECT_MARGIN;
|
|
3013
|
+
return {
|
|
3014
|
+
cloneTable,
|
|
3015
|
+
clonedSelectedCells
|
|
3016
|
+
};
|
|
3017
|
+
}
|
|
2136
3018
|
|
|
2137
|
-
|
|
2138
|
-
|
|
2139
|
-
|
|
2140
|
-
|
|
2141
|
-
|
|
2142
|
-
|
|
3019
|
+
/**
|
|
3020
|
+
* @description Selects cells in a table, handling single and multi-cell selection, and managing shift key behavior for extended selection.
|
|
3021
|
+
* @param {HTMLTableCellElement} tdElement The target table cell (`<td>`) element that is being selected.
|
|
3022
|
+
* @param {boolean} shift A flag indicating whether the shift key is held down for multi-cell selection.
|
|
3023
|
+
* If `true`, the selection will extend to include adjacent cells, otherwise it selects only the provided cell.
|
|
3024
|
+
*/
|
|
3025
|
+
#StyleSelectCells(tdElement, shift) {
|
|
3026
|
+
this.__s = shift;
|
|
3027
|
+
if (!this._shift && !this._ref) this.__removeGlobalEvents();
|
|
2143
3028
|
|
|
2144
|
-
|
|
2145
|
-
|
|
2146
|
-
|
|
2147
|
-
|
|
2148
|
-
|
|
3029
|
+
this._shift = shift;
|
|
3030
|
+
this._fixedCell = tdElement;
|
|
3031
|
+
if (!this._selectedCells?.length) this._selectedCells = [tdElement];
|
|
3032
|
+
this._fixedCellName = tdElement.nodeName;
|
|
3033
|
+
this._selectedTable = dom.query.getParentElement(tdElement, 'TABLE');
|
|
2149
3034
|
|
|
2150
|
-
|
|
2151
|
-
|
|
2152
|
-
startY
|
|
2153
|
-
};
|
|
2154
|
-
}
|
|
3035
|
+
this._deleteStyleSelectedCells();
|
|
3036
|
+
dom.utils.addClass(tdElement, 'se-selected-cell-focus');
|
|
2155
3037
|
|
|
2156
|
-
|
|
2157
|
-
|
|
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);
|
|
3038
|
+
if (!shift) {
|
|
3039
|
+
this.__globalEvents.on = this.eventManager.addGlobalEvent('mousemove', this._bindMultiOn, false);
|
|
2175
3040
|
} else {
|
|
2176
|
-
|
|
2177
|
-
|
|
2178
|
-
|
|
3041
|
+
this.__globalEvents.shiftOff = this.eventManager.addGlobalEvent('keyup', this._bindShiftOff, false);
|
|
3042
|
+
this.__globalEvents.on = this.eventManager.addGlobalEvent('mousedown', this._bindMultiOn, false);
|
|
3043
|
+
}
|
|
2179
3044
|
|
|
2180
|
-
|
|
2181
|
-
|
|
2182
|
-
|
|
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;
|
|
3045
|
+
this.__globalEvents.off = this.eventManager.addGlobalEvent('mouseup', this._bindMultiOff, false);
|
|
3046
|
+
this.__globalEvents.touchOff = this.eventManager.addGlobalEvent('touchmove', this._bindTouchOff, false);
|
|
3047
|
+
}
|
|
2188
3048
|
|
|
2189
|
-
|
|
2190
|
-
|
|
2191
|
-
|
|
2192
|
-
|
|
2193
|
-
|
|
2194
|
-
|
|
2195
|
-
|
|
2196
|
-
|
|
2197
|
-
|
|
2198
|
-
|
|
2199
|
-
|
|
2200
|
-
|
|
2201
|
-
|
|
2202
|
-
|
|
2203
|
-
|
|
2204
|
-
|
|
2205
|
-
|
|
2206
|
-
|
|
2207
|
-
|
|
3049
|
+
/**
|
|
3050
|
+
* @description Splits a table cell either vertically or horizontally.
|
|
3051
|
+
* @param {"vertical"|"horizontal"} direction The direction to split the cell.
|
|
3052
|
+
*/
|
|
3053
|
+
#OnSplitCells(direction) {
|
|
3054
|
+
const vertical = direction === 'vertical';
|
|
3055
|
+
const currentCell = this._tdElement;
|
|
3056
|
+
const rows = this._trElements;
|
|
3057
|
+
const currentRow = this._trElement;
|
|
3058
|
+
const index = this._logical_cellIndex;
|
|
3059
|
+
const rowIndex = this._rowIndex;
|
|
3060
|
+
const newCell = CreateCellsHTML(currentCell.nodeName);
|
|
3061
|
+
|
|
3062
|
+
// vertical
|
|
3063
|
+
if (vertical) {
|
|
3064
|
+
const currentColSpan = currentCell.colSpan;
|
|
3065
|
+
newCell.rowSpan = currentCell.rowSpan;
|
|
3066
|
+
|
|
3067
|
+
// colspan > 1
|
|
3068
|
+
if (currentColSpan > 1) {
|
|
3069
|
+
newCell.colSpan = Math.floor(currentColSpan / 2);
|
|
3070
|
+
currentCell.colSpan = currentColSpan - newCell.colSpan;
|
|
3071
|
+
currentRow.insertBefore(newCell, currentCell.nextElementSibling);
|
|
3072
|
+
} else {
|
|
3073
|
+
// colspan - 1
|
|
3074
|
+
let rowSpanArr = [];
|
|
3075
|
+
let spanIndex = [];
|
|
3076
|
+
|
|
3077
|
+
for (let i = 0, len = this._rowCnt, cells, colSpan; i < len; i++) {
|
|
3078
|
+
cells = rows[i].cells;
|
|
3079
|
+
colSpan = 0;
|
|
3080
|
+
for (let c = 0, cLen = cells.length, cell, cs, rs, logcalIndex; c < cLen; c++) {
|
|
3081
|
+
cell = cells[c];
|
|
3082
|
+
cs = cell.colSpan - 1;
|
|
3083
|
+
rs = cell.rowSpan - 1;
|
|
3084
|
+
logcalIndex = c + colSpan;
|
|
3085
|
+
|
|
3086
|
+
if (spanIndex.length > 0) {
|
|
3087
|
+
for (let r = 0, arr; r < spanIndex.length; r++) {
|
|
3088
|
+
arr = spanIndex[r];
|
|
3089
|
+
if (arr.row > i) continue;
|
|
3090
|
+
if (logcalIndex >= arr.index) {
|
|
3091
|
+
colSpan += arr.cs;
|
|
3092
|
+
logcalIndex += arr.cs;
|
|
3093
|
+
arr.rs -= 1;
|
|
3094
|
+
arr.row = i + 1;
|
|
3095
|
+
if (arr.rs < 1) {
|
|
3096
|
+
spanIndex.splice(r, 1);
|
|
3097
|
+
r--;
|
|
3098
|
+
}
|
|
3099
|
+
} else if (c === cLen - 1) {
|
|
3100
|
+
arr.rs -= 1;
|
|
3101
|
+
arr.row = i + 1;
|
|
3102
|
+
if (arr.rs < 1) {
|
|
3103
|
+
spanIndex.splice(r, 1);
|
|
3104
|
+
r--;
|
|
3105
|
+
}
|
|
2208
3106
|
}
|
|
2209
3107
|
}
|
|
2210
3108
|
}
|
|
2211
|
-
}
|
|
2212
3109
|
|
|
2213
|
-
|
|
2214
|
-
|
|
2215
|
-
|
|
2216
|
-
|
|
2217
|
-
|
|
2218
|
-
|
|
2219
|
-
|
|
2220
|
-
|
|
3110
|
+
if (logcalIndex <= index && rs > 0) {
|
|
3111
|
+
rowSpanArr.push({
|
|
3112
|
+
index: logcalIndex,
|
|
3113
|
+
cs: cs + 1,
|
|
3114
|
+
rs: rs,
|
|
3115
|
+
row: -1
|
|
3116
|
+
});
|
|
3117
|
+
}
|
|
2221
3118
|
|
|
2222
|
-
|
|
2223
|
-
|
|
2224
|
-
|
|
2225
|
-
|
|
3119
|
+
if (cell !== currentCell && logcalIndex <= index && logcalIndex + cs >= index + currentColSpan - 1) {
|
|
3120
|
+
cell.colSpan += 1;
|
|
3121
|
+
break;
|
|
3122
|
+
}
|
|
2226
3123
|
|
|
2227
|
-
|
|
3124
|
+
if (logcalIndex > index) break;
|
|
2228
3125
|
|
|
2229
|
-
|
|
3126
|
+
colSpan += cs;
|
|
3127
|
+
}
|
|
3128
|
+
|
|
3129
|
+
spanIndex = spanIndex.concat(rowSpanArr).sort(function (a, b) {
|
|
3130
|
+
return a.index - b.index;
|
|
3131
|
+
});
|
|
3132
|
+
rowSpanArr = [];
|
|
2230
3133
|
}
|
|
2231
3134
|
|
|
2232
|
-
|
|
2233
|
-
return a.index - b.index;
|
|
2234
|
-
});
|
|
2235
|
-
rowSpanArr = [];
|
|
3135
|
+
currentRow.insertBefore(newCell, currentCell.nextElementSibling);
|
|
2236
3136
|
}
|
|
3137
|
+
} else {
|
|
3138
|
+
// horizontal
|
|
3139
|
+
const currentRowSpan = currentCell.rowSpan;
|
|
3140
|
+
newCell.colSpan = currentCell.colSpan;
|
|
2237
3141
|
|
|
2238
|
-
|
|
2239
|
-
|
|
2240
|
-
|
|
2241
|
-
|
|
2242
|
-
const currentRowSpan = currentCell.rowSpan;
|
|
2243
|
-
newCell.colSpan = currentCell.colSpan;
|
|
3142
|
+
// rowspan > 1
|
|
3143
|
+
if (currentRowSpan > 1) {
|
|
3144
|
+
newCell.rowSpan = Math.floor(currentRowSpan / 2);
|
|
3145
|
+
const newRowSpan = currentRowSpan - newCell.rowSpan;
|
|
2244
3146
|
|
|
2245
|
-
|
|
2246
|
-
|
|
2247
|
-
|
|
2248
|
-
|
|
3147
|
+
const rowSpanArr = [];
|
|
3148
|
+
const nextRowIndex = dom.utils.getArrayIndex(rows, currentRow) + newRowSpan;
|
|
3149
|
+
|
|
3150
|
+
for (let i = 0, cells, colSpan; i < nextRowIndex; i++) {
|
|
3151
|
+
cells = rows[i].cells;
|
|
3152
|
+
colSpan = 0;
|
|
3153
|
+
for (let c = 0, cLen = cells.length, cell, cs, logcalIndex; c < cLen; c++) {
|
|
3154
|
+
logcalIndex = c + colSpan;
|
|
3155
|
+
if (logcalIndex >= index) break;
|
|
3156
|
+
|
|
3157
|
+
cell = cells[c];
|
|
3158
|
+
cs = cell.rowSpan - 1;
|
|
3159
|
+
if (cs > 0 && cs + i >= nextRowIndex && logcalIndex < index) {
|
|
3160
|
+
rowSpanArr.push({
|
|
3161
|
+
index: logcalIndex,
|
|
3162
|
+
cs: cell.colSpan
|
|
3163
|
+
});
|
|
3164
|
+
}
|
|
3165
|
+
colSpan += cell.colSpan - 1;
|
|
3166
|
+
}
|
|
3167
|
+
}
|
|
2249
3168
|
|
|
2250
|
-
|
|
2251
|
-
|
|
3169
|
+
const nextRow = rows[nextRowIndex];
|
|
3170
|
+
const nextCells = nextRow.cells;
|
|
3171
|
+
let rs = rowSpanArr.shift();
|
|
2252
3172
|
|
|
2253
|
-
|
|
2254
|
-
cells = rows[i].cells;
|
|
2255
|
-
colSpan = 0;
|
|
2256
|
-
for (let c = 0, cLen = cells.length, cell, cs, logcalIndex; c < cLen; c++) {
|
|
3173
|
+
for (let c = 0, cLen = nextCells.length, colSpan = 0, cell, cs, logcalIndex, insertIndex; c < cLen; c++) {
|
|
2257
3174
|
logcalIndex = c + colSpan;
|
|
2258
|
-
|
|
3175
|
+
cell = nextCells[c];
|
|
3176
|
+
cs = cell.colSpan - 1;
|
|
3177
|
+
insertIndex = logcalIndex + cs + 1;
|
|
2259
3178
|
|
|
2260
|
-
|
|
2261
|
-
|
|
2262
|
-
|
|
2263
|
-
rowSpanArr.
|
|
2264
|
-
index: logcalIndex,
|
|
2265
|
-
cs: cell.colSpan
|
|
2266
|
-
});
|
|
3179
|
+
if (rs && insertIndex >= rs.index) {
|
|
3180
|
+
colSpan += rs.cs;
|
|
3181
|
+
insertIndex += rs.cs;
|
|
3182
|
+
rs = rowSpanArr.shift();
|
|
2267
3183
|
}
|
|
2268
|
-
colSpan += cell.colSpan - 1;
|
|
2269
|
-
}
|
|
2270
|
-
}
|
|
2271
3184
|
|
|
2272
|
-
|
|
2273
|
-
|
|
2274
|
-
|
|
2275
|
-
|
|
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;
|
|
3185
|
+
if (insertIndex >= index || c === cLen - 1) {
|
|
3186
|
+
nextRow.insertBefore(newCell, cell.nextElementSibling);
|
|
3187
|
+
break;
|
|
3188
|
+
}
|
|
2281
3189
|
|
|
2282
|
-
|
|
2283
|
-
colSpan += rs.cs;
|
|
2284
|
-
insertIndex += rs.cs;
|
|
2285
|
-
rs = rowSpanArr.shift();
|
|
3190
|
+
colSpan += cs;
|
|
2286
3191
|
}
|
|
2287
3192
|
|
|
2288
|
-
|
|
2289
|
-
|
|
2290
|
-
|
|
3193
|
+
currentCell.rowSpan = newRowSpan;
|
|
3194
|
+
} else {
|
|
3195
|
+
// rowspan - 1
|
|
3196
|
+
newCell.rowSpan = currentCell.rowSpan;
|
|
3197
|
+
const newRow = dom.utils.createElement('TR');
|
|
3198
|
+
newRow.appendChild(newCell);
|
|
3199
|
+
|
|
3200
|
+
for (let i = 0, cells; i < rowIndex; i++) {
|
|
3201
|
+
cells = rows[i].cells;
|
|
3202
|
+
if (cells.length === 0) return;
|
|
3203
|
+
|
|
3204
|
+
for (let c = 0, cLen = cells.length; c < cLen; c++) {
|
|
3205
|
+
if (i + cells[c].rowSpan - 1 >= rowIndex) {
|
|
3206
|
+
cells[c].rowSpan += 1;
|
|
3207
|
+
}
|
|
3208
|
+
}
|
|
2291
3209
|
}
|
|
2292
3210
|
|
|
2293
|
-
|
|
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;
|
|
3211
|
+
const physicalIndex = this._physical_cellIndex;
|
|
3212
|
+
const cells = currentRow.cells;
|
|
2306
3213
|
|
|
2307
3214
|
for (let c = 0, cLen = cells.length; c < cLen; c++) {
|
|
2308
|
-
if (
|
|
2309
|
-
|
|
2310
|
-
}
|
|
3215
|
+
if (c === physicalIndex) continue;
|
|
3216
|
+
cells[c].rowSpan += 1;
|
|
2311
3217
|
}
|
|
3218
|
+
|
|
3219
|
+
currentRow.parentNode.insertBefore(newRow, currentRow.nextElementSibling);
|
|
2312
3220
|
}
|
|
3221
|
+
}
|
|
2313
3222
|
|
|
2314
|
-
|
|
2315
|
-
|
|
3223
|
+
this.selectMenu_split.close();
|
|
3224
|
+
this.#focusEdge(currentCell);
|
|
2316
3225
|
|
|
2317
|
-
|
|
2318
|
-
|
|
2319
|
-
cells[c].rowSpan += 1;
|
|
2320
|
-
}
|
|
3226
|
+
this._deleteStyleSelectedCells();
|
|
3227
|
+
this.history.push(false);
|
|
2321
3228
|
|
|
2322
|
-
|
|
2323
|
-
|
|
3229
|
+
this._setController(currentCell);
|
|
3230
|
+
this._selectedCell = this._fixedCell = currentCell;
|
|
3231
|
+
if (!this._selectedCells?.length) this._selectedCells = [currentCell];
|
|
2324
3232
|
}
|
|
2325
3233
|
|
|
2326
|
-
|
|
2327
|
-
|
|
3234
|
+
/**
|
|
3235
|
+
* @description Handles column operations such as insert and delete.
|
|
3236
|
+
* @param {"insert-left"|"insert-right"|"delete"} command The column operation to perform.
|
|
3237
|
+
*/
|
|
3238
|
+
#OnColumnEdit(command) {
|
|
3239
|
+
switch (command) {
|
|
3240
|
+
case 'insert-left':
|
|
3241
|
+
this.editTable('cell', 'left');
|
|
3242
|
+
break;
|
|
3243
|
+
case 'insert-right':
|
|
3244
|
+
this.editTable('cell', 'right');
|
|
3245
|
+
break;
|
|
3246
|
+
case 'delete':
|
|
3247
|
+
this.editTable('cell', null);
|
|
3248
|
+
}
|
|
2328
3249
|
|
|
2329
|
-
|
|
2330
|
-
|
|
3250
|
+
this._historyPush();
|
|
3251
|
+
}
|
|
2331
3252
|
|
|
2332
|
-
|
|
2333
|
-
|
|
2334
|
-
}
|
|
3253
|
+
/**
|
|
3254
|
+
* @description Handles row operations such as insert and delete.
|
|
3255
|
+
* @param {"insert-above"|"insert-below"|"delete"} command The row operation to perform.
|
|
3256
|
+
*/
|
|
3257
|
+
#OnRowEdit(command) {
|
|
3258
|
+
switch (command) {
|
|
3259
|
+
case 'insert-above':
|
|
3260
|
+
this.editTable('row', 'up');
|
|
3261
|
+
break;
|
|
3262
|
+
case 'insert-below':
|
|
3263
|
+
this.editTable('row', 'down');
|
|
3264
|
+
break;
|
|
3265
|
+
case 'delete':
|
|
3266
|
+
this.editTable('row', null);
|
|
3267
|
+
}
|
|
2335
3268
|
|
|
2336
|
-
|
|
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);
|
|
3269
|
+
this._historyPush();
|
|
2346
3270
|
}
|
|
2347
3271
|
|
|
2348
|
-
|
|
2349
|
-
|
|
3272
|
+
/**
|
|
3273
|
+
* @description Handles mouse movement within the table picker.
|
|
3274
|
+
* @param {MouseEvent} e The mouse event.
|
|
3275
|
+
*/
|
|
3276
|
+
#OnMouseMoveTablePicker(e) {
|
|
3277
|
+
e.stopPropagation();
|
|
2350
3278
|
|
|
2351
|
-
|
|
2352
|
-
|
|
2353
|
-
|
|
2354
|
-
|
|
2355
|
-
break;
|
|
2356
|
-
case 'insert-below':
|
|
2357
|
-
this.editTable('row', 'down');
|
|
2358
|
-
break;
|
|
2359
|
-
case 'delete':
|
|
2360
|
-
this.editTable('row', null);
|
|
2361
|
-
}
|
|
3279
|
+
let x = Math.ceil(e.offsetX / 18);
|
|
3280
|
+
let y = Math.ceil(e.offsetY / 18);
|
|
3281
|
+
x = x < 1 ? 1 : x;
|
|
3282
|
+
y = y < 1 ? 1 : y;
|
|
2362
3283
|
|
|
2363
|
-
|
|
2364
|
-
|
|
3284
|
+
if (this.options.get('_rtl')) {
|
|
3285
|
+
this.tableHighlight.style.left = x * 18 - 13 + 'px';
|
|
3286
|
+
x = 11 - x;
|
|
3287
|
+
}
|
|
2365
3288
|
|
|
2366
|
-
|
|
2367
|
-
|
|
3289
|
+
this.tableHighlight.style.width = x + 'em';
|
|
3290
|
+
this.tableHighlight.style.height = y + 'em';
|
|
2368
3291
|
|
|
2369
|
-
|
|
2370
|
-
|
|
2371
|
-
|
|
2372
|
-
|
|
3292
|
+
const x_u = x < 5 ? 5 : x > 8 ? 10 : x + 2;
|
|
3293
|
+
const y_u = y < 5 ? 5 : y > 8 ? 10 : y + 2;
|
|
3294
|
+
this.tableUnHighlight.style.width = x_u + 'em';
|
|
3295
|
+
this.tableUnHighlight.style.height = y_u + 'em';
|
|
2373
3296
|
|
|
2374
|
-
|
|
2375
|
-
this.
|
|
2376
|
-
x = 11 - x;
|
|
3297
|
+
dom.utils.changeTxt(this.tableDisplay, x + ' x ' + y);
|
|
3298
|
+
this._tableXY = [x, y];
|
|
2377
3299
|
}
|
|
2378
3300
|
|
|
2379
|
-
|
|
2380
|
-
|
|
2381
|
-
|
|
2382
|
-
|
|
2383
|
-
|
|
2384
|
-
|
|
2385
|
-
this.tableUnHighlight.style.height = y_u + 'em';
|
|
3301
|
+
/**
|
|
3302
|
+
* @description Executes the selected action when the table picker is clicked.
|
|
3303
|
+
*/
|
|
3304
|
+
#OnClickTablePicker() {
|
|
3305
|
+
this.action();
|
|
3306
|
+
}
|
|
2386
3307
|
|
|
2387
|
-
|
|
2388
|
-
|
|
2389
|
-
}
|
|
3308
|
+
/**
|
|
3309
|
+
* @description Handles multi-selection of table cells.
|
|
3310
|
+
* @param {MouseEvent} e The mouse event.
|
|
3311
|
+
*/
|
|
3312
|
+
#OnCellMultiSelect(e) {
|
|
3313
|
+
this.editor._preventBlur = true;
|
|
3314
|
+
const target = /** @type {HTMLTableCellElement} */ (dom.query.getParentElement(dom.query.getEventTarget(e), dom.check.isTableCell));
|
|
2390
3315
|
|
|
2391
|
-
|
|
2392
|
-
|
|
2393
|
-
|
|
3316
|
+
if (this._shift) {
|
|
3317
|
+
if (target === this._fixedCell) {
|
|
3318
|
+
this._shift = false;
|
|
3319
|
+
this._deleteStyleSelectedCells();
|
|
3320
|
+
this._toggleEditor(true);
|
|
3321
|
+
this.__removeGlobalEvents();
|
|
3322
|
+
return;
|
|
3323
|
+
} else {
|
|
3324
|
+
this._toggleEditor(false);
|
|
3325
|
+
}
|
|
3326
|
+
} else if (!this._ref) {
|
|
3327
|
+
if (target === this._fixedCell) return;
|
|
3328
|
+
else this._toggleEditor(false);
|
|
3329
|
+
}
|
|
2394
3330
|
|
|
2395
|
-
|
|
2396
|
-
|
|
3331
|
+
if (!target || target === this._selectedCell || this._fixedCellName !== target.nodeName || this._selectedTable !== dom.query.getParentElement(target, 'TABLE')) {
|
|
3332
|
+
return;
|
|
3333
|
+
}
|
|
2397
3334
|
|
|
2398
|
-
|
|
2399
|
-
return `<${nodeName}><div><br></div></${nodeName}>`.repeat(cnt);
|
|
2400
|
-
} else {
|
|
2401
|
-
return domUtils.createElement(nodeName, null, '<div><br></div>');
|
|
3335
|
+
this._setMultiCells(this._fixedCell, (this._selectedCell = target));
|
|
2402
3336
|
}
|
|
2403
|
-
}
|
|
2404
3337
|
|
|
2405
|
-
|
|
2406
|
-
|
|
2407
|
-
|
|
3338
|
+
/**
|
|
3339
|
+
* @description Stops multi-selection of table cells.
|
|
3340
|
+
* @param {MouseEvent} e The mouse event.
|
|
3341
|
+
*/
|
|
3342
|
+
#OffCellMultiSelect(e) {
|
|
3343
|
+
e.stopPropagation();
|
|
2408
3344
|
|
|
2409
|
-
|
|
2410
|
-
if (target === this._fixedCell) {
|
|
2411
|
-
this._shift = false;
|
|
2412
|
-
this._deleteStyleSelectedCells();
|
|
3345
|
+
if (!this._shift) {
|
|
2413
3346
|
this._toggleEditor(true);
|
|
2414
3347
|
this.__removeGlobalEvents();
|
|
2415
|
-
|
|
3348
|
+
} else if (this.__globalEvents.touchOff) {
|
|
3349
|
+
this.__globalEvents.touchOff = this.eventManager.removeGlobalEvent(this.__globalEvents.touchOff);
|
|
3350
|
+
}
|
|
3351
|
+
|
|
3352
|
+
if (!this._fixedCell || !this._selectedTable) return;
|
|
3353
|
+
|
|
3354
|
+
this._setMergeSplitButton();
|
|
3355
|
+
this._selectedCells = Array.from(this._selectedTable.querySelectorAll('.se-selected-table-cell'));
|
|
3356
|
+
|
|
3357
|
+
if (this._shift) return;
|
|
3358
|
+
|
|
3359
|
+
if (this._fixedCell && this._selectedCell) {
|
|
3360
|
+
this.#focusEdge(this._fixedCell);
|
|
3361
|
+
if (this._fixedCell === this._selectedCell) {
|
|
3362
|
+
dom.utils.removeClass(this._fixedCell, 'se-selected-table-cell');
|
|
3363
|
+
}
|
|
3364
|
+
}
|
|
3365
|
+
|
|
3366
|
+
const displayCell = this._selectedCells?.length > 0 ? this._selectedCell : this._fixedCell;
|
|
3367
|
+
this._setController(displayCell);
|
|
3368
|
+
}
|
|
3369
|
+
|
|
3370
|
+
/**
|
|
3371
|
+
* @description Handles the removal of shift-based selection.
|
|
3372
|
+
*/
|
|
3373
|
+
#OffCellShift() {
|
|
3374
|
+
if (!this._ref) {
|
|
3375
|
+
this._closeController();
|
|
2416
3376
|
} else {
|
|
2417
|
-
this.
|
|
3377
|
+
this.__removeGlobalEvents();
|
|
3378
|
+
this._toggleEditor(true);
|
|
3379
|
+
|
|
3380
|
+
this.#focusEdge(this._fixedCell);
|
|
3381
|
+
|
|
3382
|
+
const displayCell = this._selectedCells?.length > 0 ? this._selectedCell : this._fixedCell;
|
|
3383
|
+
this._setController(displayCell);
|
|
2418
3384
|
}
|
|
2419
|
-
} else if (!this._ref) {
|
|
2420
|
-
if (target === this._fixedCell) return;
|
|
2421
|
-
else this._toggleEditor(false);
|
|
2422
3385
|
}
|
|
2423
3386
|
|
|
2424
|
-
|
|
2425
|
-
|
|
3387
|
+
/**
|
|
3388
|
+
* @description Handles the removal of touch-based selection.
|
|
3389
|
+
*/
|
|
3390
|
+
#OffCellTouch() {
|
|
3391
|
+
this.close();
|
|
2426
3392
|
}
|
|
2427
3393
|
|
|
2428
|
-
|
|
2429
|
-
|
|
3394
|
+
/**
|
|
3395
|
+
* @description Focus cell
|
|
3396
|
+
* @param {HTMLElement} cell Target node
|
|
3397
|
+
*/
|
|
3398
|
+
#focusEdge(cell) {
|
|
3399
|
+
if (!env.isMobile) this.editor.focusEdge(cell);
|
|
3400
|
+
}
|
|
2430
3401
|
}
|
|
2431
3402
|
|
|
2432
|
-
|
|
2433
|
-
|
|
3403
|
+
/**
|
|
3404
|
+
* @private
|
|
3405
|
+
* @description Checks if the given node is a resizable table element.
|
|
3406
|
+
* @param {Node} node The DOM node to check.
|
|
3407
|
+
* @returns {boolean} True if the node is a table-related resizable element.
|
|
3408
|
+
*/
|
|
3409
|
+
function IsResizeEls(node) {
|
|
3410
|
+
return /^(TD|TH|TR)$/i.test(node?.nodeName);
|
|
3411
|
+
}
|
|
2434
3412
|
|
|
2435
|
-
|
|
2436
|
-
|
|
2437
|
-
|
|
2438
|
-
|
|
2439
|
-
|
|
2440
|
-
|
|
3413
|
+
/**
|
|
3414
|
+
* @private
|
|
3415
|
+
* @description Checks if a table cell is at its edge based on the mouse event.
|
|
3416
|
+
* @param {MouseEvent} event The mouse event.
|
|
3417
|
+
* @param {Element} tableCell The table cell to check.
|
|
3418
|
+
* @returns {Object} An object containing edge detection details.
|
|
3419
|
+
*/
|
|
3420
|
+
function CheckCellEdge(event, tableCell) {
|
|
3421
|
+
const startX = event.clientX;
|
|
3422
|
+
const startWidth = numbers.get(_w.getComputedStyle(tableCell).width, CELL_DECIMAL_END);
|
|
3423
|
+
const rect = tableCell.getBoundingClientRect();
|
|
3424
|
+
const offsetX = Math.round(startX - rect.left);
|
|
3425
|
+
const isLeft = offsetX <= CELL_SELECT_MARGIN;
|
|
3426
|
+
const is = isLeft || startWidth - offsetX <= CELL_SELECT_MARGIN;
|
|
2441
3427
|
|
|
2442
|
-
|
|
3428
|
+
return {
|
|
3429
|
+
is,
|
|
3430
|
+
isLeft,
|
|
3431
|
+
startX
|
|
3432
|
+
};
|
|
3433
|
+
}
|
|
2443
3434
|
|
|
2444
|
-
|
|
2445
|
-
|
|
3435
|
+
/**
|
|
3436
|
+
* @private
|
|
3437
|
+
* @description Checks if a row is at its edge based on the mouse event.
|
|
3438
|
+
* @param {MouseEvent} event The mouse event.
|
|
3439
|
+
* @param {Element} tableCell The table row cell to check.
|
|
3440
|
+
* @returns {Object} An object containing row edge detection details.
|
|
3441
|
+
*/
|
|
3442
|
+
function CheckRowEdge(event, tableCell) {
|
|
3443
|
+
const startY = event.clientY;
|
|
3444
|
+
const startHeight = numbers.get(_w.getComputedStyle(tableCell).height, CELL_DECIMAL_END);
|
|
3445
|
+
const rect = tableCell.getBoundingClientRect();
|
|
3446
|
+
const is = Math.ceil(startHeight + rect.top - startY) <= ROW_SELECT_MARGIN;
|
|
2446
3447
|
|
|
2447
|
-
|
|
2448
|
-
|
|
3448
|
+
return {
|
|
3449
|
+
is,
|
|
3450
|
+
startY
|
|
3451
|
+
};
|
|
2449
3452
|
}
|
|
2450
3453
|
|
|
2451
|
-
|
|
2452
|
-
|
|
3454
|
+
/**
|
|
3455
|
+
* @private
|
|
3456
|
+
* @description Creates table cells as elements strings.
|
|
3457
|
+
* @param {string} nodeName The tag name of the cell (TD or TH).
|
|
3458
|
+
* @param {number} cnt The number of cells to create.
|
|
3459
|
+
* @returns {string} The created cells.
|
|
3460
|
+
*/
|
|
3461
|
+
function CreateCellsString(nodeName, cnt) {
|
|
3462
|
+
nodeName = nodeName.toLowerCase();
|
|
3463
|
+
return `<${nodeName}><div><br></div></${nodeName}>`.repeat(cnt);
|
|
2453
3464
|
}
|
|
2454
3465
|
|
|
2455
|
-
|
|
2456
|
-
|
|
3466
|
+
/**
|
|
3467
|
+
* @private
|
|
3468
|
+
* @description Creates table cells as element HTML.
|
|
3469
|
+
* @param {string} nodeName The tag name of the cell (TD or TH).
|
|
3470
|
+
* @returns {HTMLTableCellElement} The created cells.
|
|
3471
|
+
*/
|
|
3472
|
+
function CreateCellsHTML(nodeName) {
|
|
3473
|
+
nodeName = nodeName.toLowerCase();
|
|
3474
|
+
return /** @type {HTMLTableCellElement} */ (dom.utils.createElement(nodeName, null, '<div><br></div>'));
|
|
2457
3475
|
}
|
|
2458
3476
|
|
|
3477
|
+
/**
|
|
3478
|
+
* @private
|
|
3479
|
+
* @description Gets the maximum number of columns in a table.
|
|
3480
|
+
* @param {HTMLTableElement} table The table element.
|
|
3481
|
+
* @returns {number} The maximum number of columns in the table.
|
|
3482
|
+
*/
|
|
2459
3483
|
function GetMaxColumns(table) {
|
|
3484
|
+
const rows = table.rows;
|
|
2460
3485
|
let maxColumns = 0;
|
|
2461
3486
|
|
|
2462
|
-
for (
|
|
3487
|
+
for (let i = 0, len = rows.length; i < len; i++) {
|
|
3488
|
+
const cells = rows[i].cells;
|
|
2463
3489
|
let columnCount = 0;
|
|
2464
|
-
|
|
2465
|
-
|
|
3490
|
+
|
|
3491
|
+
for (let j = 0, jLen = cells.length; j < jLen; j++) {
|
|
3492
|
+
columnCount += cells[j].colSpan;
|
|
2466
3493
|
}
|
|
3494
|
+
|
|
2467
3495
|
maxColumns = Math.max(maxColumns, columnCount);
|
|
2468
3496
|
}
|
|
2469
3497
|
|
|
2470
3498
|
return maxColumns;
|
|
2471
3499
|
}
|
|
2472
3500
|
|
|
3501
|
+
/**
|
|
3502
|
+
* @private
|
|
3503
|
+
* @description Handles border style changes in table properties.
|
|
3504
|
+
* @param {string} command The border style command.
|
|
3505
|
+
*/
|
|
2473
3506
|
function OnPropsBorderEdit(command) {
|
|
2474
3507
|
this.propTargets.border_style.textContent = command;
|
|
2475
3508
|
this._disableBorderProps(command === BORDER_LIST[0]);
|
|
2476
3509
|
this.selectMenu_props_border.close();
|
|
2477
3510
|
}
|
|
2478
3511
|
|
|
3512
|
+
/**
|
|
3513
|
+
* @private
|
|
3514
|
+
* @description Handles border format changes in table properties.
|
|
3515
|
+
* @param {string} defaultCommand The default border format command.
|
|
3516
|
+
* @param {string} command The new border format command.
|
|
3517
|
+
*/
|
|
2479
3518
|
function OnPropsBorderFormatEdit(defaultCommand, command) {
|
|
2480
3519
|
const { border_format } = this.propTargets;
|
|
2481
3520
|
|
|
2482
3521
|
border_format.setAttribute('se-border-format', command);
|
|
2483
3522
|
border_format.firstElementChild.innerHTML = this.icons[BORDER_FORMATS[command]];
|
|
2484
|
-
if (command !== defaultCommand)
|
|
2485
|
-
else
|
|
3523
|
+
if (command !== defaultCommand) dom.utils.addClass(border_format, 'active');
|
|
3524
|
+
else dom.utils.removeClass(border_format, 'active');
|
|
2486
3525
|
|
|
2487
3526
|
this.selectMenu_props_border_format.close();
|
|
2488
3527
|
this.selectMenu_props_border_format_oneCell.close();
|
|
2489
3528
|
}
|
|
2490
3529
|
|
|
3530
|
+
/**
|
|
3531
|
+
* @description Creates the table properties controller.
|
|
3532
|
+
* @param {ClipboardEvent} e - Event object
|
|
3533
|
+
* @param {HTMLElement} container - The container element
|
|
3534
|
+
* @param {NodeListOf<HTMLTableCellElement>} selectedCells - The selected table cells
|
|
3535
|
+
*/
|
|
3536
|
+
function SetClipboardSelectedTableCells(e, container, selectedCells) {
|
|
3537
|
+
e.preventDefault();
|
|
3538
|
+
e.stopPropagation();
|
|
3539
|
+
|
|
3540
|
+
const originalTable = selectedCells[0].closest('table');
|
|
3541
|
+
const tempTable = originalTable.cloneNode(false);
|
|
3542
|
+
const tbody = dom.utils.createElement('tbody');
|
|
3543
|
+
tempTable.appendChild(tbody);
|
|
3544
|
+
|
|
3545
|
+
const cellPositions = new Map();
|
|
3546
|
+
selectedCells.forEach((cell) => {
|
|
3547
|
+
cellPositions.set(cell, true);
|
|
3548
|
+
});
|
|
3549
|
+
|
|
3550
|
+
const rows = originalTable.rows;
|
|
3551
|
+
const rowCount = rows.length;
|
|
3552
|
+
const colCount = Array.from(rows[0].cells).reduce((sum, cell) => sum + (cell.colSpan || 1), 0);
|
|
3553
|
+
const matrix = Array.from({ length: rowCount }, () => Array(colCount).fill(null));
|
|
3554
|
+
|
|
3555
|
+
// build matrix
|
|
3556
|
+
for (let r = 0, realRow = 0; r < rowCount; r++, realRow++) {
|
|
3557
|
+
const cells = rows[r].cells;
|
|
3558
|
+
for (let c = 0, realCol = 0, cLen = cells.length; c < cLen; c++) {
|
|
3559
|
+
while (matrix[realRow][realCol]) realCol++;
|
|
3560
|
+
const cell = cells[c];
|
|
3561
|
+
const rowspan = cell.rowSpan || 1;
|
|
3562
|
+
const colspan = cell.colSpan || 1;
|
|
3563
|
+
for (let i = 0; i < rowspan; i++) {
|
|
3564
|
+
for (let j = 0; j < colspan; j++) {
|
|
3565
|
+
matrix[realRow + i][realCol + j] = cell;
|
|
3566
|
+
}
|
|
3567
|
+
}
|
|
3568
|
+
realCol += colspan;
|
|
3569
|
+
}
|
|
3570
|
+
}
|
|
3571
|
+
|
|
3572
|
+
// construct new table
|
|
3573
|
+
for (let r = 0; r < rowCount; r++) {
|
|
3574
|
+
let newRow;
|
|
3575
|
+
for (let c = 0; c < colCount; c++) {
|
|
3576
|
+
const cell = matrix[r][c];
|
|
3577
|
+
if (!cell || !cellPositions.has(cell)) continue;
|
|
3578
|
+
|
|
3579
|
+
if (!newRow) {
|
|
3580
|
+
newRow = dom.utils.createElement('tr');
|
|
3581
|
+
tbody.appendChild(newRow);
|
|
3582
|
+
}
|
|
3583
|
+
|
|
3584
|
+
if (newRow.lastChild && matrix[r][c - 1] === cell) continue;
|
|
3585
|
+
if (r > 0 && matrix[r - 1][c] === cell) continue;
|
|
3586
|
+
|
|
3587
|
+
const clonedCell = cell.cloneNode(true);
|
|
3588
|
+
|
|
3589
|
+
// recalculate rowspan and colspan
|
|
3590
|
+
let rowspan = 1;
|
|
3591
|
+
let colspan = 1;
|
|
3592
|
+
while (r + rowspan < rowCount && matrix[r + rowspan][c] === cell) rowspan++;
|
|
3593
|
+
while (c + colspan < colCount && matrix[r][c + colspan] === cell) colspan++;
|
|
3594
|
+
|
|
3595
|
+
if (rowspan > 1) clonedCell.rowSpan = rowspan;
|
|
3596
|
+
if (colspan > 1) clonedCell.colSpan = colspan;
|
|
3597
|
+
|
|
3598
|
+
newRow.appendChild(clonedCell);
|
|
3599
|
+
}
|
|
3600
|
+
}
|
|
3601
|
+
|
|
3602
|
+
const figure = dom.utils.createElement('figure');
|
|
3603
|
+
figure.className = container.className;
|
|
3604
|
+
figure.appendChild(tempTable);
|
|
3605
|
+
|
|
3606
|
+
const htmlContent = `<html><body><!--StartFragment-->${figure.outerHTML}<!--EndFragment--></body></html>`;
|
|
3607
|
+
e.clipboardData.setData('text/html', htmlContent);
|
|
3608
|
+
}
|
|
3609
|
+
|
|
3610
|
+
function _CellFormZIndex(value) {
|
|
3611
|
+
this.controller_cell.bringToTop(value);
|
|
3612
|
+
}
|
|
3613
|
+
|
|
3614
|
+
/** --------------------- HTML Create --------------------- */
|
|
2491
3615
|
// init element
|
|
2492
3616
|
function CreateSplitMenu(lang) {
|
|
2493
|
-
const menus =
|
|
3617
|
+
const menus = dom.utils.createElement(
|
|
2494
3618
|
'DIV',
|
|
2495
3619
|
null,
|
|
2496
3620
|
/*html*/ `
|
|
@@ -2506,7 +3630,7 @@ function CreateSplitMenu(lang) {
|
|
|
2506
3630
|
}
|
|
2507
3631
|
|
|
2508
3632
|
function CreateColumnMenu(lang, icons) {
|
|
2509
|
-
const menus =
|
|
3633
|
+
const menus = dom.utils.createElement(
|
|
2510
3634
|
'DIV',
|
|
2511
3635
|
null,
|
|
2512
3636
|
/*html*/ `
|
|
@@ -2525,7 +3649,7 @@ function CreateColumnMenu(lang, icons) {
|
|
|
2525
3649
|
}
|
|
2526
3650
|
|
|
2527
3651
|
function CreateRowMenu(lang, icons) {
|
|
2528
|
-
const menus =
|
|
3652
|
+
const menus = dom.utils.createElement(
|
|
2529
3653
|
'DIV',
|
|
2530
3654
|
null,
|
|
2531
3655
|
/*html*/ `
|
|
@@ -2554,7 +3678,7 @@ function CreateBorderMenu() {
|
|
|
2554
3678
|
</div>`;
|
|
2555
3679
|
}
|
|
2556
3680
|
|
|
2557
|
-
const menus =
|
|
3681
|
+
const menus = dom.utils.createElement('DIV', null, html);
|
|
2558
3682
|
return { items: BORDER_LIST, menus: menus.querySelectorAll('div') };
|
|
2559
3683
|
}
|
|
2560
3684
|
|
|
@@ -2575,7 +3699,7 @@ function CreateBorderFormatMenu(langs, icons, indideFormats) {
|
|
|
2575
3699
|
</button>`;
|
|
2576
3700
|
}
|
|
2577
3701
|
|
|
2578
|
-
const menus =
|
|
3702
|
+
const menus = dom.utils.createElement('DIV', null, html);
|
|
2579
3703
|
return { items, menus: menus.querySelectorAll('button') };
|
|
2580
3704
|
}
|
|
2581
3705
|
|
|
@@ -2588,7 +3712,7 @@ function CreateHTML() {
|
|
|
2588
3712
|
</div>
|
|
2589
3713
|
<div class="se-table-size-display">1 x 1</div>`;
|
|
2590
3714
|
|
|
2591
|
-
return
|
|
3715
|
+
return dom.utils.createElement('DIV', { class: 'se-dropdown se-selector-table' }, html);
|
|
2592
3716
|
}
|
|
2593
3717
|
|
|
2594
3718
|
function CreateHTML_controller_table({ lang, icons }) {
|
|
@@ -2625,6 +3749,12 @@ function CreateHTML_controller_table({ lang, icons }) {
|
|
|
2625
3749
|
<span class="se-tooltip-text">${lang.minSize}</span>
|
|
2626
3750
|
</span>
|
|
2627
3751
|
</button>
|
|
3752
|
+
<button type="button" data-command="copy" class="se-btn se-tooltip">
|
|
3753
|
+
${icons.copy}
|
|
3754
|
+
<span class="se-tooltip-inner">
|
|
3755
|
+
<span class="se-tooltip-text">${lang.copy}</span>
|
|
3756
|
+
</span>
|
|
3757
|
+
</button>
|
|
2628
3758
|
<button type="button" data-command="remove" class="se-btn se-tooltip">
|
|
2629
3759
|
${icons.delete}
|
|
2630
3760
|
<span class="se-tooltip-inner">
|
|
@@ -2633,9 +3763,13 @@ function CreateHTML_controller_table({ lang, icons }) {
|
|
|
2633
3763
|
</button>
|
|
2634
3764
|
</div>`;
|
|
2635
3765
|
|
|
2636
|
-
return
|
|
3766
|
+
return dom.utils.createElement('DIV', { class: 'se-controller se-controller-table' }, html);
|
|
2637
3767
|
}
|
|
2638
3768
|
|
|
3769
|
+
/**
|
|
3770
|
+
* @param {__se__EditorCore} editor
|
|
3771
|
+
* @returns {{ html: HTMLElement, splitButton: HTMLButtonElement, columnButton: HTMLButtonElement, rowButton: HTMLButtonElement, mergeButton: HTMLButtonElement, unmergeButton: HTMLButtonElement }}
|
|
3772
|
+
*/
|
|
2639
3773
|
function CreateHTML_controller_cell({ lang, icons }, cellControllerTop) {
|
|
2640
3774
|
const html = /*html*/ `
|
|
2641
3775
|
<div class="se-arrow se-arrow-${cellControllerTop ? 'down se-visible-hidden' : 'up'}"></div>
|
|
@@ -2669,12 +3803,50 @@ function CreateHTML_controller_cell({ lang, icons }, cellControllerTop) {
|
|
|
2669
3803
|
<span class="se-tooltip-inner">
|
|
2670
3804
|
<span class="se-tooltip-text">${lang.splitCells}</span>
|
|
2671
3805
|
</span>
|
|
3806
|
+
</button>
|
|
3807
|
+
<button type="button" data-command="unmerge" class="se-btn se-tooltip">
|
|
3808
|
+
${icons.unmerge_cell}
|
|
3809
|
+
<span class="se-tooltip-inner">
|
|
3810
|
+
<span class="se-tooltip-text">${lang.unmergeCells}</span>
|
|
3811
|
+
</span>
|
|
2672
3812
|
</button>
|
|
2673
3813
|
</div>`;
|
|
2674
3814
|
|
|
2675
|
-
|
|
3815
|
+
const content = dom.utils.createElement('DIV', { class: 'se-controller se-controller-table-cell' }, html);
|
|
3816
|
+
|
|
3817
|
+
return {
|
|
3818
|
+
html: content,
|
|
3819
|
+
splitButton: content.querySelector('[data-command="onsplit"]'),
|
|
3820
|
+
columnButton: content.querySelector('[data-command="oncolumn"]'),
|
|
3821
|
+
rowButton: content.querySelector('[data-command="onrow"]'),
|
|
3822
|
+
mergeButton: content.querySelector('[data-command="merge"]'),
|
|
3823
|
+
unmergeButton: content.querySelector('[data-command="unmerge"]')
|
|
3824
|
+
};
|
|
2676
3825
|
}
|
|
2677
3826
|
|
|
3827
|
+
/**
|
|
3828
|
+
* @typedef {Object} TableCtrlProps
|
|
3829
|
+
* @property {HTMLElement} html
|
|
3830
|
+
* @property {HTMLElement} controller_props_title
|
|
3831
|
+
* @property {HTMLButtonElement} borderButton
|
|
3832
|
+
* @property {HTMLButtonElement} borderFormatButton
|
|
3833
|
+
* @property {HTMLElement} cell_alignment
|
|
3834
|
+
* @property {HTMLElement} cell_alignment_vertical
|
|
3835
|
+
* @property {HTMLElement} cell_alignment_table_text
|
|
3836
|
+
* @property {HTMLButtonElement} border_style
|
|
3837
|
+
* @property {HTMLInputElement} border_color
|
|
3838
|
+
* @property {HTMLInputElement} border_width
|
|
3839
|
+
* @property {HTMLInputElement} back_color
|
|
3840
|
+
* @property {HTMLInputElement} font_color
|
|
3841
|
+
* @property {HTMLButtonElement} palette_border_button
|
|
3842
|
+
* @property {HTMLButtonElement} font_bold
|
|
3843
|
+
* @property {HTMLButtonElement} font_underline
|
|
3844
|
+
* @property {HTMLButtonElement} font_italic
|
|
3845
|
+
* @property {HTMLButtonElement} font_strike
|
|
3846
|
+
*
|
|
3847
|
+
* @param {__se__EditorCore} editor - Editor instance
|
|
3848
|
+
* @returns {TableCtrlProps}
|
|
3849
|
+
*/
|
|
2678
3850
|
function CreateHTML_controller_properties({ lang, icons, options }) {
|
|
2679
3851
|
const alignItems = options.get('_rtl') ? ['right', 'center', 'left', 'justify'] : ['left', 'center', 'right', 'justify'];
|
|
2680
3852
|
let alignHtml = '';
|
|
@@ -2682,14 +3854,12 @@ function CreateHTML_controller_properties({ lang, icons, options }) {
|
|
|
2682
3854
|
item = alignItems[i];
|
|
2683
3855
|
text = lang['align' + item.charAt(0).toUpperCase() + item.slice(1)];
|
|
2684
3856
|
alignHtml += /*html*/ `
|
|
2685
|
-
<
|
|
2686
|
-
|
|
2687
|
-
|
|
2688
|
-
<span class="se-tooltip-
|
|
2689
|
-
|
|
2690
|
-
|
|
2691
|
-
</button>
|
|
2692
|
-
</li>`;
|
|
3857
|
+
<button type="button" class="se-btn se-tooltip" data-command="props_align" data-value="${item}" title="${text}" aria-label="${text}">
|
|
3858
|
+
${icons['align_' + item]}
|
|
3859
|
+
<span class="se-tooltip-inner">
|
|
3860
|
+
<span class="se-tooltip-text">${text}</span>
|
|
3861
|
+
</span>
|
|
3862
|
+
</button>`;
|
|
2693
3863
|
}
|
|
2694
3864
|
|
|
2695
3865
|
// vertical align html
|
|
@@ -2699,14 +3869,12 @@ function CreateHTML_controller_properties({ lang, icons, options }) {
|
|
|
2699
3869
|
item = verticalAligns[i];
|
|
2700
3870
|
text = lang['align' + item.charAt(0).toUpperCase() + item.slice(1)];
|
|
2701
3871
|
verticalAlignHtml += /*html*/ `
|
|
2702
|
-
<
|
|
2703
|
-
|
|
2704
|
-
|
|
2705
|
-
<span class="se-tooltip-
|
|
2706
|
-
|
|
2707
|
-
|
|
2708
|
-
</button>
|
|
2709
|
-
</li>`;
|
|
3872
|
+
<button type="button" class="se-btn se-tooltip" data-command="props_align_vertical" data-value="${item}" title="${text}" aria-label="${text}">
|
|
3873
|
+
${icons['align_' + item]}
|
|
3874
|
+
<span class="se-tooltip-inner">
|
|
3875
|
+
<span class="se-tooltip-text">${text}</span>
|
|
3876
|
+
</span>
|
|
3877
|
+
</button>`;
|
|
2710
3878
|
}
|
|
2711
3879
|
|
|
2712
3880
|
const html = /*html*/ `
|
|
@@ -2789,12 +3957,14 @@ function CreateHTML_controller_properties({ lang, icons, options }) {
|
|
|
2789
3957
|
</div>
|
|
2790
3958
|
|
|
2791
3959
|
<div class="se-table-props-align">
|
|
2792
|
-
<label>${lang.align}</label>
|
|
2793
|
-
<div class="se-form-group se-form-w0 se-list-inner
|
|
2794
|
-
<
|
|
2795
|
-
|
|
2796
|
-
|
|
2797
|
-
<
|
|
3960
|
+
<label>${lang.align} <span class="__se__a_table_t">( ${lang.table} )</span></label>
|
|
3961
|
+
<div class="se-form-group se-form-w0 se-list-inner">
|
|
3962
|
+
<div class="__se__a_h">
|
|
3963
|
+
${alignHtml}
|
|
3964
|
+
</div>
|
|
3965
|
+
<div class="__se__a_v">
|
|
3966
|
+
${verticalAlignHtml}
|
|
3967
|
+
</div>
|
|
2798
3968
|
</div>
|
|
2799
3969
|
</div>
|
|
2800
3970
|
</div>
|
|
@@ -2804,7 +3974,27 @@ function CreateHTML_controller_properties({ lang, icons, options }) {
|
|
|
2804
3974
|
</div>
|
|
2805
3975
|
</div>`;
|
|
2806
3976
|
|
|
2807
|
-
|
|
3977
|
+
const content = dom.utils.createElement('DIV', { class: 'se-controller se-table-props' }, html);
|
|
3978
|
+
|
|
3979
|
+
return {
|
|
3980
|
+
html: content,
|
|
3981
|
+
controller_props_title: content.querySelector('.se-controller-title'),
|
|
3982
|
+
borderButton: content.querySelector('[data-command="props_onborder_style"]'),
|
|
3983
|
+
borderFormatButton: content.querySelector('[data-command="props_onborder_format"]'),
|
|
3984
|
+
cell_alignment: content.querySelector('.se-table-props-align .__se__a_h'),
|
|
3985
|
+
cell_alignment_vertical: content.querySelector('.se-table-props-align .__se__a_v'),
|
|
3986
|
+
cell_alignment_table_text: content.querySelector('.se-table-props-align .__se__a_table_t'),
|
|
3987
|
+
border_style: content.querySelector('[data-command="props_onborder_style"] .se-txt'),
|
|
3988
|
+
border_color: content.querySelector('.__se_border_color'),
|
|
3989
|
+
border_width: content.querySelector('.__se__border_size'),
|
|
3990
|
+
back_color: content.querySelector('.__se_back_color'),
|
|
3991
|
+
font_color: content.querySelector('.__se_font_color'),
|
|
3992
|
+
palette_border_button: content.querySelector('[data-command="props_onpalette"][data-value="border"]'),
|
|
3993
|
+
font_bold: content.querySelector('[data-command="props_font_style"][data-value="bold"]'),
|
|
3994
|
+
font_underline: content.querySelector('[data-command="props_font_style"][data-value="underline"]'),
|
|
3995
|
+
font_italic: content.querySelector('[data-command="props_font_style"][data-value="italic"]'),
|
|
3996
|
+
font_strike: content.querySelector('[data-command="props_font_style"][data-value="strike"]')
|
|
3997
|
+
};
|
|
2808
3998
|
}
|
|
2809
3999
|
|
|
2810
4000
|
export default Table;
|