suneditor 3.0.0-beta.9 → 3.0.0-rc.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +65 -57
- package/dist/suneditor-contents.min.css +1 -0
- package/dist/suneditor.min.css +1 -1
- package/dist/suneditor.min.js +1 -1
- package/package.json +110 -61
- package/src/assets/design/color.css +36 -17
- package/src/assets/design/size.css +2 -0
- package/src/assets/icons/defaultIcons.js +17 -2
- package/src/assets/suneditor-contents.css +51 -16
- package/src/assets/suneditor.css +116 -43
- package/src/core/config/contextProvider.js +288 -0
- package/src/core/config/eventManager.js +188 -0
- package/src/core/config/instanceCheck.js +59 -0
- package/src/core/config/optionProvider.js +452 -0
- package/src/core/editor.js +166 -1637
- package/src/core/event/actions/index.js +229 -0
- package/src/core/event/effects/common.registry.js +74 -0
- package/src/core/event/effects/keydown.registry.js +573 -0
- package/src/core/event/effects/ruleHelpers.js +148 -0
- package/src/core/event/eventOrchestrator.js +944 -0
- package/src/core/event/executor.js +27 -0
- package/src/core/{base/eventHandlers → event/handlers}/handler_toolbar.js +27 -28
- package/src/core/{base/eventHandlers → event/handlers}/handler_ww_clipboard.js +10 -8
- package/src/core/{base/eventHandlers → event/handlers}/handler_ww_dragDrop.js +22 -23
- package/src/core/event/handlers/handler_ww_input.js +75 -0
- package/src/core/event/handlers/handler_ww_key.js +228 -0
- package/src/core/event/handlers/handler_ww_mouse.js +166 -0
- package/src/core/event/ports.js +211 -0
- package/src/core/event/reducers/keydown.reducer.js +97 -0
- package/src/core/event/rules/keydown.rule.arrow.js +63 -0
- package/src/core/event/rules/keydown.rule.backspace.js +208 -0
- package/src/core/event/rules/keydown.rule.delete.js +132 -0
- package/src/core/event/rules/keydown.rule.enter.js +150 -0
- package/src/core/event/rules/keydown.rule.tab.js +35 -0
- package/src/core/event/support/defaultLineManager.js +136 -0
- package/src/core/event/support/selectionState.js +204 -0
- package/src/core/kernel/coreKernel.js +320 -0
- package/src/core/kernel/kernelInjector.js +19 -0
- package/src/core/kernel/store.js +173 -0
- package/src/core/{class → logic/dom}/char.js +42 -45
- package/src/core/logic/dom/format.js +1075 -0
- package/src/core/{class → logic/dom}/html.js +743 -624
- package/src/core/logic/dom/inline.js +1847 -0
- package/src/core/logic/dom/listFormat.js +601 -0
- package/src/core/{class → logic/dom}/nodeTransform.js +92 -72
- package/src/core/{class → logic/dom}/offset.js +254 -317
- package/src/core/logic/dom/selection.js +754 -0
- package/src/core/logic/panel/menu.js +389 -0
- package/src/core/logic/panel/toolbar.js +449 -0
- package/src/core/logic/panel/viewer.js +761 -0
- package/src/core/logic/shell/_commandExecutor.js +380 -0
- package/src/core/logic/shell/commandDispatcher.js +241 -0
- package/src/core/logic/shell/component.js +970 -0
- package/src/core/logic/shell/focusManager.js +110 -0
- package/src/core/{base → logic/shell}/history.js +110 -60
- package/src/core/logic/shell/pluginManager.js +363 -0
- package/src/core/logic/shell/shortcuts.js +130 -0
- package/src/core/logic/shell/ui.js +904 -0
- package/src/core/schema/context.js +66 -0
- package/src/core/schema/frameContext.js +160 -0
- package/src/core/schema/options.js +628 -0
- package/src/core/section/constructor.js +194 -500
- package/src/core/section/documentType.js +297 -222
- package/src/events.js +808 -543
- package/src/helper/clipboard.js +27 -16
- package/src/helper/converter.js +100 -78
- package/src/helper/dom/domCheck.js +56 -30
- package/src/helper/dom/domQuery.js +159 -89
- package/src/helper/dom/domUtils.js +114 -49
- package/src/helper/dom/index.js +5 -1
- package/src/helper/env.js +26 -26
- package/src/helper/index.js +1 -1
- package/src/helper/keyCodeMap.js +25 -28
- package/src/helper/numbers.js +4 -8
- package/src/helper/unicode.js +4 -8
- package/src/hooks/base.js +307 -0
- package/src/hooks/params.js +130 -0
- package/src/interfaces/contracts.js +227 -0
- package/src/interfaces/index.js +7 -0
- package/src/interfaces/plugins.js +239 -0
- package/src/langs/ckb.js +4 -4
- package/src/langs/cs.js +4 -4
- package/src/langs/da.js +4 -4
- package/src/langs/de.js +4 -4
- package/src/langs/en.js +4 -4
- package/src/langs/es.js +4 -4
- package/src/langs/fa.js +4 -4
- package/src/langs/fr.js +4 -4
- package/src/langs/he.js +4 -4
- package/src/langs/hu.js +4 -4
- package/src/langs/it.js +4 -4
- package/src/langs/ja.js +4 -4
- package/src/langs/km.js +4 -4
- package/src/langs/ko.js +4 -4
- package/src/langs/lv.js +4 -4
- package/src/langs/nl.js +4 -4
- package/src/langs/pl.js +4 -4
- package/src/langs/pt_br.js +13 -13
- package/src/langs/ro.js +4 -4
- package/src/langs/ru.js +4 -4
- package/src/langs/se.js +4 -4
- package/src/langs/tr.js +4 -4
- package/src/langs/uk.js +4 -4
- package/src/langs/ur.js +4 -4
- package/src/langs/zh_cn.js +4 -4
- package/src/modules/{Browser.js → contract/Browser.js} +119 -128
- package/src/modules/{ColorPicker.js → contract/ColorPicker.js} +132 -142
- package/src/modules/contract/Controller.js +589 -0
- package/src/modules/{Figure.js → contract/Figure.js} +591 -411
- package/src/modules/{HueSlider.js → contract/HueSlider.js} +125 -86
- package/src/modules/contract/Modal.js +357 -0
- package/src/modules/contract/index.js +9 -0
- package/src/modules/manager/ApiManager.js +197 -0
- package/src/modules/{FileManager.js → manager/FileManager.js} +128 -160
- package/src/modules/manager/index.js +5 -0
- package/src/modules/{ModalAnchorEditor.js → ui/ModalAnchorEditor.js} +108 -138
- package/src/modules/{SelectMenu.js → ui/SelectMenu.js} +119 -120
- package/src/modules/{_DragHandle.js → ui/_DragHandle.js} +1 -1
- package/src/modules/ui/index.js +6 -0
- package/src/plugins/browser/audioGallery.js +23 -26
- package/src/plugins/browser/fileBrowser.js +25 -28
- package/src/plugins/browser/fileGallery.js +20 -23
- package/src/plugins/browser/imageGallery.js +24 -23
- package/src/plugins/browser/videoGallery.js +27 -29
- package/src/plugins/command/blockquote.js +11 -17
- package/src/plugins/command/exportPDF.js +26 -26
- package/src/plugins/command/fileUpload.js +138 -133
- package/src/plugins/command/list_bulleted.js +48 -44
- package/src/plugins/command/list_numbered.js +48 -44
- package/src/plugins/dropdown/align.js +64 -50
- package/src/plugins/dropdown/backgroundColor.js +34 -35
- package/src/plugins/dropdown/{formatBlock.js → blockStyle.js} +43 -37
- package/src/plugins/dropdown/font.js +50 -36
- package/src/plugins/dropdown/fontColor.js +34 -35
- package/src/plugins/dropdown/hr.js +55 -50
- package/src/plugins/dropdown/layout.js +20 -15
- package/src/plugins/dropdown/lineHeight.js +46 -30
- package/src/plugins/dropdown/list.js +32 -33
- package/src/plugins/dropdown/paragraphStyle.js +40 -34
- package/src/plugins/dropdown/table/index.js +915 -0
- package/src/plugins/dropdown/table/render/table.html.js +308 -0
- package/src/plugins/dropdown/table/render/table.menu.js +121 -0
- package/src/plugins/dropdown/table/services/table.cell.js +465 -0
- package/src/plugins/dropdown/table/services/table.clipboard.js +414 -0
- package/src/plugins/dropdown/table/services/table.grid.js +504 -0
- package/src/plugins/dropdown/table/services/table.resize.js +463 -0
- package/src/plugins/dropdown/table/services/table.selection.js +466 -0
- package/src/plugins/dropdown/table/services/table.style.js +844 -0
- package/src/plugins/dropdown/table/shared/table.constants.js +109 -0
- package/src/plugins/dropdown/table/shared/table.utils.js +219 -0
- package/src/plugins/dropdown/template.js +20 -15
- package/src/plugins/dropdown/textStyle.js +28 -22
- package/src/plugins/field/mention.js +54 -49
- package/src/plugins/index.js +5 -5
- package/src/plugins/input/fontSize.js +100 -97
- package/src/plugins/input/pageNavigator.js +13 -10
- package/src/plugins/modal/audio.js +208 -219
- package/src/plugins/modal/drawing.js +99 -104
- package/src/plugins/modal/embed.js +323 -312
- package/src/plugins/modal/image/index.js +942 -0
- package/src/plugins/modal/image/render/image.html.js +150 -0
- package/src/plugins/modal/image/services/image.size.js +198 -0
- package/src/plugins/modal/image/services/image.upload.js +216 -0
- package/src/plugins/modal/image/shared/image.constants.js +20 -0
- package/src/plugins/modal/link.js +74 -54
- package/src/plugins/modal/math.js +126 -119
- package/src/plugins/modal/video/index.js +858 -0
- package/src/plugins/modal/video/render/video.html.js +131 -0
- package/src/plugins/modal/video/services/video.size.js +281 -0
- package/src/plugins/modal/video/services/video.upload.js +92 -0
- package/src/plugins/popup/anchor.js +57 -49
- package/src/suneditor.js +73 -61
- package/src/themes/cobalt.css +155 -0
- package/src/themes/dark.css +143 -120
- package/src/typedef.js +214 -63
- package/types/assets/icons/defaultIcons.d.ts +8 -0
- package/types/assets/suneditor-contents.css.d.ts +1 -0
- package/types/assets/suneditor.css.d.ts +1 -0
- package/types/core/config/contextProvider.d.ts +148 -0
- package/types/core/config/eventManager.d.ts +68 -0
- package/types/core/config/instanceCheck.d.ts +33 -0
- package/types/core/config/optionProvider.d.ts +147 -0
- package/types/core/editor.d.ts +27 -586
- package/types/core/event/actions/index.d.ts +50 -0
- package/types/core/event/effects/common.registry.d.ts +56 -0
- package/types/core/event/effects/keydown.registry.d.ts +80 -0
- package/types/core/event/effects/ruleHelpers.d.ts +36 -0
- package/types/core/event/eventOrchestrator.d.ts +191 -0
- package/types/core/event/executor.d.ts +13 -0
- package/types/core/event/handlers/handler_toolbar.d.ts +38 -0
- package/types/core/event/handlers/handler_ww_clipboard.d.ts +36 -0
- package/types/core/event/handlers/handler_ww_dragDrop.d.ts +26 -0
- package/types/core/event/handlers/handler_ww_input.d.ts +38 -0
- package/types/core/event/handlers/handler_ww_key.d.ts +40 -0
- package/types/core/event/handlers/handler_ww_mouse.d.ts +47 -0
- package/types/core/event/ports.d.ts +256 -0
- package/types/core/event/reducers/keydown.reducer.d.ts +84 -0
- package/types/core/event/rules/keydown.rule.arrow.d.ts +19 -0
- package/types/core/event/rules/keydown.rule.backspace.d.ts +18 -0
- package/types/core/event/rules/keydown.rule.delete.d.ts +18 -0
- package/types/core/event/rules/keydown.rule.enter.d.ts +18 -0
- package/types/core/event/rules/keydown.rule.tab.d.ts +18 -0
- package/types/core/event/support/defaultLineManager.d.ts +22 -0
- package/types/core/event/support/selectionState.d.ts +29 -0
- package/types/core/kernel/coreKernel.d.ts +219 -0
- package/types/core/kernel/kernelInjector.d.ts +16 -0
- package/types/core/kernel/store.d.ts +170 -0
- package/types/core/logic/dom/char.d.ts +46 -0
- package/types/core/logic/dom/format.d.ts +234 -0
- package/types/core/logic/dom/html.d.ts +290 -0
- package/types/core/logic/dom/inline.d.ts +93 -0
- package/types/core/logic/dom/listFormat.d.ts +101 -0
- package/types/core/logic/dom/nodeTransform.d.ts +110 -0
- package/types/core/logic/dom/offset.d.ts +335 -0
- package/types/core/logic/dom/selection.d.ts +165 -0
- package/types/core/logic/panel/menu.d.ts +93 -0
- package/types/core/logic/panel/toolbar.d.ts +128 -0
- package/types/core/logic/panel/viewer.d.ts +89 -0
- package/types/core/logic/shell/_commandExecutor.d.ts +18 -0
- package/types/core/logic/shell/commandDispatcher.d.ts +65 -0
- package/types/core/logic/shell/component.d.ts +182 -0
- package/types/core/logic/shell/focusManager.d.ts +31 -0
- package/types/core/{base → logic/shell}/history.d.ts +13 -12
- package/types/core/logic/shell/pluginManager.d.ts +115 -0
- package/types/core/logic/shell/shortcuts.d.ts +131 -0
- package/types/core/logic/shell/ui.d.ts +261 -0
- package/types/core/schema/context.d.ts +104 -0
- package/types/core/schema/frameContext.d.ts +320 -0
- package/types/core/schema/options.d.ts +1241 -0
- package/types/core/section/constructor.d.ts +117 -652
- package/types/core/section/documentType.d.ts +43 -61
- package/types/events.d.ts +796 -65
- package/types/helper/clipboard.d.ts +5 -4
- package/types/helper/converter.d.ts +55 -43
- package/types/helper/dom/domCheck.d.ts +27 -19
- package/types/helper/dom/domQuery.d.ts +76 -57
- package/types/helper/dom/domUtils.d.ts +62 -39
- package/types/helper/dom/index.d.ts +87 -1
- package/types/helper/env.d.ts +16 -13
- package/types/helper/index.d.ts +8 -2
- package/types/helper/keyCodeMap.d.ts +24 -23
- package/types/helper/numbers.d.ts +4 -6
- package/types/helper/unicode.d.ts +4 -3
- package/types/hooks/base.d.ts +239 -0
- package/types/hooks/params.d.ts +65 -0
- package/types/index.d.ts +20 -117
- package/types/interfaces/contracts.d.ts +183 -0
- package/types/interfaces/index.d.ts +3 -0
- package/types/interfaces/plugins.d.ts +168 -0
- package/types/langs/_Lang.d.ts +2 -2
- package/types/langs/index.d.ts +2 -2
- package/types/modules/contract/Browser.d.ts +262 -0
- package/types/modules/contract/ColorPicker.d.ts +99 -0
- package/types/modules/contract/Controller.d.ts +204 -0
- package/types/modules/contract/Figure.d.ts +529 -0
- package/types/modules/{HueSlider.d.ts → contract/HueSlider.d.ts} +39 -28
- package/types/modules/contract/Modal.d.ts +62 -0
- package/types/modules/contract/index.d.ts +7 -0
- package/types/modules/manager/ApiManager.d.ts +106 -0
- package/types/modules/manager/FileManager.d.ts +124 -0
- package/types/modules/manager/index.d.ts +3 -0
- package/types/modules/ui/ModalAnchorEditor.d.ts +152 -0
- package/types/modules/ui/SelectMenu.d.ts +107 -0
- package/types/modules/{_DragHandle.d.ts → ui/_DragHandle.d.ts} +1 -0
- package/types/modules/ui/index.d.ts +4 -0
- package/types/plugins/browser/audioGallery.d.ts +33 -41
- package/types/plugins/browser/fileBrowser.d.ts +42 -50
- package/types/plugins/browser/fileGallery.d.ts +33 -41
- package/types/plugins/browser/imageGallery.d.ts +30 -37
- package/types/plugins/browser/videoGallery.d.ts +33 -41
- package/types/plugins/command/blockquote.d.ts +4 -21
- package/types/plugins/command/exportPDF.d.ts +23 -33
- package/types/plugins/command/fileUpload.d.ts +80 -100
- package/types/plugins/command/list_bulleted.d.ts +9 -35
- package/types/plugins/command/list_numbered.d.ts +9 -35
- package/types/plugins/dropdown/align.d.ts +23 -46
- package/types/plugins/dropdown/backgroundColor.d.ts +35 -53
- package/types/plugins/dropdown/blockStyle.d.ts +45 -0
- package/types/plugins/dropdown/font.d.ts +18 -41
- package/types/plugins/dropdown/fontColor.d.ts +35 -53
- package/types/plugins/dropdown/hr.d.ts +26 -52
- package/types/plugins/dropdown/layout.d.ts +19 -25
- package/types/plugins/dropdown/lineHeight.d.ts +21 -39
- package/types/plugins/dropdown/list.d.ts +6 -34
- package/types/plugins/dropdown/paragraphStyle.d.ts +34 -45
- package/types/plugins/dropdown/table/index.d.ts +158 -0
- package/types/plugins/dropdown/table/render/table.html.d.ts +71 -0
- package/types/plugins/dropdown/table/render/table.menu.d.ts +59 -0
- package/types/plugins/dropdown/table/services/table.cell.d.ts +76 -0
- package/types/plugins/dropdown/table/services/table.clipboard.d.ts +26 -0
- package/types/plugins/dropdown/table/services/table.grid.d.ts +77 -0
- package/types/plugins/dropdown/table/services/table.resize.d.ts +72 -0
- package/types/plugins/dropdown/table/services/table.selection.d.ts +59 -0
- package/types/plugins/dropdown/table/services/table.style.d.ts +162 -0
- package/types/plugins/dropdown/table/shared/table.constants.d.ts +134 -0
- package/types/plugins/dropdown/table/shared/table.utils.d.ts +91 -0
- package/types/plugins/dropdown/template.d.ts +19 -25
- package/types/plugins/dropdown/textStyle.d.ts +23 -30
- package/types/plugins/field/mention.d.ts +66 -72
- package/types/plugins/index.d.ts +41 -40
- package/types/plugins/input/fontSize.d.ts +57 -96
- package/types/plugins/input/pageNavigator.d.ts +5 -8
- package/types/plugins/modal/audio.d.ts +60 -153
- package/types/plugins/modal/drawing.d.ts +16 -118
- package/types/plugins/modal/embed.d.ts +46 -166
- package/types/plugins/modal/image/index.d.ts +281 -0
- package/types/plugins/modal/image/render/image.html.d.ts +45 -0
- package/types/plugins/modal/image/services/image.size.d.ts +55 -0
- package/types/plugins/modal/image/services/image.upload.d.ts +24 -0
- package/types/plugins/modal/image/shared/image.constants.d.ts +17 -0
- package/types/plugins/modal/link.d.ts +46 -66
- package/types/plugins/modal/math.d.ts +17 -86
- package/types/plugins/modal/{video.d.ts → video/index.d.ts} +89 -221
- package/types/plugins/modal/video/render/video.html.d.ts +37 -0
- package/types/plugins/modal/video/services/video.size.d.ts +74 -0
- package/types/plugins/modal/video/services/video.upload.d.ts +19 -0
- package/types/plugins/popup/anchor.d.ts +8 -38
- package/types/suneditor.d.ts +55 -24
- package/types/typedef.d.ts +344 -228
- package/CONTRIBUTING.md +0 -186
- package/src/core/base/eventHandlers/handler_ww_key_input.js +0 -1200
- package/src/core/base/eventHandlers/handler_ww_mouse.js +0 -194
- package/src/core/base/eventManager.js +0 -1523
- package/src/core/class/component.js +0 -856
- package/src/core/class/format.js +0 -3433
- package/src/core/class/menu.js +0 -346
- package/src/core/class/selection.js +0 -610
- package/src/core/class/shortcuts.js +0 -98
- package/src/core/class/toolbar.js +0 -431
- package/src/core/class/ui.js +0 -424
- package/src/core/class/viewer.js +0 -750
- package/src/core/section/actives.js +0 -266
- package/src/core/section/context.js +0 -102
- package/src/editorInjector/_classes.js +0 -36
- package/src/editorInjector/_core.js +0 -87
- package/src/editorInjector/index.js +0 -73
- package/src/modules/ApiManager.js +0 -191
- package/src/modules/Controller.js +0 -474
- package/src/modules/Modal.js +0 -346
- package/src/modules/index.js +0 -14
- package/src/plugins/dropdown/table.js +0 -4034
- package/src/plugins/modal/image.js +0 -1376
- package/src/plugins/modal/video.js +0 -1226
- package/types/core/base/eventHandlers/handler_toolbar.d.ts +0 -41
- package/types/core/base/eventHandlers/handler_ww_clipboard.d.ts +0 -40
- package/types/core/base/eventHandlers/handler_ww_dragDrop.d.ts +0 -35
- package/types/core/base/eventHandlers/handler_ww_key_input.d.ts +0 -45
- package/types/core/base/eventHandlers/handler_ww_mouse.d.ts +0 -39
- package/types/core/base/eventManager.d.ts +0 -401
- package/types/core/class/char.d.ts +0 -61
- package/types/core/class/component.d.ts +0 -213
- package/types/core/class/format.d.ts +0 -623
- package/types/core/class/html.d.ts +0 -430
- package/types/core/class/menu.d.ts +0 -126
- package/types/core/class/nodeTransform.d.ts +0 -93
- package/types/core/class/offset.d.ts +0 -522
- package/types/core/class/selection.d.ts +0 -188
- package/types/core/class/shortcuts.d.ts +0 -142
- package/types/core/class/toolbar.d.ts +0 -189
- package/types/core/class/ui.d.ts +0 -164
- package/types/core/class/viewer.d.ts +0 -140
- package/types/core/section/actives.d.ts +0 -46
- package/types/core/section/context.d.ts +0 -45
- package/types/editorInjector/_classes.d.ts +0 -41
- package/types/editorInjector/_core.d.ts +0 -87
- package/types/editorInjector/index.d.ts +0 -69
- package/types/modules/ApiManager.d.ts +0 -125
- package/types/modules/Browser.d.ts +0 -326
- package/types/modules/ColorPicker.d.ts +0 -135
- package/types/modules/Controller.d.ts +0 -251
- package/types/modules/Figure.d.ts +0 -517
- package/types/modules/FileManager.d.ts +0 -202
- package/types/modules/Modal.d.ts +0 -111
- package/types/modules/ModalAnchorEditor.d.ts +0 -236
- package/types/modules/SelectMenu.d.ts +0 -194
- package/types/modules/index.d.ts +0 -26
- package/types/plugins/dropdown/formatBlock.d.ts +0 -55
- package/types/plugins/dropdown/table.d.ts +0 -627
- package/types/plugins/modal/image.d.ts +0 -451
- /package/{LICENSE → LICENSE.txt} +0 -0
|
@@ -1,4034 +0,0 @@
|
|
|
1
|
-
import EditorInjector from '../../editorInjector';
|
|
2
|
-
import { dom, numbers, converter, env, keyCodeMap } from '../../helper';
|
|
3
|
-
import { Controller, SelectMenu, ColorPicker, Figure, _DragHandle } from '../../modules';
|
|
4
|
-
|
|
5
|
-
const { _w, ON_OVER_COMPONENT } = env;
|
|
6
|
-
|
|
7
|
-
const ROW_SELECT_MARGIN = 5;
|
|
8
|
-
const CELL_SELECT_MARGIN = 2;
|
|
9
|
-
const CELL_DECIMAL_END = 0;
|
|
10
|
-
|
|
11
|
-
const RESIZE_CELL_CLASS = '.se-table-resize-line';
|
|
12
|
-
const RESIZE_CELL_PREV_CLASS = '.se-table-resize-line-prev';
|
|
13
|
-
const RESIZE_ROW_CLASS = '.se-table-resize-row';
|
|
14
|
-
const RESIZE_ROW_PREV_CLASS = '.se-table-resize-row-prev';
|
|
15
|
-
|
|
16
|
-
const BORDER_LIST = ['none', 'solid', 'dotted', 'dashed', 'double', 'groove', 'ridge', 'inset', 'outset'];
|
|
17
|
-
const BORDER_FORMATS = {
|
|
18
|
-
all: 'border_all',
|
|
19
|
-
inside: 'border_inside',
|
|
20
|
-
horizon: 'border_horizontal',
|
|
21
|
-
vertical: 'border_vertical',
|
|
22
|
-
outside: 'border_outside',
|
|
23
|
-
left: 'border_left',
|
|
24
|
-
top: 'border_top',
|
|
25
|
-
right: 'border_right',
|
|
26
|
-
bottom: 'border_bottom',
|
|
27
|
-
none: 'border_none'
|
|
28
|
-
};
|
|
29
|
-
const BORDER_FORMAT_INSIDE = ['all', 'inside', 'horizon', 'vertical'];
|
|
30
|
-
const BORDER_NS = {
|
|
31
|
-
l: 'borderLeft',
|
|
32
|
-
t: 'borderTop',
|
|
33
|
-
r: 'borderRight',
|
|
34
|
-
b: 'borderBottom'
|
|
35
|
-
};
|
|
36
|
-
const DEFAULT_BORDER_UNIT = 'px';
|
|
37
|
-
const DEFAULT_COLOR_LIST = [
|
|
38
|
-
// row-1
|
|
39
|
-
'#b0dbb0',
|
|
40
|
-
'#efef7e',
|
|
41
|
-
'#f2acac',
|
|
42
|
-
'#dcb0f6',
|
|
43
|
-
'#99bdff',
|
|
44
|
-
// row-2
|
|
45
|
-
'#5dbd5d',
|
|
46
|
-
'#e7c301',
|
|
47
|
-
'#f64444',
|
|
48
|
-
'#e57ff4',
|
|
49
|
-
'#4387f1',
|
|
50
|
-
// row-3
|
|
51
|
-
'#27836a',
|
|
52
|
-
'#f69915',
|
|
53
|
-
'#ba0808',
|
|
54
|
-
'#a90bed',
|
|
55
|
-
'#134299',
|
|
56
|
-
// row-4
|
|
57
|
-
'#e4e4e4',
|
|
58
|
-
'#B3B3B3',
|
|
59
|
-
'#808080',
|
|
60
|
-
'#4D4D4D',
|
|
61
|
-
'#000000'
|
|
62
|
-
];
|
|
63
|
-
|
|
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
|
-
}
|
|
81
|
-
|
|
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';
|
|
123
|
-
}
|
|
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;
|
|
246
|
-
|
|
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;
|
|
260
|
-
|
|
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
|
-
}
|
|
309
|
-
|
|
310
|
-
/**
|
|
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.
|
|
314
|
-
*/
|
|
315
|
-
action() {
|
|
316
|
-
const oTable = dom.utils.createElement('TABLE');
|
|
317
|
-
const x = this._tableXY[0];
|
|
318
|
-
const y = this._tableXY[1];
|
|
319
|
-
|
|
320
|
-
const body = `<tbody>${`<tr>${CreateCellsString('td', x)}</tr>`.repeat(y)}</tbody>`;
|
|
321
|
-
const colGroup = `<colgroup>${`<col style="width: ${numbers.get(100 / x, CELL_DECIMAL_END)}%;">`.repeat(x)}</colgroup>`;
|
|
322
|
-
oTable.innerHTML = colGroup + body;
|
|
323
|
-
|
|
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 });
|
|
331
|
-
figure.appendChild(oTable);
|
|
332
|
-
|
|
333
|
-
if (this.component.insert(figure, { skipCharCount: false, skipSelection: false, skipHistory: false })) {
|
|
334
|
-
this._resetTablePicker();
|
|
335
|
-
const target = oTable.querySelector('td div');
|
|
336
|
-
this.selection.setRange(target, 0, target, 0);
|
|
337
|
-
}
|
|
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
|
-
}
|
|
409
|
-
|
|
410
|
-
/**
|
|
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.
|
|
420
|
-
*/
|
|
421
|
-
retainFormat() {
|
|
422
|
-
return {
|
|
423
|
-
query: 'table',
|
|
424
|
-
method: (element) => {
|
|
425
|
-
const ColgroupEl = element.querySelector('colgroup');
|
|
426
|
-
let FigureEl = /** @type {HTMLElement} */ (dom.check.isFigure(element.parentNode) ? element.parentNode : null);
|
|
427
|
-
|
|
428
|
-
// create colgroup
|
|
429
|
-
if (!ColgroupEl) {
|
|
430
|
-
const rows = element.rows;
|
|
431
|
-
const firstRow = rows[0];
|
|
432
|
-
const maxCount = GetMaxColumns(element);
|
|
433
|
-
const colHTML = [];
|
|
434
|
-
|
|
435
|
-
for (let i = 0; i < maxCount; i++) {
|
|
436
|
-
let colStyle = '';
|
|
437
|
-
if (firstRow && firstRow.cells[i]) {
|
|
438
|
-
const styleWidth = firstRow.cells[i].style.width;
|
|
439
|
-
if (styleWidth) {
|
|
440
|
-
colStyle = ` style="width: ${styleWidth};"`;
|
|
441
|
-
dom.utils.setStyle(firstRow.cells[i], 'width', '');
|
|
442
|
-
}
|
|
443
|
-
}
|
|
444
|
-
colHTML.push(`<col${colStyle}>`);
|
|
445
|
-
}
|
|
446
|
-
|
|
447
|
-
const colGroup = dom.utils.createElement('colgroup', null, colHTML.join(''));
|
|
448
|
-
element.insertBefore(colGroup, element.firstElementChild);
|
|
449
|
-
}
|
|
450
|
-
|
|
451
|
-
// figure
|
|
452
|
-
if (!FigureEl) {
|
|
453
|
-
FigureEl = dom.utils.createElement('FIGURE', { class: 'se-flex-component se-input-component' });
|
|
454
|
-
element.parentNode.insertBefore(FigureEl, element);
|
|
455
|
-
FigureEl.appendChild(element);
|
|
456
|
-
} else {
|
|
457
|
-
dom.utils.addClass(FigureEl, 'se-flex-component|se-input-component');
|
|
458
|
-
}
|
|
459
|
-
|
|
460
|
-
// table width
|
|
461
|
-
if (element.style.width) {
|
|
462
|
-
FigureEl.style.width = element.style.width;
|
|
463
|
-
dom.utils.setStyle(element, 'width', '');
|
|
464
|
-
}
|
|
465
|
-
|
|
466
|
-
// scroll
|
|
467
|
-
if (!this.figureScroll) {
|
|
468
|
-
dom.utils.removeClass(FigureEl, this.figureScrollList.join('|'));
|
|
469
|
-
} else {
|
|
470
|
-
const scrollTypeClass = `se-scroll-figure-${this.figureScroll}`;
|
|
471
|
-
dom.utils.addClass(FigureEl, scrollTypeClass);
|
|
472
|
-
dom.utils.removeClass(FigureEl, this.figureScrollList.filter((v) => v !== scrollTypeClass).join('|'));
|
|
473
|
-
}
|
|
474
|
-
}
|
|
475
|
-
};
|
|
476
|
-
}
|
|
477
|
-
|
|
478
|
-
/**
|
|
479
|
-
* @editorMethod Editor.core
|
|
480
|
-
* @description Executes the method called when the rtl, ltr mode changes. ("editor.setDir")
|
|
481
|
-
* @param {string} dir Direction ("rtl" or "ltr")
|
|
482
|
-
*/
|
|
483
|
-
setDir(dir) {
|
|
484
|
-
this.tableHighlight.style.left = dir === 'rtl' ? 10 * 18 - 13 + 'px' : '';
|
|
485
|
-
this._resetTablePicker();
|
|
486
|
-
this._resetPropsAlign();
|
|
487
|
-
}
|
|
488
|
-
|
|
489
|
-
/**
|
|
490
|
-
* @editorMethod Editor.EventManager
|
|
491
|
-
* @description Executes the event function of "mousemove".
|
|
492
|
-
* @param {__se__PluginMouseEventInfo} params
|
|
493
|
-
*/
|
|
494
|
-
onMouseMove({ event }) {
|
|
495
|
-
if (this._resizing) return;
|
|
496
|
-
|
|
497
|
-
const eventTarget = dom.query.getEventTarget(event);
|
|
498
|
-
const target = dom.query.getParentElement(eventTarget, IsResizeEls);
|
|
499
|
-
if (!target) {
|
|
500
|
-
this.__hideResizeLine();
|
|
501
|
-
return;
|
|
502
|
-
}
|
|
503
|
-
|
|
504
|
-
const cellEdge = CheckCellEdge(event, target);
|
|
505
|
-
if (cellEdge.is) {
|
|
506
|
-
if (this._element) this._element.style.cursor = '';
|
|
507
|
-
this.__removeGlobalEvents();
|
|
508
|
-
if (this._resizeLine?.style.display === 'block') this._resizeLine.style.display = 'none';
|
|
509
|
-
this._resizeLine = this.editor.frameContext.get('wrapper').querySelector(RESIZE_CELL_CLASS);
|
|
510
|
-
this._setResizeLinePosition(dom.query.getParentElement(target, dom.check.isTable), target, this._resizeLine, cellEdge.isLeft);
|
|
511
|
-
this._resizeLine.style.display = 'block';
|
|
512
|
-
return;
|
|
513
|
-
}
|
|
514
|
-
|
|
515
|
-
const rowEdge = CheckRowEdge(event, target);
|
|
516
|
-
if (rowEdge.is) {
|
|
517
|
-
this.__removeGlobalEvents();
|
|
518
|
-
this._element = dom.query.getParentElement(target, dom.check.isTable);
|
|
519
|
-
this._element.style.cursor = 'ns-resize';
|
|
520
|
-
if (this._resizeLine?.style.display === 'block') this._resizeLine.style.display = 'none';
|
|
521
|
-
this._resizeLine = this.editor.frameContext.get('wrapper').querySelector(RESIZE_ROW_CLASS);
|
|
522
|
-
this._setResizeRowPosition(dom.query.getParentElement(target, dom.check.isTable), target, this._resizeLine);
|
|
523
|
-
this._resizeLine.style.display = 'block';
|
|
524
|
-
return;
|
|
525
|
-
}
|
|
526
|
-
|
|
527
|
-
if (this._element) this._element.style.cursor = '';
|
|
528
|
-
this.__hideResizeLine();
|
|
529
|
-
}
|
|
530
|
-
|
|
531
|
-
/**
|
|
532
|
-
* @editorMethod Editor.EventManager
|
|
533
|
-
* @description Executes the event function of "scroll".
|
|
534
|
-
*/
|
|
535
|
-
onScroll() {
|
|
536
|
-
if (this._resizeLine?.style.display !== 'block') return;
|
|
537
|
-
// delete resize line position
|
|
538
|
-
if (this._element) this._element.style.cursor = '';
|
|
539
|
-
this._resizeLine.style.display = 'none';
|
|
540
|
-
}
|
|
541
|
-
|
|
542
|
-
/**
|
|
543
|
-
* @editorMethod Editor.EventManager
|
|
544
|
-
* @description Executes the event function of "mousedown".
|
|
545
|
-
* @param {__se__PluginMouseEventInfo} params
|
|
546
|
-
*/
|
|
547
|
-
onMouseDown({ event }) {
|
|
548
|
-
this._ref = this._selectedCell = null;
|
|
549
|
-
const eventTarget = dom.query.getEventTarget(event);
|
|
550
|
-
const target = /** @type {HTMLTableCellElement} */ (dom.query.getParentElement(eventTarget, IsResizeEls));
|
|
551
|
-
if (!target) return;
|
|
552
|
-
|
|
553
|
-
if (!this.cellControllerTop) {
|
|
554
|
-
this.controller_cell.hide();
|
|
555
|
-
}
|
|
556
|
-
|
|
557
|
-
const cellEdge = CheckCellEdge(event, target);
|
|
558
|
-
if (cellEdge.is) {
|
|
559
|
-
try {
|
|
560
|
-
this._deleteStyleSelectedCells();
|
|
561
|
-
this.setCellInfo(target, true);
|
|
562
|
-
const colIndex = this._logical_cellIndex - (cellEdge.isLeft ? 1 : 0);
|
|
563
|
-
|
|
564
|
-
// ready
|
|
565
|
-
this.ui.enableBackWrapper('ew-resize');
|
|
566
|
-
if (!this._resizeLine) this._resizeLine = this.editor.frameContext.get('wrapper').querySelector(RESIZE_CELL_CLASS);
|
|
567
|
-
this._resizeLinePrev = this.editor.frameContext.get('wrapper').querySelector(RESIZE_CELL_PREV_CLASS);
|
|
568
|
-
|
|
569
|
-
// select figure
|
|
570
|
-
if (colIndex < 0 || colIndex === this._logical_cellCnt - 1) {
|
|
571
|
-
this._startFigureResizing(cellEdge.startX, colIndex < 0);
|
|
572
|
-
return;
|
|
573
|
-
}
|
|
574
|
-
|
|
575
|
-
const col = this._element.querySelector('colgroup').querySelectorAll('col')[colIndex < 0 ? 0 : colIndex];
|
|
576
|
-
this._startCellResizing(col, cellEdge.startX, numbers.get(_w.getComputedStyle(col).width, CELL_DECIMAL_END), cellEdge.isLeft);
|
|
577
|
-
this._toggleEditor(false);
|
|
578
|
-
} catch (err) {
|
|
579
|
-
console.warn('[SUNEDITOR.plugins.table.error]', err);
|
|
580
|
-
this.__removeGlobalEvents();
|
|
581
|
-
} finally {
|
|
582
|
-
this._fixedCell = this._selectedCell = null;
|
|
583
|
-
}
|
|
584
|
-
|
|
585
|
-
return;
|
|
586
|
-
}
|
|
587
|
-
|
|
588
|
-
const rowEdge = CheckRowEdge(event, target);
|
|
589
|
-
if (rowEdge.is) {
|
|
590
|
-
try {
|
|
591
|
-
/** @type {HTMLTableRowElement} */
|
|
592
|
-
let row = dom.query.getParentElement(target, dom.check.isTableRow);
|
|
593
|
-
let rowSpan = target.rowSpan;
|
|
594
|
-
if (rowSpan > 1) {
|
|
595
|
-
while (dom.check.isTableRow(row) && rowSpan > 1) {
|
|
596
|
-
row = /** @type {HTMLTableRowElement} */ (row.nextElementSibling);
|
|
597
|
-
--rowSpan;
|
|
598
|
-
}
|
|
599
|
-
}
|
|
600
|
-
|
|
601
|
-
this._deleteStyleSelectedCells();
|
|
602
|
-
this.setRowInfo(row);
|
|
603
|
-
|
|
604
|
-
// ready
|
|
605
|
-
this.ui.enableBackWrapper('ns-resize');
|
|
606
|
-
if (!this._resizeLine) this._resizeLine = this.editor.frameContext.get('wrapper').querySelector(RESIZE_ROW_CLASS);
|
|
607
|
-
this._resizeLinePrev = this.editor.frameContext.get('wrapper').querySelector(RESIZE_ROW_PREV_CLASS);
|
|
608
|
-
|
|
609
|
-
this._startRowResizing(row, rowEdge.startY, numbers.get(_w.getComputedStyle(row).height, CELL_DECIMAL_END));
|
|
610
|
-
this._toggleEditor(false);
|
|
611
|
-
} catch (err) {
|
|
612
|
-
console.warn('[SUNEDITOR.plugins.table.error]', err);
|
|
613
|
-
this.__removeGlobalEvents();
|
|
614
|
-
} finally {
|
|
615
|
-
this._fixedCell = this._selectedCell = null;
|
|
616
|
-
}
|
|
617
|
-
|
|
618
|
-
return;
|
|
619
|
-
}
|
|
620
|
-
|
|
621
|
-
if (this._shift && target !== this._fixedCell) return;
|
|
622
|
-
|
|
623
|
-
this._deleteStyleSelectedCells();
|
|
624
|
-
if (/^TR$/i.test(target.nodeName)) return;
|
|
625
|
-
|
|
626
|
-
this.#StyleSelectCells(target, false);
|
|
627
|
-
}
|
|
628
|
-
|
|
629
|
-
/**
|
|
630
|
-
* @editorMethod Editor.EventManager
|
|
631
|
-
* @description Executes the event function of "mouseup".
|
|
632
|
-
*/
|
|
633
|
-
onMouseUp() {
|
|
634
|
-
this._shift = false;
|
|
635
|
-
if (!this.cellControllerTop) {
|
|
636
|
-
this.controller_cell.resetPosition(this._fixedCell);
|
|
637
|
-
}
|
|
638
|
-
}
|
|
639
|
-
|
|
640
|
-
/**
|
|
641
|
-
* @editorMethod Editor.EventManager
|
|
642
|
-
* @description Executes the event function of "mouseleave".
|
|
643
|
-
*/
|
|
644
|
-
onMouseLeave() {
|
|
645
|
-
this.__hideResizeLine();
|
|
646
|
-
}
|
|
647
|
-
|
|
648
|
-
/**
|
|
649
|
-
* @editorMethod Editor.EventManager
|
|
650
|
-
* @description Executes the event function of "keydown".
|
|
651
|
-
* @param {__se__PluginKeyEventInfo} params
|
|
652
|
-
*/
|
|
653
|
-
onKeyDown({ event, range, line }) {
|
|
654
|
-
this._ref = null;
|
|
655
|
-
|
|
656
|
-
const keyCode = event.code;
|
|
657
|
-
const isTab = keyCodeMap.isTab(keyCode);
|
|
658
|
-
if (this.editor.selectMenuOn || this._resizing || (!isTab && this.__s) || keyCodeMap.isCtrl(event)) return;
|
|
659
|
-
|
|
660
|
-
if (!this.cellControllerTop) {
|
|
661
|
-
this.controller_cell.hide();
|
|
662
|
-
}
|
|
663
|
-
|
|
664
|
-
this.__s = keyCodeMap.isShift(event);
|
|
665
|
-
|
|
666
|
-
// table tabkey
|
|
667
|
-
if (isTab) {
|
|
668
|
-
this._deleteStyleSelectedCells();
|
|
669
|
-
const tableCell = dom.query.getParentElement(line, dom.check.isTableCell);
|
|
670
|
-
if (tableCell && range.collapsed && dom.check.isEdgePoint(range.startContainer, range.startOffset)) {
|
|
671
|
-
this._closeController();
|
|
672
|
-
|
|
673
|
-
const shift = this.__s;
|
|
674
|
-
this._shift = this.__s = false;
|
|
675
|
-
|
|
676
|
-
/** @type {HTMLTableElement} */
|
|
677
|
-
const table = dom.query.getParentElement(tableCell, 'table');
|
|
678
|
-
/** @type {HTMLTableCellElement[]} */
|
|
679
|
-
const cells = dom.query.getListChildren(table, dom.check.isTableCell);
|
|
680
|
-
const idx = shift ? dom.utils.prevIndex(cells, tableCell) : dom.utils.nextIndex(cells, tableCell);
|
|
681
|
-
|
|
682
|
-
if (idx === cells.length && !shift) {
|
|
683
|
-
if (!dom.query.getParentElement(tableCell, 'thead')) {
|
|
684
|
-
const rows = table.rows;
|
|
685
|
-
const newRow = this.insertBodyRow(table, rows.length, this._cellCnt);
|
|
686
|
-
const firstTd = newRow.querySelector('td div');
|
|
687
|
-
this.selection.setRange(firstTd, 0, firstTd, 0);
|
|
688
|
-
}
|
|
689
|
-
|
|
690
|
-
event.preventDefault();
|
|
691
|
-
event.stopPropagation();
|
|
692
|
-
|
|
693
|
-
return false;
|
|
694
|
-
}
|
|
695
|
-
|
|
696
|
-
if (idx === -1 && shift) return false;
|
|
697
|
-
|
|
698
|
-
const moveCell = cells[idx];
|
|
699
|
-
if (!moveCell) return;
|
|
700
|
-
|
|
701
|
-
const rangeCell = moveCell.firstElementChild || moveCell;
|
|
702
|
-
this.selection.setRange(rangeCell, 0, rangeCell, 0);
|
|
703
|
-
|
|
704
|
-
event.preventDefault();
|
|
705
|
-
event.stopPropagation();
|
|
706
|
-
|
|
707
|
-
return false;
|
|
708
|
-
}
|
|
709
|
-
}
|
|
710
|
-
|
|
711
|
-
let cell = null;
|
|
712
|
-
if (!keyCodeMap.isShift(event)) {
|
|
713
|
-
cell = dom.query.getParentElement(line, dom.check.isTableCell);
|
|
714
|
-
if (!dom.utils.hasClass(cell, 'se-selected-cell-focus')) return;
|
|
715
|
-
|
|
716
|
-
this._deleteStyleSelectedCells();
|
|
717
|
-
this._toggleEditor(true);
|
|
718
|
-
this.__removeGlobalEvents();
|
|
719
|
-
this._closeController();
|
|
720
|
-
|
|
721
|
-
return;
|
|
722
|
-
}
|
|
723
|
-
|
|
724
|
-
if (this._shift || this._ref) return;
|
|
725
|
-
|
|
726
|
-
cell = /** @type {HTMLTableCellElement} */ (cell || dom.query.getParentElement(line, dom.check.isTableCell));
|
|
727
|
-
if (cell) {
|
|
728
|
-
this.__s = false;
|
|
729
|
-
this._fixedCell = cell;
|
|
730
|
-
this._closeController();
|
|
731
|
-
this.#StyleSelectCells(cell, event.shiftKey);
|
|
732
|
-
return false;
|
|
733
|
-
}
|
|
734
|
-
}
|
|
735
|
-
|
|
736
|
-
/**
|
|
737
|
-
* @editorMethod Editor.EventManager
|
|
738
|
-
* @description Executes the event function of "keyup".
|
|
739
|
-
* @param {__se__PluginKeyEventInfo} params
|
|
740
|
-
*/
|
|
741
|
-
onKeyUp({ line }) {
|
|
742
|
-
this.__s = false;
|
|
743
|
-
if (this._shift && dom.query.getParentElement(line, dom.check.isTableCell) === this._fixedCell) {
|
|
744
|
-
this._deleteStyleSelectedCells();
|
|
745
|
-
this._toggleEditor(true);
|
|
746
|
-
this.__removeGlobalEvents();
|
|
747
|
-
}
|
|
748
|
-
this._shift = false;
|
|
749
|
-
}
|
|
750
|
-
|
|
751
|
-
/**
|
|
752
|
-
* @editorMethod Modules.ColorPicker
|
|
753
|
-
* @description Executes the method called when a button of "ColorPicker" module is clicked.
|
|
754
|
-
* @param {string} color - Color code (hex)
|
|
755
|
-
*/
|
|
756
|
-
colorPickerAction(color) {
|
|
757
|
-
const target = this.propTargets[`${this.sliderType}_color`];
|
|
758
|
-
target.style.borderColor = target.value = color;
|
|
759
|
-
this.controller_colorPicker.close();
|
|
760
|
-
}
|
|
761
|
-
|
|
762
|
-
/**
|
|
763
|
-
* @editorMethod Modules.Controller
|
|
764
|
-
* @description Executes the method that is called when a button is clicked in the "controller".
|
|
765
|
-
* @param {HTMLButtonElement} target Target button element
|
|
766
|
-
*/
|
|
767
|
-
controllerAction(target) {
|
|
768
|
-
const command = target.getAttribute('data-command');
|
|
769
|
-
if (!command) return;
|
|
770
|
-
|
|
771
|
-
const { back_color, font_color, border_color } = this.propTargets;
|
|
772
|
-
const value = target.getAttribute('data-value');
|
|
773
|
-
|
|
774
|
-
switch (command) {
|
|
775
|
-
case 'header':
|
|
776
|
-
this.toggleHeader();
|
|
777
|
-
this._historyPush();
|
|
778
|
-
break;
|
|
779
|
-
case 'caption':
|
|
780
|
-
this.toggleCaption();
|
|
781
|
-
this._historyPush();
|
|
782
|
-
break;
|
|
783
|
-
case 'onsplit':
|
|
784
|
-
this.selectMenu_split.open();
|
|
785
|
-
break;
|
|
786
|
-
case 'oncolumn':
|
|
787
|
-
this.selectMenu_column.open();
|
|
788
|
-
break;
|
|
789
|
-
case 'onrow':
|
|
790
|
-
this.selectMenu_row.menus[0].style.display = this.selectMenu_row.menus[1].style.display = /^TH$/i.test(this._tdElement?.nodeName) ? 'none' : '';
|
|
791
|
-
this.selectMenu_row.open();
|
|
792
|
-
break;
|
|
793
|
-
case 'openTableProperties':
|
|
794
|
-
if (this.controller_props.currentTarget === target && this.controller_props.form?.style.display === 'block') {
|
|
795
|
-
this.controller_props.close();
|
|
796
|
-
} else {
|
|
797
|
-
this.controller_props_title.textContent = this.lang.tableProperties;
|
|
798
|
-
this._setCtrlProps('table');
|
|
799
|
-
this.controller_props.open(target, this.controller_table.form, { isWWTarget: false, initMethod: null, addOffset: null });
|
|
800
|
-
}
|
|
801
|
-
break;
|
|
802
|
-
case 'openCellProperties':
|
|
803
|
-
if (this.controller_props.currentTarget === target && this.controller_props.form?.style.display === 'block') {
|
|
804
|
-
this.controller_props.close();
|
|
805
|
-
} else {
|
|
806
|
-
this.controller_props_title.textContent = this.lang.cellProperties;
|
|
807
|
-
this._setCtrlProps('cell');
|
|
808
|
-
this.controller_props.open(target, this.controller_cell.form, { isWWTarget: false, initMethod: null, addOffset: null });
|
|
809
|
-
}
|
|
810
|
-
break;
|
|
811
|
-
case 'props_onborder_format':
|
|
812
|
-
if (this._propsCache.length === 1) {
|
|
813
|
-
this.selectMenu_props_border_format_oneCell.open();
|
|
814
|
-
} else {
|
|
815
|
-
this.selectMenu_props_border_format.open();
|
|
816
|
-
}
|
|
817
|
-
break;
|
|
818
|
-
case 'props_onborder_style':
|
|
819
|
-
this.selectMenu_props_border.open();
|
|
820
|
-
break;
|
|
821
|
-
case 'props_onpalette':
|
|
822
|
-
this._onColorPalette(target, value, value === 'border' ? border_color : value === 'back' ? back_color : font_color);
|
|
823
|
-
break;
|
|
824
|
-
case 'props_font_style':
|
|
825
|
-
dom.utils.toggleClass(this.propTargets[`font_${value}`], 'on');
|
|
826
|
-
break;
|
|
827
|
-
case 'props_submit':
|
|
828
|
-
this._submitProps(target);
|
|
829
|
-
break;
|
|
830
|
-
case 'revert': {
|
|
831
|
-
const propsCache = this._propsCache;
|
|
832
|
-
for (let i = 0, len = propsCache.length; i < len; i++) {
|
|
833
|
-
propsCache[i][0].style.cssText = propsCache[i][1];
|
|
834
|
-
}
|
|
835
|
-
// alignment
|
|
836
|
-
this._setAlignProps(this.propTargets.cell_alignment, this._propsAlignCache, true);
|
|
837
|
-
this._setAlignProps(this.propTargets.cell_alignment_vertical, this._propsVerticalAlignCache, true);
|
|
838
|
-
if (dom.check.isTable(propsCache[0][0]) && this._figure) {
|
|
839
|
-
this._figure.style.float = this._propsAlignCache;
|
|
840
|
-
}
|
|
841
|
-
break;
|
|
842
|
-
}
|
|
843
|
-
case 'close_props':
|
|
844
|
-
this.controller_props.close();
|
|
845
|
-
break;
|
|
846
|
-
case 'props_align':
|
|
847
|
-
this._setAlignProps(this.propTargets.cell_alignment, target.getAttribute('data-value'), false);
|
|
848
|
-
break;
|
|
849
|
-
case 'props_align_vertical':
|
|
850
|
-
this._setAlignProps(this.propTargets.cell_alignment_vertical, target.getAttribute('data-value'), false);
|
|
851
|
-
break;
|
|
852
|
-
case 'merge':
|
|
853
|
-
this.mergeCells(this._selectedCells);
|
|
854
|
-
break;
|
|
855
|
-
case 'unmerge':
|
|
856
|
-
this.unmergeCells(this._selectedCells);
|
|
857
|
-
break;
|
|
858
|
-
case 'resize':
|
|
859
|
-
this._maxWidth = !this._maxWidth;
|
|
860
|
-
this._setTableStyle('width', false);
|
|
861
|
-
this._historyPush();
|
|
862
|
-
this.component.select(this._element, Table.key, { isInput: true });
|
|
863
|
-
break;
|
|
864
|
-
case 'layout':
|
|
865
|
-
this._fixedColumn = !this._fixedColumn;
|
|
866
|
-
this._setTableStyle('column', false);
|
|
867
|
-
this._historyPush();
|
|
868
|
-
this.component.select(this._element, Table.key, { isInput: true });
|
|
869
|
-
break;
|
|
870
|
-
case 'copy':
|
|
871
|
-
this.component.copy(this._figure);
|
|
872
|
-
break;
|
|
873
|
-
case 'remove': {
|
|
874
|
-
const emptyDiv = this._figure?.parentNode;
|
|
875
|
-
dom.utils.removeItem(this._figure);
|
|
876
|
-
|
|
877
|
-
this._closeTableSelectInfo();
|
|
878
|
-
|
|
879
|
-
if (emptyDiv !== this.editor.frameContext.get('wysiwyg'))
|
|
880
|
-
this.nodeTransform.removeAllParents(
|
|
881
|
-
emptyDiv,
|
|
882
|
-
function (current) {
|
|
883
|
-
return current.childNodes.length === 0;
|
|
884
|
-
},
|
|
885
|
-
null
|
|
886
|
-
);
|
|
887
|
-
this.editor.focus();
|
|
888
|
-
this.history.push(false);
|
|
889
|
-
}
|
|
890
|
-
}
|
|
891
|
-
|
|
892
|
-
if (!/(^props_|^revert|Properties$)/.test(command)) {
|
|
893
|
-
this.controller_props.close();
|
|
894
|
-
this.controller_colorPicker.close();
|
|
895
|
-
}
|
|
896
|
-
|
|
897
|
-
if (!/^(remove|props_|on|open|merge)/.test(command)) {
|
|
898
|
-
this._setCellControllerPosition(this._tdElement, this._shift);
|
|
899
|
-
}
|
|
900
|
-
}
|
|
901
|
-
|
|
902
|
-
/**
|
|
903
|
-
* @editorMethod Modules.Controller
|
|
904
|
-
* @description Executes the method called when the "controller" is closed.
|
|
905
|
-
*/
|
|
906
|
-
close() {
|
|
907
|
-
this.__removeGlobalEvents();
|
|
908
|
-
this._deleteStyleSelectedCells();
|
|
909
|
-
this._toggleEditor(true);
|
|
910
|
-
|
|
911
|
-
this._figure = null;
|
|
912
|
-
this._element = null;
|
|
913
|
-
this._trElement = null;
|
|
914
|
-
this._trElements = null;
|
|
915
|
-
this._tableXY = [];
|
|
916
|
-
this._maxWidth = false;
|
|
917
|
-
this._fixedColumn = false;
|
|
918
|
-
this._physical_cellCnt = 0;
|
|
919
|
-
this._logical_cellCnt = 0;
|
|
920
|
-
this._rowCnt = 0;
|
|
921
|
-
this._rowIndex = 0;
|
|
922
|
-
this._physical_cellIndex = 0;
|
|
923
|
-
this._logical_cellIndex = 0;
|
|
924
|
-
this._current_colSpan = 0;
|
|
925
|
-
this._current_rowSpan = 0;
|
|
926
|
-
|
|
927
|
-
this._shift = false;
|
|
928
|
-
this._selectedCells = null;
|
|
929
|
-
this._selectedTable = null;
|
|
930
|
-
this._ref = null;
|
|
931
|
-
|
|
932
|
-
this._fixedCell = null;
|
|
933
|
-
this._selectedCell = null;
|
|
934
|
-
this._fixedCellName = null;
|
|
935
|
-
|
|
936
|
-
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;
|
|
937
|
-
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');
|
|
938
|
-
}
|
|
939
|
-
|
|
940
|
-
/**
|
|
941
|
-
* @description Selects a group of table cells and sets internal state related to multi-cell selection.
|
|
942
|
-
* @param {HTMLTableCellElement[]} cells - An array of table cell elements to be selected.
|
|
943
|
-
*/
|
|
944
|
-
selectCells(cells) {
|
|
945
|
-
const firstCell = cells[0];
|
|
946
|
-
const lastCell = dom.query.findVisualLastCell(cells);
|
|
947
|
-
|
|
948
|
-
this._selectedCells = cells;
|
|
949
|
-
this._fixedCell = firstCell;
|
|
950
|
-
this._selectedCell = lastCell;
|
|
951
|
-
this._fixedCellName = firstCell.nodeName;
|
|
952
|
-
this._selectedTable = dom.query.getParentElement(firstCell, 'TABLE');
|
|
953
|
-
|
|
954
|
-
this._setMultiCells(firstCell, lastCell);
|
|
955
|
-
}
|
|
956
|
-
|
|
957
|
-
/**
|
|
958
|
-
* @description Sets the table and figure elements based on the provided cell element, and stores references to them for later use.
|
|
959
|
-
* @param {Node} element The target table cell (`<td>`) element from which the table info will be extracted.
|
|
960
|
-
* @returns {HTMLTableElement} The `<table>` element that is the parent of the provided `element`.
|
|
961
|
-
*/
|
|
962
|
-
setTableInfo(element) {
|
|
963
|
-
const table = (this._element = this._selectedTable = dom.query.getParentElement(element, 'TABLE'));
|
|
964
|
-
this._figure = dom.query.getParentElement(table, dom.check.isFigure) || table;
|
|
965
|
-
return /** @type {HTMLTableElement} */ (table);
|
|
966
|
-
}
|
|
967
|
-
|
|
968
|
-
/**
|
|
969
|
-
* @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.
|
|
970
|
-
* @param {HTMLTableCellElement} tdElement The target table cell (`<td>`) element from which table information will be extracted.
|
|
971
|
-
* @param {boolean} reset A flag indicating whether to reset the cell information. If `true`, the cell information will be reset and recalculated.
|
|
972
|
-
*/
|
|
973
|
-
setCellInfo(tdElement, reset) {
|
|
974
|
-
const table = this.setTableInfo(tdElement);
|
|
975
|
-
if (!table) return;
|
|
976
|
-
this._fixedCell = tdElement;
|
|
977
|
-
this._trElement = /** @type {HTMLTableRowElement} */ (tdElement.parentNode);
|
|
978
|
-
|
|
979
|
-
// hedaer
|
|
980
|
-
if (table.querySelector('thead')) dom.utils.addClass(this.headerButton, 'active');
|
|
981
|
-
else dom.utils.removeClass(this.headerButton, 'active');
|
|
982
|
-
|
|
983
|
-
// caption
|
|
984
|
-
if (table.querySelector('caption')) dom.utils.addClass(this.captionButton, 'active');
|
|
985
|
-
else dom.utils.removeClass(this.captionButton, 'active');
|
|
986
|
-
|
|
987
|
-
if (reset || this._physical_cellCnt === 0) {
|
|
988
|
-
if (this._tdElement !== tdElement) {
|
|
989
|
-
this._tdElement = tdElement;
|
|
990
|
-
this._trElement = /** @type {HTMLTableRowElement} */ (tdElement.parentNode);
|
|
991
|
-
}
|
|
992
|
-
|
|
993
|
-
if (!this._selectedCells?.length) this._selectedCells = [tdElement];
|
|
994
|
-
|
|
995
|
-
const rows = (this._trElements = table.rows);
|
|
996
|
-
const cellIndex = tdElement.cellIndex;
|
|
997
|
-
|
|
998
|
-
let cellCnt = 0;
|
|
999
|
-
for (let i = 0, cells = rows[0].cells, len = rows[0].cells.length; i < len; i++) {
|
|
1000
|
-
cellCnt += cells[i].colSpan;
|
|
1001
|
-
}
|
|
1002
|
-
|
|
1003
|
-
// row cnt, row index
|
|
1004
|
-
const rowIndex = (this._rowIndex = this._trElement.rowIndex);
|
|
1005
|
-
this._rowCnt = rows.length;
|
|
1006
|
-
|
|
1007
|
-
// cell cnt, physical cell index
|
|
1008
|
-
this._physical_cellCnt = this._trElement.cells.length;
|
|
1009
|
-
this._logical_cellCnt = this._cellCnt = cellCnt;
|
|
1010
|
-
this._physical_cellIndex = cellIndex;
|
|
1011
|
-
|
|
1012
|
-
// span
|
|
1013
|
-
this._current_colSpan = this._tdElement.colSpan - 1;
|
|
1014
|
-
this._current_rowSpan = this._trElement.cells[cellIndex].rowSpan - 1;
|
|
1015
|
-
|
|
1016
|
-
// find logcal cell index
|
|
1017
|
-
let rowSpanArr = [];
|
|
1018
|
-
let spanIndex = [];
|
|
1019
|
-
for (let i = 0, cells, colSpan; i <= rowIndex; i++) {
|
|
1020
|
-
cells = rows[i].cells;
|
|
1021
|
-
colSpan = 0;
|
|
1022
|
-
for (let c = 0, cLen = cells.length, cell, cs, rs, logcalIndex; c < cLen; c++) {
|
|
1023
|
-
cell = cells[c];
|
|
1024
|
-
cs = cell.colSpan - 1;
|
|
1025
|
-
rs = cell.rowSpan - 1;
|
|
1026
|
-
logcalIndex = c + colSpan;
|
|
1027
|
-
|
|
1028
|
-
if (spanIndex.length > 0) {
|
|
1029
|
-
for (let r = 0, arr; r < spanIndex.length; r++) {
|
|
1030
|
-
arr = spanIndex[r];
|
|
1031
|
-
if (arr.row > i) continue;
|
|
1032
|
-
if (logcalIndex >= arr.index) {
|
|
1033
|
-
colSpan += arr.cs;
|
|
1034
|
-
logcalIndex += arr.cs;
|
|
1035
|
-
arr.rs -= 1;
|
|
1036
|
-
arr.row = i + 1;
|
|
1037
|
-
if (arr.rs < 1) {
|
|
1038
|
-
spanIndex.splice(r, 1);
|
|
1039
|
-
r--;
|
|
1040
|
-
}
|
|
1041
|
-
} else if (c === cLen - 1) {
|
|
1042
|
-
arr.rs -= 1;
|
|
1043
|
-
arr.row = i + 1;
|
|
1044
|
-
if (arr.rs < 1) {
|
|
1045
|
-
spanIndex.splice(r, 1);
|
|
1046
|
-
r--;
|
|
1047
|
-
}
|
|
1048
|
-
}
|
|
1049
|
-
}
|
|
1050
|
-
}
|
|
1051
|
-
|
|
1052
|
-
// logcal cell index
|
|
1053
|
-
if (i === rowIndex && c === cellIndex) {
|
|
1054
|
-
this._logical_cellIndex = logcalIndex;
|
|
1055
|
-
break;
|
|
1056
|
-
}
|
|
1057
|
-
|
|
1058
|
-
if (rs > 0) {
|
|
1059
|
-
rowSpanArr.push({
|
|
1060
|
-
index: logcalIndex,
|
|
1061
|
-
cs: cs + 1,
|
|
1062
|
-
rs: rs,
|
|
1063
|
-
row: -1
|
|
1064
|
-
});
|
|
1065
|
-
}
|
|
1066
|
-
|
|
1067
|
-
colSpan += cs;
|
|
1068
|
-
}
|
|
1069
|
-
|
|
1070
|
-
spanIndex = spanIndex.concat(rowSpanArr).sort(function (a, b) {
|
|
1071
|
-
return a.index - b.index;
|
|
1072
|
-
});
|
|
1073
|
-
rowSpanArr = [];
|
|
1074
|
-
}
|
|
1075
|
-
|
|
1076
|
-
rowSpanArr = null;
|
|
1077
|
-
spanIndex = null;
|
|
1078
|
-
}
|
|
1079
|
-
}
|
|
1080
|
-
|
|
1081
|
-
/**
|
|
1082
|
-
* @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.
|
|
1083
|
-
* @param {HTMLTableRowElement} trElement The target table row (`<tr>`) element from which row information will be extracted.
|
|
1084
|
-
*/
|
|
1085
|
-
setRowInfo(trElement) {
|
|
1086
|
-
const table = this.setTableInfo(trElement);
|
|
1087
|
-
const rows = (this._trElements = table.rows);
|
|
1088
|
-
this._rowCnt = rows.length;
|
|
1089
|
-
this._rowIndex = trElement.rowIndex;
|
|
1090
|
-
}
|
|
1091
|
-
|
|
1092
|
-
/**
|
|
1093
|
-
* @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.
|
|
1094
|
-
* @param {"row"|"cell"} type The type of element to edit ('row' or 'cell').
|
|
1095
|
-
* @param {?"up"|"down"|"left"|"right"} option The action to perform: 'up', 'down', 'left', 'right', or `null` for removing.
|
|
1096
|
-
*/
|
|
1097
|
-
editTable(type, option) {
|
|
1098
|
-
const table = this._element;
|
|
1099
|
-
const isRow = type === 'row';
|
|
1100
|
-
|
|
1101
|
-
if (isRow) {
|
|
1102
|
-
const tableAttr = this._trElement.parentElement;
|
|
1103
|
-
if (/^THEAD$/i.test(tableAttr.nodeName)) {
|
|
1104
|
-
if (option === 'up') {
|
|
1105
|
-
return;
|
|
1106
|
-
} else if (!tableAttr.nextElementSibling || !/^TBODY$/i.test(tableAttr.nextElementSibling.nodeName)) {
|
|
1107
|
-
if (!option) {
|
|
1108
|
-
dom.utils.removeItem(this._figure);
|
|
1109
|
-
this._closeTableSelectInfo();
|
|
1110
|
-
} else {
|
|
1111
|
-
table.innerHTML += '<tbody><tr>' + CreateCellsString('td', this._logical_cellCnt) + '</tr></tbody>';
|
|
1112
|
-
}
|
|
1113
|
-
return;
|
|
1114
|
-
}
|
|
1115
|
-
}
|
|
1116
|
-
}
|
|
1117
|
-
|
|
1118
|
-
// multi
|
|
1119
|
-
if (this._ref) {
|
|
1120
|
-
const positionCell = this._tdElement;
|
|
1121
|
-
const selectedCells = this._selectedCells;
|
|
1122
|
-
// multi - row
|
|
1123
|
-
if (isRow) {
|
|
1124
|
-
// remove row
|
|
1125
|
-
if (!option) {
|
|
1126
|
-
let row = selectedCells[0].parentNode;
|
|
1127
|
-
const removeCells = [selectedCells[0]];
|
|
1128
|
-
|
|
1129
|
-
for (let i = 1, len = selectedCells.length, cell; i < len; i++) {
|
|
1130
|
-
cell = selectedCells[i];
|
|
1131
|
-
if (row !== cell.parentNode) {
|
|
1132
|
-
removeCells.push(cell);
|
|
1133
|
-
row = cell.parentNode;
|
|
1134
|
-
}
|
|
1135
|
-
}
|
|
1136
|
-
|
|
1137
|
-
for (let i = 0, len = removeCells.length; i < len; i++) {
|
|
1138
|
-
this.setCellInfo(removeCells[i], true);
|
|
1139
|
-
this.editRow(option);
|
|
1140
|
-
}
|
|
1141
|
-
} else {
|
|
1142
|
-
// edit row
|
|
1143
|
-
this.setCellInfo(option === 'up' ? selectedCells[0] : selectedCells[selectedCells.length - 1], true);
|
|
1144
|
-
this.editRow(option, null, positionCell);
|
|
1145
|
-
}
|
|
1146
|
-
} else {
|
|
1147
|
-
// multi - cell
|
|
1148
|
-
const firstRow = selectedCells[0].parentNode;
|
|
1149
|
-
// remove cell
|
|
1150
|
-
if (!option) {
|
|
1151
|
-
const removeCells = [selectedCells[0]];
|
|
1152
|
-
|
|
1153
|
-
for (let i = 1, len = selectedCells.length, cell; i < len; i++) {
|
|
1154
|
-
cell = selectedCells[i];
|
|
1155
|
-
if (firstRow === cell.parentNode) {
|
|
1156
|
-
removeCells.push(cell);
|
|
1157
|
-
} else {
|
|
1158
|
-
break;
|
|
1159
|
-
}
|
|
1160
|
-
}
|
|
1161
|
-
|
|
1162
|
-
for (let i = 0, len = removeCells.length; i < len; i++) {
|
|
1163
|
-
this.setCellInfo(removeCells[i], true);
|
|
1164
|
-
this.editCell(option);
|
|
1165
|
-
}
|
|
1166
|
-
} else {
|
|
1167
|
-
// edit cell
|
|
1168
|
-
let rightCell = null;
|
|
1169
|
-
|
|
1170
|
-
for (let i = 0, len = selectedCells.length - 1; i < len; i++) {
|
|
1171
|
-
if (firstRow !== selectedCells[i + 1].parentNode) {
|
|
1172
|
-
rightCell = selectedCells[i];
|
|
1173
|
-
break;
|
|
1174
|
-
}
|
|
1175
|
-
}
|
|
1176
|
-
|
|
1177
|
-
this.setCellInfo(option === 'left' ? selectedCells[0] : rightCell || selectedCells[0], true);
|
|
1178
|
-
this.editCell(option, null, positionCell);
|
|
1179
|
-
}
|
|
1180
|
-
}
|
|
1181
|
-
|
|
1182
|
-
if (!option) this.close();
|
|
1183
|
-
} // one
|
|
1184
|
-
else {
|
|
1185
|
-
this[isRow ? 'editRow' : 'editCell'](option);
|
|
1186
|
-
}
|
|
1187
|
-
|
|
1188
|
-
// after remove
|
|
1189
|
-
if (!option) {
|
|
1190
|
-
const children = table.children;
|
|
1191
|
-
for (let i = 0; i < children.length; i++) {
|
|
1192
|
-
if (children[i].children.length === 0) {
|
|
1193
|
-
dom.utils.removeItem(children[i]);
|
|
1194
|
-
i--;
|
|
1195
|
-
}
|
|
1196
|
-
}
|
|
1197
|
-
|
|
1198
|
-
if (table.children.length === 0) dom.utils.removeItem(table);
|
|
1199
|
-
}
|
|
1200
|
-
}
|
|
1201
|
-
|
|
1202
|
-
/**
|
|
1203
|
-
* @description Edits a table row, either adding, removing, the row
|
|
1204
|
-
* @param {?string} option The action to perform on the row ("up"|"down"|null)
|
|
1205
|
-
* - null: to remove the row
|
|
1206
|
-
* - 'up': to insert the row up
|
|
1207
|
-
* - 'down': to insert the row down, or null to remove.
|
|
1208
|
-
* @param {?HTMLTableCellElement=} targetCell Target cell, (default: current selected cell)
|
|
1209
|
-
* @param {?HTMLTableCellElement=} [positionResetElement] The element to reset the position of (optional). This can be the cell that triggered the row edit.
|
|
1210
|
-
*/
|
|
1211
|
-
editRow(option, targetCell, positionResetElement) {
|
|
1212
|
-
this._deleteStyleSelectedCells();
|
|
1213
|
-
if (targetCell) this.setCellInfo(targetCell, true);
|
|
1214
|
-
|
|
1215
|
-
const remove = !option;
|
|
1216
|
-
const up = option === 'up';
|
|
1217
|
-
const originRowIndex = this._rowIndex;
|
|
1218
|
-
const rowIndex = remove || up ? originRowIndex : originRowIndex + this._current_rowSpan + 1;
|
|
1219
|
-
const sign = remove ? -1 : 1;
|
|
1220
|
-
|
|
1221
|
-
const rows = this._trElements;
|
|
1222
|
-
let cellCnt = this._logical_cellCnt;
|
|
1223
|
-
|
|
1224
|
-
for (let i = 0, len = originRowIndex + (remove ? -1 : 0), cell; i <= len; i++) {
|
|
1225
|
-
cell = rows[i].cells;
|
|
1226
|
-
if (cell.length === 0) return;
|
|
1227
|
-
|
|
1228
|
-
for (let c = 0, cLen = cell.length, rs, cs; c < cLen; c++) {
|
|
1229
|
-
rs = cell[c].rowSpan;
|
|
1230
|
-
cs = cell[c].colSpan;
|
|
1231
|
-
if (rs < 2 && cs < 2) continue;
|
|
1232
|
-
|
|
1233
|
-
if (rs + i > rowIndex && rowIndex > i) {
|
|
1234
|
-
cell[c].rowSpan = rs + sign;
|
|
1235
|
-
cellCnt -= cs;
|
|
1236
|
-
}
|
|
1237
|
-
}
|
|
1238
|
-
}
|
|
1239
|
-
|
|
1240
|
-
if (remove) {
|
|
1241
|
-
const next = rows[originRowIndex + 1];
|
|
1242
|
-
if (next) {
|
|
1243
|
-
const spanCells = [];
|
|
1244
|
-
let cells = rows[originRowIndex].cells;
|
|
1245
|
-
let colSpan = 0;
|
|
1246
|
-
|
|
1247
|
-
for (let i = 0, len = cells.length, cell, logcalIndex; i < len; i++) {
|
|
1248
|
-
cell = cells[i];
|
|
1249
|
-
logcalIndex = i + colSpan;
|
|
1250
|
-
colSpan += cell.colSpan - 1;
|
|
1251
|
-
|
|
1252
|
-
if (cell.rowSpan > 1) {
|
|
1253
|
-
cell.rowSpan -= 1;
|
|
1254
|
-
spanCells.push({ cell: /** @type {HTMLTableCellElement} */ (cell.cloneNode(false)), index: logcalIndex });
|
|
1255
|
-
}
|
|
1256
|
-
}
|
|
1257
|
-
|
|
1258
|
-
if (spanCells.length > 0) {
|
|
1259
|
-
let spanCell = spanCells.shift();
|
|
1260
|
-
cells = next.cells;
|
|
1261
|
-
colSpan = 0;
|
|
1262
|
-
|
|
1263
|
-
for (let i = 0, len = cells.length, cell, logcalIndex; i < len; i++) {
|
|
1264
|
-
cell = cells[i];
|
|
1265
|
-
logcalIndex = i + colSpan;
|
|
1266
|
-
colSpan += cell.colSpan - 1;
|
|
1267
|
-
|
|
1268
|
-
if (logcalIndex >= spanCell.index) {
|
|
1269
|
-
i--;
|
|
1270
|
-
colSpan--;
|
|
1271
|
-
colSpan += spanCell.cell.colSpan - 1;
|
|
1272
|
-
next.insertBefore(spanCell.cell, cell);
|
|
1273
|
-
spanCell = spanCells.shift();
|
|
1274
|
-
if (!spanCell) break;
|
|
1275
|
-
}
|
|
1276
|
-
}
|
|
1277
|
-
|
|
1278
|
-
if (spanCell) {
|
|
1279
|
-
next.appendChild(spanCell.cell);
|
|
1280
|
-
for (let i = 0, len = spanCells.length; i < len; i++) {
|
|
1281
|
-
next.appendChild(spanCells[i].cell);
|
|
1282
|
-
}
|
|
1283
|
-
}
|
|
1284
|
-
}
|
|
1285
|
-
}
|
|
1286
|
-
|
|
1287
|
-
this._element.deleteRow(rowIndex);
|
|
1288
|
-
} else {
|
|
1289
|
-
this.insertBodyRow(this._element, rowIndex, cellCnt);
|
|
1290
|
-
}
|
|
1291
|
-
|
|
1292
|
-
if (!remove) {
|
|
1293
|
-
this._setCellControllerPosition(positionResetElement || this._tdElement, true);
|
|
1294
|
-
} else {
|
|
1295
|
-
this._closeController();
|
|
1296
|
-
}
|
|
1297
|
-
}
|
|
1298
|
-
|
|
1299
|
-
/**
|
|
1300
|
-
* @description Edits a table cell(column), either adding, removing, or modifying the cell based on the provided option.
|
|
1301
|
-
* @param {?string} option The action to perform on the cell ("left"|"right"|null)
|
|
1302
|
-
* - null: to remove the cell
|
|
1303
|
-
* - left: to insert a new cell to the left
|
|
1304
|
-
* - right: to insert a new cell to the right
|
|
1305
|
-
* @param {?HTMLTableCellElement=} targetCell Target cell, (default: current selected cell)
|
|
1306
|
-
* @param {?HTMLTableCellElement=} positionResetElement The element to reset the position of (optional). This can be the cell that triggered the column edit.
|
|
1307
|
-
* @returns {HTMLTableCellElement} Target table cell
|
|
1308
|
-
*/
|
|
1309
|
-
editCell(option, targetCell, positionResetElement) {
|
|
1310
|
-
if (targetCell) this.setCellInfo(targetCell, true);
|
|
1311
|
-
|
|
1312
|
-
const remove = !option;
|
|
1313
|
-
const left = option === 'left';
|
|
1314
|
-
const colSpan = this._current_colSpan;
|
|
1315
|
-
const cellIndex = remove || left ? this._logical_cellIndex : this._logical_cellIndex + colSpan + 1;
|
|
1316
|
-
|
|
1317
|
-
const rows = this._trElements;
|
|
1318
|
-
let rowSpanArr = [];
|
|
1319
|
-
let spanIndex = [];
|
|
1320
|
-
let passCell = 0;
|
|
1321
|
-
let insertIndex;
|
|
1322
|
-
const removeCell = [];
|
|
1323
|
-
const removeSpanArr = [];
|
|
1324
|
-
|
|
1325
|
-
for (let i = 0, len = this._rowCnt, row, cells, newCell, applySpan, cellColSpan; i < len; i++) {
|
|
1326
|
-
row = rows[i];
|
|
1327
|
-
insertIndex = cellIndex;
|
|
1328
|
-
applySpan = false;
|
|
1329
|
-
cells = row.cells;
|
|
1330
|
-
cellColSpan = 0;
|
|
1331
|
-
|
|
1332
|
-
for (let c = 0, cell, cLen = cells.length, rs, cs, removeIndex; c < cLen; c++) {
|
|
1333
|
-
cell = cells[c];
|
|
1334
|
-
if (!cell) break;
|
|
1335
|
-
|
|
1336
|
-
rs = cell.rowSpan - 1;
|
|
1337
|
-
cs = cell.colSpan - 1;
|
|
1338
|
-
|
|
1339
|
-
if (!remove) {
|
|
1340
|
-
if (c >= insertIndex) break;
|
|
1341
|
-
if (cs > 0) {
|
|
1342
|
-
if (passCell < 1 && cs + c >= insertIndex) {
|
|
1343
|
-
cell.colSpan += 1;
|
|
1344
|
-
insertIndex = null;
|
|
1345
|
-
passCell = rs + 1;
|
|
1346
|
-
break;
|
|
1347
|
-
}
|
|
1348
|
-
|
|
1349
|
-
insertIndex -= cs;
|
|
1350
|
-
}
|
|
1351
|
-
|
|
1352
|
-
if (!applySpan) {
|
|
1353
|
-
for (let r = 0, arr; r < spanIndex.length; r++) {
|
|
1354
|
-
arr = spanIndex[r];
|
|
1355
|
-
insertIndex -= arr.cs;
|
|
1356
|
-
arr.rs -= 1;
|
|
1357
|
-
if (arr.rs < 1) {
|
|
1358
|
-
spanIndex.splice(r, 1);
|
|
1359
|
-
r--;
|
|
1360
|
-
}
|
|
1361
|
-
}
|
|
1362
|
-
applySpan = true;
|
|
1363
|
-
}
|
|
1364
|
-
} else {
|
|
1365
|
-
removeIndex = c + cellColSpan;
|
|
1366
|
-
|
|
1367
|
-
if (spanIndex.length > 0) {
|
|
1368
|
-
const lastCell = !cells[c + 1];
|
|
1369
|
-
for (let r = 0, arr; r < spanIndex.length; r++) {
|
|
1370
|
-
arr = spanIndex[r];
|
|
1371
|
-
if (arr.row > i) continue;
|
|
1372
|
-
|
|
1373
|
-
if (removeIndex >= arr.index) {
|
|
1374
|
-
cellColSpan += arr.cs;
|
|
1375
|
-
removeIndex = c + cellColSpan;
|
|
1376
|
-
arr.rs -= 1;
|
|
1377
|
-
arr.row = i + 1;
|
|
1378
|
-
if (arr.rs < 1) {
|
|
1379
|
-
spanIndex.splice(r, 1);
|
|
1380
|
-
r--;
|
|
1381
|
-
}
|
|
1382
|
-
} else if (lastCell) {
|
|
1383
|
-
arr.rs -= 1;
|
|
1384
|
-
arr.row = i + 1;
|
|
1385
|
-
if (arr.rs < 1) {
|
|
1386
|
-
spanIndex.splice(r, 1);
|
|
1387
|
-
r--;
|
|
1388
|
-
}
|
|
1389
|
-
}
|
|
1390
|
-
}
|
|
1391
|
-
}
|
|
1392
|
-
|
|
1393
|
-
if (rs > 0) {
|
|
1394
|
-
rowSpanArr.push({
|
|
1395
|
-
rs: rs,
|
|
1396
|
-
cs: cs + 1,
|
|
1397
|
-
index: removeIndex,
|
|
1398
|
-
row: -1
|
|
1399
|
-
});
|
|
1400
|
-
}
|
|
1401
|
-
|
|
1402
|
-
if (removeIndex >= insertIndex && removeIndex + cs <= insertIndex + colSpan) {
|
|
1403
|
-
removeCell.push(cell);
|
|
1404
|
-
} else if (removeIndex <= insertIndex + colSpan && removeIndex + cs >= insertIndex) {
|
|
1405
|
-
cell.colSpan -= numbers.getOverlapRangeAtIndex(cellIndex, cellIndex + colSpan, removeIndex, removeIndex + cs);
|
|
1406
|
-
} else if (rs > 0 && (removeIndex < insertIndex || removeIndex + cs > insertIndex + colSpan)) {
|
|
1407
|
-
removeSpanArr.push({
|
|
1408
|
-
cell: cell,
|
|
1409
|
-
i: i,
|
|
1410
|
-
rs: i + rs
|
|
1411
|
-
});
|
|
1412
|
-
}
|
|
1413
|
-
|
|
1414
|
-
cellColSpan += cs;
|
|
1415
|
-
}
|
|
1416
|
-
}
|
|
1417
|
-
|
|
1418
|
-
spanIndex = spanIndex.concat(rowSpanArr).sort(function (a, b) {
|
|
1419
|
-
return a.index - b.index;
|
|
1420
|
-
});
|
|
1421
|
-
rowSpanArr = [];
|
|
1422
|
-
|
|
1423
|
-
if (!remove) {
|
|
1424
|
-
if (passCell > 0) {
|
|
1425
|
-
passCell -= 1;
|
|
1426
|
-
continue;
|
|
1427
|
-
}
|
|
1428
|
-
|
|
1429
|
-
if (insertIndex !== null && cells.length > 0) {
|
|
1430
|
-
newCell = CreateCellsHTML(cells[0].nodeName);
|
|
1431
|
-
newCell = row.insertBefore(newCell, cells[insertIndex]);
|
|
1432
|
-
}
|
|
1433
|
-
}
|
|
1434
|
-
}
|
|
1435
|
-
|
|
1436
|
-
const colgroup = this._element.querySelector('colgroup');
|
|
1437
|
-
if (colgroup) {
|
|
1438
|
-
const cols = colgroup.querySelectorAll('col');
|
|
1439
|
-
if (remove) {
|
|
1440
|
-
dom.utils.removeItem(cols[insertIndex]);
|
|
1441
|
-
} else {
|
|
1442
|
-
let totalW = 0;
|
|
1443
|
-
for (let i = 0, len = cols.length, w; i < len; i++) {
|
|
1444
|
-
w = numbers.get(cols[i].style.width);
|
|
1445
|
-
w -= Math.round((w * len * 0.1) / 2);
|
|
1446
|
-
totalW += w;
|
|
1447
|
-
cols[i].style.width = `${w}%`;
|
|
1448
|
-
}
|
|
1449
|
-
const newCol = dom.utils.createElement('col', { style: `width:${100 - totalW}%` });
|
|
1450
|
-
colgroup.insertBefore(newCol, cols[insertIndex]);
|
|
1451
|
-
}
|
|
1452
|
-
}
|
|
1453
|
-
|
|
1454
|
-
if (remove) {
|
|
1455
|
-
let removeFirst, removeEnd;
|
|
1456
|
-
for (let r = 0, rLen = removeCell.length, row; r < rLen; r++) {
|
|
1457
|
-
row = /** @type {HTMLTableRowElement} */ (removeCell[r].parentNode);
|
|
1458
|
-
dom.utils.removeItem(removeCell[r]);
|
|
1459
|
-
if (row.cells.length === 0) {
|
|
1460
|
-
if (!removeFirst) removeFirst = dom.utils.getArrayIndex(rows, row);
|
|
1461
|
-
removeEnd = dom.utils.getArrayIndex(rows, row);
|
|
1462
|
-
dom.utils.removeItem(row);
|
|
1463
|
-
}
|
|
1464
|
-
}
|
|
1465
|
-
|
|
1466
|
-
for (let c = 0, cLen = removeSpanArr.length, rowSpanCell; c < cLen; c++) {
|
|
1467
|
-
rowSpanCell = removeSpanArr[c];
|
|
1468
|
-
rowSpanCell.cell.rowSpan = numbers.getOverlapRangeAtIndex(removeFirst, removeEnd, rowSpanCell.i, rowSpanCell.rs);
|
|
1469
|
-
}
|
|
1470
|
-
|
|
1471
|
-
this._closeController();
|
|
1472
|
-
} else {
|
|
1473
|
-
this._setCellControllerPosition(positionResetElement || this._tdElement, true);
|
|
1474
|
-
}
|
|
1475
|
-
|
|
1476
|
-
return positionResetElement || this._tdElement;
|
|
1477
|
-
}
|
|
1478
|
-
|
|
1479
|
-
/**
|
|
1480
|
-
* @description Updates the target table's cells with the data from the copied table.
|
|
1481
|
-
* @param {HTMLTableElement} copyTable The table containing the copied data.
|
|
1482
|
-
* @param {HTMLTableCellElement} targetTD The starting cell in the target table where data will be pasted.
|
|
1483
|
-
*/
|
|
1484
|
-
pasteTableCellMatrix(copyTable, targetTD) {
|
|
1485
|
-
if (!copyTable || !targetTD) return;
|
|
1486
|
-
|
|
1487
|
-
// --- copy info ---
|
|
1488
|
-
const copyRows = copyTable.rows;
|
|
1489
|
-
let rowCnt = 0;
|
|
1490
|
-
const colIndexMap = [];
|
|
1491
|
-
for (let row = 0; row < copyRows.length; row++) {
|
|
1492
|
-
const cells = copyRows[row].cells;
|
|
1493
|
-
let logicalCol = 0;
|
|
1494
|
-
|
|
1495
|
-
for (let i = 0; i < cells.length; i++) {
|
|
1496
|
-
const cell = cells[i];
|
|
1497
|
-
|
|
1498
|
-
while (colIndexMap[row]?.[logicalCol]) {
|
|
1499
|
-
logicalCol++;
|
|
1500
|
-
}
|
|
1501
|
-
|
|
1502
|
-
const rowspan = cell.rowSpan || 1;
|
|
1503
|
-
const colspan = cell.colSpan || 1;
|
|
1504
|
-
|
|
1505
|
-
if (logicalCol === 0) {
|
|
1506
|
-
rowCnt += rowspan;
|
|
1507
|
-
}
|
|
1508
|
-
|
|
1509
|
-
// rowspan map
|
|
1510
|
-
for (let r = 0; r < rowspan; r++) {
|
|
1511
|
-
for (let c = 0; c < colspan; c++) {
|
|
1512
|
-
if (!colIndexMap[row + r]) colIndexMap[row + r] = [];
|
|
1513
|
-
colIndexMap[row + r][logicalCol + c] = true;
|
|
1514
|
-
}
|
|
1515
|
-
}
|
|
1516
|
-
|
|
1517
|
-
logicalCol += colspan;
|
|
1518
|
-
}
|
|
1519
|
-
}
|
|
1520
|
-
|
|
1521
|
-
let logicalColCount = 0;
|
|
1522
|
-
for (let i = 0, cells = copyRows[0].cells, len = cells.length; i < len; i++) {
|
|
1523
|
-
const cell = cells[i];
|
|
1524
|
-
logicalColCount += cell.colSpan || 1;
|
|
1525
|
-
}
|
|
1526
|
-
|
|
1527
|
-
const copyInfo = {
|
|
1528
|
-
rowCnt: rowCnt,
|
|
1529
|
-
logicalCellCnt: logicalColCount
|
|
1530
|
-
};
|
|
1531
|
-
|
|
1532
|
-
// --- target info ---
|
|
1533
|
-
this._deleteStyleSelectedCells();
|
|
1534
|
-
const originTable = targetTD.closest('table');
|
|
1535
|
-
const { cloneTable, clonedSelectedCells } = this.#cloneTable(originTable, [targetTD]);
|
|
1536
|
-
|
|
1537
|
-
const targetTable = cloneTable;
|
|
1538
|
-
targetTD = clonedSelectedCells[0];
|
|
1539
|
-
let targetRows = targetTable.rows;
|
|
1540
|
-
this.setTableInfo(targetTable);
|
|
1541
|
-
this.setCellInfo(targetTD, true);
|
|
1542
|
-
|
|
1543
|
-
const targetInfo = {
|
|
1544
|
-
physicalCellCnt: this._physical_cellCnt,
|
|
1545
|
-
logicalCellCnt: this._logical_cellCnt,
|
|
1546
|
-
rowCnt: this._rowCnt,
|
|
1547
|
-
rowInex: this._rowIndex,
|
|
1548
|
-
physicalCellIndex: this._physical_cellIndex,
|
|
1549
|
-
logicalCellIndex: this._logical_cellIndex,
|
|
1550
|
-
currentColSpan: this._current_colSpan,
|
|
1551
|
-
currentRowSpan: this._current_rowSpan
|
|
1552
|
-
};
|
|
1553
|
-
|
|
1554
|
-
// --- [expand] target table ---
|
|
1555
|
-
const addRowCnt = copyInfo.rowCnt - (targetInfo.rowCnt - (targetInfo.rowInex + 1)) - 1;
|
|
1556
|
-
const addColCnt = copyInfo.logicalCellCnt - (targetInfo.logicalCellCnt - (targetInfo.logicalCellIndex + 1)) - 1;
|
|
1557
|
-
targetInfo.rowCnt += addRowCnt;
|
|
1558
|
-
targetInfo.logicalCellCnt += addColCnt;
|
|
1559
|
-
targetInfo.physicalCellCnt += addColCnt;
|
|
1560
|
-
|
|
1561
|
-
if (addRowCnt > 0 || addColCnt > 0) {
|
|
1562
|
-
const lastRow = targetRows[targetRows.length - 1];
|
|
1563
|
-
const lastCell = lastRow.cells[lastRow.cells.length - 1];
|
|
1564
|
-
for (let i = 0; i < addRowCnt; i++) {
|
|
1565
|
-
this.editRow('down', lastCell);
|
|
1566
|
-
}
|
|
1567
|
-
for (let i = 0; i < addColCnt; i++) {
|
|
1568
|
-
this.editCell('right', lastCell);
|
|
1569
|
-
}
|
|
1570
|
-
targetRows = this._trElements = targetTable.rows;
|
|
1571
|
-
}
|
|
1572
|
-
|
|
1573
|
-
// --- [Un_merge] cells ---
|
|
1574
|
-
const startRowIndex = targetInfo.rowInex;
|
|
1575
|
-
const cellIndex = targetInfo.logicalCellIndex;
|
|
1576
|
-
const cellEndIndex = cellIndex + copyInfo.logicalCellCnt - 1;
|
|
1577
|
-
const unmergeCells = [];
|
|
1578
|
-
const un_mergeRowSpanMap = [];
|
|
1579
|
-
|
|
1580
|
-
for (let r = 0, len = startRowIndex + copyInfo.rowCnt; r < len; r++) {
|
|
1581
|
-
const cells = targetRows[r]?.cells;
|
|
1582
|
-
if (!cells) continue;
|
|
1583
|
-
|
|
1584
|
-
let logicalIndex = 0;
|
|
1585
|
-
let cellIndexInRow = 0;
|
|
1586
|
-
|
|
1587
|
-
for (let c = 0; c < cells.length; c++) {
|
|
1588
|
-
while (un_mergeRowSpanMap[r]?.[logicalIndex]) {
|
|
1589
|
-
logicalIndex++;
|
|
1590
|
-
}
|
|
1591
|
-
|
|
1592
|
-
const cell = cells[cellIndexInRow++];
|
|
1593
|
-
if (!cell) break;
|
|
1594
|
-
|
|
1595
|
-
const cs = cell.colSpan || 1;
|
|
1596
|
-
const rs = cell.rowSpan || 1;
|
|
1597
|
-
const logicalStart = logicalIndex;
|
|
1598
|
-
const logicalEnd = logicalIndex + cs - 1;
|
|
1599
|
-
|
|
1600
|
-
// rowSpan map
|
|
1601
|
-
if (rs > 1 || cs > 1) {
|
|
1602
|
-
for (let rsOffset = 1; rsOffset < rs; rsOffset++) {
|
|
1603
|
-
const rowIndex = r + rsOffset;
|
|
1604
|
-
if (!un_mergeRowSpanMap[rowIndex]) un_mergeRowSpanMap[rowIndex] = [];
|
|
1605
|
-
for (let csOffset = 0; csOffset < cs; csOffset++) {
|
|
1606
|
-
un_mergeRowSpanMap[rowIndex][logicalIndex + csOffset] = true;
|
|
1607
|
-
}
|
|
1608
|
-
}
|
|
1609
|
-
}
|
|
1610
|
-
|
|
1611
|
-
const isOverlap = logicalStart <= cellEndIndex && logicalEnd >= cellIndex;
|
|
1612
|
-
if (isOverlap && (cs > 1 || rs > 1)) {
|
|
1613
|
-
unmergeCells.push(cell);
|
|
1614
|
-
}
|
|
1615
|
-
|
|
1616
|
-
logicalIndex += cs;
|
|
1617
|
-
}
|
|
1618
|
-
}
|
|
1619
|
-
|
|
1620
|
-
if (unmergeCells.length > 0) {
|
|
1621
|
-
this.unmergeCells(unmergeCells, true);
|
|
1622
|
-
targetRows = this._trElements = targetTable.rows;
|
|
1623
|
-
}
|
|
1624
|
-
|
|
1625
|
-
// --- [merge] cells ---
|
|
1626
|
-
const mergeGroups = [];
|
|
1627
|
-
const copyCowSpanMap = [];
|
|
1628
|
-
const targetRowSpanMap = [];
|
|
1629
|
-
for (let r = 0, len = copyInfo.rowCnt; r < len; r++) {
|
|
1630
|
-
const cells = copyRows[r]?.cells;
|
|
1631
|
-
if (!cells) break;
|
|
1632
|
-
|
|
1633
|
-
let copyIndex = 0;
|
|
1634
|
-
for (let c = 0; c < cells.length; c++) {
|
|
1635
|
-
const cell = cells[c];
|
|
1636
|
-
const cs = cell.colSpan || 1;
|
|
1637
|
-
const rs = cell.rowSpan || 1;
|
|
1638
|
-
|
|
1639
|
-
while (copyCowSpanMap[r]?.[copyIndex]) {
|
|
1640
|
-
copyIndex++;
|
|
1641
|
-
}
|
|
1642
|
-
|
|
1643
|
-
for (let rsOffset = 1; rsOffset < rs; rsOffset++) {
|
|
1644
|
-
const rowIndex = r + rsOffset;
|
|
1645
|
-
if (!copyCowSpanMap[rowIndex]) copyCowSpanMap[rowIndex] = [];
|
|
1646
|
-
for (let csOffset = 0; csOffset < cs; csOffset++) {
|
|
1647
|
-
copyCowSpanMap[rowIndex][copyIndex + csOffset] = true;
|
|
1648
|
-
}
|
|
1649
|
-
}
|
|
1650
|
-
|
|
1651
|
-
if (cs <= 1 && rs <= 1) {
|
|
1652
|
-
copyIndex += cs;
|
|
1653
|
-
continue;
|
|
1654
|
-
}
|
|
1655
|
-
|
|
1656
|
-
const cStart = copyIndex + targetInfo.logicalCellIndex;
|
|
1657
|
-
const cEnd = cStart + cs - 1;
|
|
1658
|
-
const mergeCells = [];
|
|
1659
|
-
|
|
1660
|
-
for (let targetR = targetInfo.rowInex + r, tRowCnt = targetR + rs, rowOffset = 0; targetR < tRowCnt; targetR++, rowOffset++) {
|
|
1661
|
-
const targetRow = targetRows[targetR];
|
|
1662
|
-
const targetCells = targetRow.cells;
|
|
1663
|
-
|
|
1664
|
-
let logicalIndex = 0;
|
|
1665
|
-
let targetIndex = 0;
|
|
1666
|
-
|
|
1667
|
-
while (targetIndex < targetCells.length && logicalIndex <= cEnd) {
|
|
1668
|
-
while (targetRowSpanMap[targetR]?.[logicalIndex]) {
|
|
1669
|
-
logicalIndex++;
|
|
1670
|
-
}
|
|
1671
|
-
|
|
1672
|
-
const tCell = targetCells[targetIndex++];
|
|
1673
|
-
const tcs = tCell.colSpan || 1;
|
|
1674
|
-
const trs = tCell.rowSpan || 1;
|
|
1675
|
-
const logicalStart = logicalIndex;
|
|
1676
|
-
const logicalEnd = logicalIndex + tcs - 1;
|
|
1677
|
-
|
|
1678
|
-
// rowSpan map
|
|
1679
|
-
if (trs > 1) {
|
|
1680
|
-
for (let rsOffset = 1; rsOffset < trs; rsOffset++) {
|
|
1681
|
-
const rIndex = targetR + rsOffset;
|
|
1682
|
-
if (!targetRowSpanMap[rIndex]) targetRowSpanMap[rIndex] = [];
|
|
1683
|
-
for (let i = 0; i < tcs; i++) {
|
|
1684
|
-
targetRowSpanMap[rIndex][logicalIndex + i] = true;
|
|
1685
|
-
}
|
|
1686
|
-
}
|
|
1687
|
-
}
|
|
1688
|
-
|
|
1689
|
-
if (logicalEnd >= cStart && logicalStart <= cEnd) {
|
|
1690
|
-
mergeCells.push(tCell);
|
|
1691
|
-
}
|
|
1692
|
-
|
|
1693
|
-
logicalIndex += tcs;
|
|
1694
|
-
}
|
|
1695
|
-
}
|
|
1696
|
-
|
|
1697
|
-
if (mergeCells.length > 0) {
|
|
1698
|
-
mergeGroups.push(mergeCells);
|
|
1699
|
-
}
|
|
1700
|
-
|
|
1701
|
-
copyIndex += cs;
|
|
1702
|
-
}
|
|
1703
|
-
}
|
|
1704
|
-
|
|
1705
|
-
if (mergeGroups.length > 0) {
|
|
1706
|
-
for (const mc of mergeGroups) {
|
|
1707
|
-
this._ref = null;
|
|
1708
|
-
this._trElements = targetTable.rows;
|
|
1709
|
-
this.mergeCells(mc, true);
|
|
1710
|
-
}
|
|
1711
|
-
targetRows = this._trElements = targetTable.rows;
|
|
1712
|
-
}
|
|
1713
|
-
|
|
1714
|
-
// --- [result] paste cell data ---
|
|
1715
|
-
const selectedCells = [];
|
|
1716
|
-
const rowSpanMap = [];
|
|
1717
|
-
for (let r = 0; r < copyInfo.rowCnt; r++) {
|
|
1718
|
-
const tr = targetRows[targetInfo.rowInex + r];
|
|
1719
|
-
const cr = copyRows[r];
|
|
1720
|
-
if (!tr || !cr) break;
|
|
1721
|
-
|
|
1722
|
-
const tCells = tr.cells;
|
|
1723
|
-
const cCells = cr.cells;
|
|
1724
|
-
|
|
1725
|
-
let tLogicalIndex = 0;
|
|
1726
|
-
let tIndex = 0;
|
|
1727
|
-
let cIndex = 0;
|
|
1728
|
-
|
|
1729
|
-
while (tIndex < tCells.length && cIndex < cCells.length && tLogicalIndex <= cellEndIndex) {
|
|
1730
|
-
while (rowSpanMap[r]?.[tLogicalIndex]) {
|
|
1731
|
-
tLogicalIndex++;
|
|
1732
|
-
}
|
|
1733
|
-
|
|
1734
|
-
const tCell = tCells[tIndex++];
|
|
1735
|
-
const cCell = cCells[cIndex];
|
|
1736
|
-
if (!tCell || !cCell) break;
|
|
1737
|
-
|
|
1738
|
-
const tcs = tCell.colSpan || 1;
|
|
1739
|
-
const trs = tCell.rowSpan || 1;
|
|
1740
|
-
|
|
1741
|
-
// rowSpan map
|
|
1742
|
-
if (trs > 1) {
|
|
1743
|
-
for (let rs = 1; rs < trs; rs++) {
|
|
1744
|
-
const rr = r + rs;
|
|
1745
|
-
if (!rowSpanMap[rr]) rowSpanMap[rr] = [];
|
|
1746
|
-
for (let cs = 0; cs < tcs; cs++) {
|
|
1747
|
-
rowSpanMap[rr][tLogicalIndex + cs] = true;
|
|
1748
|
-
}
|
|
1749
|
-
}
|
|
1750
|
-
}
|
|
1751
|
-
|
|
1752
|
-
if (tLogicalIndex >= cellIndex && tLogicalIndex + tcs - 1 <= cellEndIndex) {
|
|
1753
|
-
tCell.innerHTML = cCell.innerHTML;
|
|
1754
|
-
selectedCells.push(tCell);
|
|
1755
|
-
cIndex++;
|
|
1756
|
-
}
|
|
1757
|
-
|
|
1758
|
-
tLogicalIndex += tcs;
|
|
1759
|
-
}
|
|
1760
|
-
}
|
|
1761
|
-
|
|
1762
|
-
// replace table
|
|
1763
|
-
originTable.replaceWith(targetTable);
|
|
1764
|
-
this._closeTableSelectInfo();
|
|
1765
|
-
this.setTableInfo(targetTable);
|
|
1766
|
-
|
|
1767
|
-
// select cell
|
|
1768
|
-
this.selectCells(selectedCells);
|
|
1769
|
-
this._setMergeSplitButton();
|
|
1770
|
-
this._setUnMergeButton();
|
|
1771
|
-
this.#focusEdge(selectedCells[0]);
|
|
1772
|
-
|
|
1773
|
-
// history push
|
|
1774
|
-
this._historyPush();
|
|
1775
|
-
}
|
|
1776
|
-
|
|
1777
|
-
/**
|
|
1778
|
-
* @description Inserts a new row into the table at the specified index to it.
|
|
1779
|
-
* @param {HTMLTableElement} table The table element to insert the row into.
|
|
1780
|
-
* @param {number} rowIndex The index at which to insert the new row.
|
|
1781
|
-
* @param {number} cellCnt The number of cells to create in the new row.
|
|
1782
|
-
* @returns {HTMLTableRowElement} The newly inserted row element.
|
|
1783
|
-
*/
|
|
1784
|
-
insertBodyRow(table, rowIndex, cellCnt) {
|
|
1785
|
-
const newRow = table.insertRow(rowIndex);
|
|
1786
|
-
newRow.innerHTML = CreateCellsString('td', cellCnt);
|
|
1787
|
-
return newRow;
|
|
1788
|
-
}
|
|
1789
|
-
|
|
1790
|
-
/**
|
|
1791
|
-
* @description Merges the selected table cells into one cell by combining their contents and adjusting their row and column spans.
|
|
1792
|
-
* - This method removes the selected cells, consolidates their contents, and applies the appropriate row and column spans to the merged cell.
|
|
1793
|
-
* @param {HTMLTableCellElement[]} selectedCells Cells array
|
|
1794
|
-
* @param {boolean} [skipPostProcess=false] - If true, skips table cloning, cell re-selection, history stack push, and rendering.
|
|
1795
|
-
*/
|
|
1796
|
-
mergeCells(selectedCells, skipPostProcess = false) {
|
|
1797
|
-
const originTable = selectedCells[0].closest('table');
|
|
1798
|
-
const { cloneTable, clonedSelectedCells } = skipPostProcess ? { cloneTable: originTable, clonedSelectedCells: selectedCells } : this.#cloneTable(originTable, selectedCells);
|
|
1799
|
-
|
|
1800
|
-
this.setTableInfo(cloneTable);
|
|
1801
|
-
selectedCells = clonedSelectedCells;
|
|
1802
|
-
this._ref = null;
|
|
1803
|
-
this._setMultiCells(selectedCells[0], dom.query.findVisualLastCell(selectedCells));
|
|
1804
|
-
|
|
1805
|
-
const ref = this._ref;
|
|
1806
|
-
const mergeCell = selectedCells[0];
|
|
1807
|
-
|
|
1808
|
-
let emptyRowFirst = null;
|
|
1809
|
-
let emptyRowLast = null;
|
|
1810
|
-
const cs = ref.ce - ref.cs + 1;
|
|
1811
|
-
let rs = ref.re - ref.rs + 1;
|
|
1812
|
-
let mergeHTML = '';
|
|
1813
|
-
let row = null;
|
|
1814
|
-
|
|
1815
|
-
for (let i = 1, len = selectedCells.length, cell, ch; i < len; i++) {
|
|
1816
|
-
cell = selectedCells[i];
|
|
1817
|
-
if (row !== cell.parentNode) row = /** @type {HTMLTableRowElement} */ (cell.parentNode);
|
|
1818
|
-
|
|
1819
|
-
ch = cell.children;
|
|
1820
|
-
for (let c = 0, cLen = ch.length; c < cLen; c++) {
|
|
1821
|
-
if (this.format.isLine(ch[c]) && dom.check.isZeroWidth(ch[c].textContent)) {
|
|
1822
|
-
dom.utils.removeItem(ch[c]);
|
|
1823
|
-
}
|
|
1824
|
-
}
|
|
1825
|
-
|
|
1826
|
-
mergeHTML += cell.innerHTML;
|
|
1827
|
-
dom.utils.removeItem(cell);
|
|
1828
|
-
|
|
1829
|
-
if (row.cells.length === 0) {
|
|
1830
|
-
if (!emptyRowFirst) emptyRowFirst = row;
|
|
1831
|
-
else emptyRowLast = row;
|
|
1832
|
-
rs -= 1;
|
|
1833
|
-
}
|
|
1834
|
-
}
|
|
1835
|
-
|
|
1836
|
-
if (emptyRowFirst) {
|
|
1837
|
-
const rows = this._trElements;
|
|
1838
|
-
const rowIndexFirst = dom.utils.getArrayIndex(rows, emptyRowFirst);
|
|
1839
|
-
const rowIndexLast = dom.utils.getArrayIndex(rows, emptyRowLast || emptyRowFirst);
|
|
1840
|
-
const removeRows = [];
|
|
1841
|
-
|
|
1842
|
-
for (let i = 0, cells; i <= rowIndexLast; i++) {
|
|
1843
|
-
cells = rows[i].cells;
|
|
1844
|
-
if (cells.length === 0) {
|
|
1845
|
-
removeRows.push(rows[i]);
|
|
1846
|
-
continue;
|
|
1847
|
-
}
|
|
1848
|
-
|
|
1849
|
-
for (let c = 0, cLen = cells.length, cell, rs2; c < cLen; c++) {
|
|
1850
|
-
cell = cells[c];
|
|
1851
|
-
rs2 = cell.rowSpan - 1;
|
|
1852
|
-
if (rs2 > 0 && i + rs2 >= rowIndexFirst) {
|
|
1853
|
-
cell.rowSpan -= numbers.getOverlapRangeAtIndex(rowIndexFirst, rowIndexLast, i, i + rs2);
|
|
1854
|
-
}
|
|
1855
|
-
}
|
|
1856
|
-
}
|
|
1857
|
-
|
|
1858
|
-
for (let i = 0, len = removeRows.length; i < len; i++) {
|
|
1859
|
-
dom.utils.removeItem(removeRows[i]);
|
|
1860
|
-
}
|
|
1861
|
-
}
|
|
1862
|
-
|
|
1863
|
-
mergeCell.innerHTML += mergeHTML;
|
|
1864
|
-
mergeCell.colSpan = cs;
|
|
1865
|
-
mergeCell.rowSpan = rs;
|
|
1866
|
-
|
|
1867
|
-
if (skipPostProcess) return;
|
|
1868
|
-
|
|
1869
|
-
// replace table
|
|
1870
|
-
originTable.replaceWith(cloneTable);
|
|
1871
|
-
this._closeTableSelectInfo();
|
|
1872
|
-
|
|
1873
|
-
this._setMergeSplitButton();
|
|
1874
|
-
this._setController(mergeCell);
|
|
1875
|
-
|
|
1876
|
-
this.#focusEdge(mergeCell);
|
|
1877
|
-
|
|
1878
|
-
// history push
|
|
1879
|
-
this._historyPush();
|
|
1880
|
-
}
|
|
1881
|
-
|
|
1882
|
-
/**
|
|
1883
|
-
* @description Unmerges a table cell that has been merged using rowspan and/or colspan.
|
|
1884
|
-
* @param {HTMLTableCellElement[]} selectedCells - Cells array
|
|
1885
|
-
* @param {boolean} [skipPostProcess=false] - If true, skips table cloning, cell re-selection, history stack push, and rendering.
|
|
1886
|
-
*/
|
|
1887
|
-
unmergeCells(selectedCells, skipPostProcess = false) {
|
|
1888
|
-
if (!selectedCells?.length) return;
|
|
1889
|
-
|
|
1890
|
-
const originTable = selectedCells[0].closest('table');
|
|
1891
|
-
const { cloneTable, clonedSelectedCells } = skipPostProcess ? { cloneTable: originTable, clonedSelectedCells: selectedCells } : this.#cloneTable(originTable, selectedCells);
|
|
1892
|
-
|
|
1893
|
-
this._ref = null;
|
|
1894
|
-
this.setTableInfo(cloneTable);
|
|
1895
|
-
selectedCells = clonedSelectedCells;
|
|
1896
|
-
|
|
1897
|
-
let firstCell = selectedCells[0];
|
|
1898
|
-
let lastCell = dom.query.findVisualLastCell(selectedCells);
|
|
1899
|
-
let newLastCell = null;
|
|
1900
|
-
|
|
1901
|
-
const table = firstCell.closest('table');
|
|
1902
|
-
const rows = table.rows;
|
|
1903
|
-
|
|
1904
|
-
for (const cell of selectedCells) {
|
|
1905
|
-
const tr = /** @type {HTMLTableRowElement} */ (cell.parentElement);
|
|
1906
|
-
const rowIndex = tr.rowIndex;
|
|
1907
|
-
const colIndex = cell.cellIndex;
|
|
1908
|
-
const rowspan = cell.rowSpan;
|
|
1909
|
-
const colspan = cell.colSpan;
|
|
1910
|
-
|
|
1911
|
-
if (rowspan === 1 && colspan === 1) continue;
|
|
1912
|
-
|
|
1913
|
-
this.setCellInfo(cell, true);
|
|
1914
|
-
|
|
1915
|
-
const originalHTML = cell.innerHTML;
|
|
1916
|
-
cell.remove();
|
|
1917
|
-
|
|
1918
|
-
for (let r = 0; r < rowspan; r++) {
|
|
1919
|
-
const targetRow = rows[rowIndex + r];
|
|
1920
|
-
|
|
1921
|
-
for (let c = 0; c < colspan; c++) {
|
|
1922
|
-
const newCell = CreateCellsHTML('td');
|
|
1923
|
-
|
|
1924
|
-
if (r === 0 && c === 0) {
|
|
1925
|
-
if (firstCell === cell) firstCell = newCell;
|
|
1926
|
-
if (lastCell === cell) lastCell = newCell;
|
|
1927
|
-
newCell.innerHTML = originalHTML;
|
|
1928
|
-
targetRow.insertBefore(newCell, targetRow.cells[colIndex]);
|
|
1929
|
-
} else {
|
|
1930
|
-
targetRow.insertBefore(newCell, targetRow.cells[colIndex + c]);
|
|
1931
|
-
newLastCell = newCell;
|
|
1932
|
-
}
|
|
1933
|
-
}
|
|
1934
|
-
}
|
|
1935
|
-
}
|
|
1936
|
-
|
|
1937
|
-
this._selectedCells = null;
|
|
1938
|
-
|
|
1939
|
-
if (skipPostProcess) return;
|
|
1940
|
-
|
|
1941
|
-
// replace table
|
|
1942
|
-
originTable.replaceWith(cloneTable);
|
|
1943
|
-
this._closeTableSelectInfo();
|
|
1944
|
-
this.setTableInfo(cloneTable);
|
|
1945
|
-
|
|
1946
|
-
// set info
|
|
1947
|
-
if (firstCell !== lastCell) {
|
|
1948
|
-
lastCell = !newLastCell || lastCell.closest('tr').rowIndex > newLastCell.closest('tr').rowIndex || lastCell.cellIndex > newLastCell.cellIndex ? lastCell : newLastCell;
|
|
1949
|
-
this._setMultiCells(firstCell, lastCell);
|
|
1950
|
-
this._selectedCells = Array.from(table.querySelectorAll('.se-selected-table-cell'));
|
|
1951
|
-
} else {
|
|
1952
|
-
this.setCellInfo(lastCell, true);
|
|
1953
|
-
}
|
|
1954
|
-
|
|
1955
|
-
this._fixedCell = firstCell;
|
|
1956
|
-
this._selectedCell = lastCell;
|
|
1957
|
-
dom.utils.addClass(lastCell, 'se-selected-cell-focus');
|
|
1958
|
-
|
|
1959
|
-
this._setUnMergeButton();
|
|
1960
|
-
this.controller_cell.resetPosition(lastCell);
|
|
1961
|
-
|
|
1962
|
-
// history push
|
|
1963
|
-
this._historyPush();
|
|
1964
|
-
}
|
|
1965
|
-
|
|
1966
|
-
/**
|
|
1967
|
-
* @description Find merged cells
|
|
1968
|
-
* @param {HTMLTableCellElement[]} cells - Cells array
|
|
1969
|
-
*/
|
|
1970
|
-
findMergedCells(cells) {
|
|
1971
|
-
const mergedCells = [];
|
|
1972
|
-
cells?.forEach((cell) => {
|
|
1973
|
-
if (cell && (cell.rowSpan > 1 || cell.colSpan > 1)) {
|
|
1974
|
-
mergedCells.push(cell);
|
|
1975
|
-
}
|
|
1976
|
-
});
|
|
1977
|
-
return mergedCells;
|
|
1978
|
-
}
|
|
1979
|
-
|
|
1980
|
-
/**
|
|
1981
|
-
* @description Toggles the visibility of the table header (`<thead>`). If the header is present, it is removed; if absent, it is added.
|
|
1982
|
-
*/
|
|
1983
|
-
toggleHeader() {
|
|
1984
|
-
const btn = this.headerButton;
|
|
1985
|
-
const active = dom.utils.hasClass(btn, 'active');
|
|
1986
|
-
const table = this._element;
|
|
1987
|
-
|
|
1988
|
-
if (!active) {
|
|
1989
|
-
const header = dom.utils.createElement('THEAD');
|
|
1990
|
-
header.innerHTML = '<tr>' + CreateCellsString('th', this._logical_cellCnt) + '</tr>';
|
|
1991
|
-
table.insertBefore(header, table.firstElementChild);
|
|
1992
|
-
} else {
|
|
1993
|
-
dom.utils.removeItem(table.querySelector('thead'));
|
|
1994
|
-
}
|
|
1995
|
-
|
|
1996
|
-
dom.utils.toggleClass(btn, 'active');
|
|
1997
|
-
|
|
1998
|
-
if (/TH/i.test(this._tdElement.nodeName)) {
|
|
1999
|
-
this._closeController();
|
|
2000
|
-
} else {
|
|
2001
|
-
this._setCellControllerPosition(this._tdElement, false);
|
|
2002
|
-
}
|
|
2003
|
-
}
|
|
2004
|
-
|
|
2005
|
-
/**
|
|
2006
|
-
* @description Toggles the visibility of the table caption (`<caption>`). If the caption is present, it is removed; if absent, it is added.
|
|
2007
|
-
*/
|
|
2008
|
-
toggleCaption() {
|
|
2009
|
-
const btn = this.captionButton;
|
|
2010
|
-
const active = dom.utils.hasClass(btn, 'active');
|
|
2011
|
-
const table = this._element;
|
|
2012
|
-
|
|
2013
|
-
if (!active) {
|
|
2014
|
-
const caption = dom.utils.createElement('CAPTION', { class: `se-table-caption-${this.captionPosition}` });
|
|
2015
|
-
caption.innerHTML = '<div><br></div>';
|
|
2016
|
-
table.insertBefore(caption, table.firstElementChild);
|
|
2017
|
-
} else {
|
|
2018
|
-
dom.utils.removeItem(table.querySelector('caption'));
|
|
2019
|
-
}
|
|
2020
|
-
|
|
2021
|
-
dom.utils.toggleClass(btn, 'active');
|
|
2022
|
-
this._setCellControllerPosition(this._tdElement, false);
|
|
2023
|
-
}
|
|
2024
|
-
|
|
2025
|
-
/**
|
|
2026
|
-
* @private
|
|
2027
|
-
* @description Updates table styles.
|
|
2028
|
-
* @param {string} styles - Styles to update.
|
|
2029
|
-
* @param {boolean} ondisplay - Whether to update display.
|
|
2030
|
-
*/
|
|
2031
|
-
_setTableStyle(styles, ondisplay) {
|
|
2032
|
-
if (styles.includes('width')) {
|
|
2033
|
-
const targets = this._figure;
|
|
2034
|
-
if (!targets) return;
|
|
2035
|
-
|
|
2036
|
-
let sizeIcon, text;
|
|
2037
|
-
if (!this._maxWidth) {
|
|
2038
|
-
sizeIcon = this.icons.expansion;
|
|
2039
|
-
text = this.maxText;
|
|
2040
|
-
if (!ondisplay) targets.style.width = 'min-content';
|
|
2041
|
-
} else {
|
|
2042
|
-
sizeIcon = this.icons.reduction;
|
|
2043
|
-
text = this.minText;
|
|
2044
|
-
if (!ondisplay) targets.style.width = '100%';
|
|
2045
|
-
}
|
|
2046
|
-
|
|
2047
|
-
dom.utils.changeElement(this.resizeButton.firstElementChild, sizeIcon);
|
|
2048
|
-
dom.utils.changeTxt(this.resizeText, text);
|
|
2049
|
-
}
|
|
2050
|
-
|
|
2051
|
-
if (styles.includes('column')) {
|
|
2052
|
-
if (!this._fixedColumn) {
|
|
2053
|
-
dom.utils.removeClass(this._element, 'se-table-layout-fixed');
|
|
2054
|
-
dom.utils.addClass(this._element, 'se-table-layout-auto');
|
|
2055
|
-
dom.utils.removeClass(this.columnFixedButton, 'active');
|
|
2056
|
-
} else {
|
|
2057
|
-
dom.utils.removeClass(this._element, 'se-table-layout-auto');
|
|
2058
|
-
dom.utils.addClass(this._element, 'se-table-layout-fixed');
|
|
2059
|
-
dom.utils.addClass(this.columnFixedButton, 'active');
|
|
2060
|
-
}
|
|
2061
|
-
}
|
|
2062
|
-
}
|
|
2063
|
-
|
|
2064
|
-
/**
|
|
2065
|
-
* @private
|
|
2066
|
-
* @description Sets the merge/split button visibility.
|
|
2067
|
-
*/
|
|
2068
|
-
_setMergeSplitButton() {
|
|
2069
|
-
if (!this._ref) {
|
|
2070
|
-
this.splitButton.style.display = 'block';
|
|
2071
|
-
this.mergeButton.style.display = 'none';
|
|
2072
|
-
} else {
|
|
2073
|
-
this.splitButton.style.display = 'none';
|
|
2074
|
-
this.mergeButton.style.display = 'block';
|
|
2075
|
-
}
|
|
2076
|
-
}
|
|
2077
|
-
|
|
2078
|
-
/**
|
|
2079
|
-
* @private
|
|
2080
|
-
* @description Sets the unmerge button visibility.
|
|
2081
|
-
*/
|
|
2082
|
-
_setUnMergeButton() {
|
|
2083
|
-
if (this.findMergedCells(!this._selectedCells?.length ? [this._fixedCell] : this._selectedCells).length > 0) {
|
|
2084
|
-
this.unmergeButton.disabled = false;
|
|
2085
|
-
} else {
|
|
2086
|
-
this.unmergeButton.disabled = true;
|
|
2087
|
-
}
|
|
2088
|
-
}
|
|
2089
|
-
|
|
2090
|
-
/**
|
|
2091
|
-
* @private
|
|
2092
|
-
* @description Sets the controller position for a cell.
|
|
2093
|
-
* @param {HTMLTableCellElement} tdElement - The target table cell.
|
|
2094
|
-
*/
|
|
2095
|
-
_setController(tdElement) {
|
|
2096
|
-
if (!this.selection.get().isCollapsed && !this._selectedCell) {
|
|
2097
|
-
this._deleteStyleSelectedCells();
|
|
2098
|
-
return;
|
|
2099
|
-
}
|
|
2100
|
-
|
|
2101
|
-
this._setUnMergeButton();
|
|
2102
|
-
|
|
2103
|
-
this._tdElement = tdElement;
|
|
2104
|
-
if (this._fixedCell === tdElement) dom.utils.addClass(tdElement, 'se-selected-cell-focus');
|
|
2105
|
-
if (!this._selectedCells?.length) this._selectedCells = [tdElement];
|
|
2106
|
-
const tableElement = this._selectedTable || this._element || dom.query.getParentElement(tdElement, 'TABLE');
|
|
2107
|
-
this.component.select(tableElement, Table.key, { isInput: true });
|
|
2108
|
-
}
|
|
2109
|
-
|
|
2110
|
-
/**
|
|
2111
|
-
* @private
|
|
2112
|
-
* @description Sets the position of the cell controller.
|
|
2113
|
-
* @param {HTMLTableCellElement} tdElement - The target table cell.
|
|
2114
|
-
* @param {boolean} reset - Whether to reset the controller position.
|
|
2115
|
-
*/
|
|
2116
|
-
_setCellControllerPosition(tdElement, reset) {
|
|
2117
|
-
this.setCellInfo(tdElement, reset);
|
|
2118
|
-
this.controller_cell.resetPosition(this.cellControllerTop ? dom.query.getParentElement(tdElement, dom.check.isTable) : tdElement);
|
|
2119
|
-
}
|
|
2120
|
-
|
|
2121
|
-
/**
|
|
2122
|
-
* @private
|
|
2123
|
-
* @description Adds a new entry to the history stack.
|
|
2124
|
-
*/
|
|
2125
|
-
_historyPush() {
|
|
2126
|
-
this._deleteStyleSelectedCells();
|
|
2127
|
-
this.history.push(false);
|
|
2128
|
-
this._recallStyleSelectedCells();
|
|
2129
|
-
}
|
|
2130
|
-
|
|
2131
|
-
/**
|
|
2132
|
-
* @private
|
|
2133
|
-
* @description Opens the figure.
|
|
2134
|
-
* @param {Node} target - The target figure element.
|
|
2135
|
-
*/
|
|
2136
|
-
_figureOpen(target) {
|
|
2137
|
-
this.figure.open(target, { nonResizing: true, nonSizeInfo: true, nonBorder: true, figureTarget: true, __fileManagerInfo: false });
|
|
2138
|
-
}
|
|
2139
|
-
|
|
2140
|
-
/**
|
|
2141
|
-
* @private
|
|
2142
|
-
* @description Starts resizing a table cell.
|
|
2143
|
-
* @param {HTMLElement} col The column element.
|
|
2144
|
-
* @param {number} startX The starting X position.
|
|
2145
|
-
* @param {number} startWidth The initial width of the column.
|
|
2146
|
-
* @param {boolean} isLeftEdge Whether the resizing is on the left edge.
|
|
2147
|
-
*/
|
|
2148
|
-
_startCellResizing(col, startX, startWidth, isLeftEdge) {
|
|
2149
|
-
this._setResizeLinePosition(this._figure, this._tdElement, this._resizeLinePrev, isLeftEdge);
|
|
2150
|
-
this._resizeLinePrev.style.display = 'block';
|
|
2151
|
-
const prevValue = col.style.width;
|
|
2152
|
-
const nextCol = /** @type {HTMLElement} */ (col.nextElementSibling);
|
|
2153
|
-
const nextColPrevValue = nextCol.style.width;
|
|
2154
|
-
const realWidth = dom.utils.hasClass(this._element, 'se-table-layout-fixed') ? nextColPrevValue : converter.getWidthInPercentage(col);
|
|
2155
|
-
|
|
2156
|
-
if (_DragHandle.get('__dragHandler')) _DragHandle.get('__dragHandler').style.display = 'none';
|
|
2157
|
-
this._addResizeGlobalEvents(
|
|
2158
|
-
this._cellResize.bind(
|
|
2159
|
-
this,
|
|
2160
|
-
col,
|
|
2161
|
-
nextCol,
|
|
2162
|
-
this._figure,
|
|
2163
|
-
this._tdElement,
|
|
2164
|
-
this._resizeLine,
|
|
2165
|
-
isLeftEdge,
|
|
2166
|
-
startX,
|
|
2167
|
-
startWidth,
|
|
2168
|
-
numbers.get(prevValue, CELL_DECIMAL_END),
|
|
2169
|
-
numbers.get(realWidth, CELL_DECIMAL_END),
|
|
2170
|
-
this._element.offsetWidth
|
|
2171
|
-
),
|
|
2172
|
-
() => {
|
|
2173
|
-
this.__removeGlobalEvents();
|
|
2174
|
-
this.history.push(true);
|
|
2175
|
-
this.component.select(this._element, Table.key, { isInput: true });
|
|
2176
|
-
},
|
|
2177
|
-
(e) => {
|
|
2178
|
-
this._stopResize(col, prevValue, 'width', e);
|
|
2179
|
-
this._stopResize(nextCol, nextColPrevValue, 'width', e);
|
|
2180
|
-
}
|
|
2181
|
-
);
|
|
2182
|
-
}
|
|
2183
|
-
|
|
2184
|
-
/**
|
|
2185
|
-
* @private
|
|
2186
|
-
* @description Resizes a table cell.
|
|
2187
|
-
* @param {HTMLElement} col The column element.
|
|
2188
|
-
* @param {HTMLElement} nextCol The next column element.
|
|
2189
|
-
* @param {HTMLElement} figure The table figure element.
|
|
2190
|
-
* @param {HTMLElement} tdEl The table cell element.
|
|
2191
|
-
* @param {HTMLElement} resizeLine The resize line element.
|
|
2192
|
-
* @param {boolean} isLeftEdge Whether the resizing is on the left edge.
|
|
2193
|
-
* @param {number} startX The starting X position.
|
|
2194
|
-
* @param {number} startWidth The initial width of the column.
|
|
2195
|
-
* @param {number} prevWidthPercent The previous width percentage.
|
|
2196
|
-
* @param {number} nextColWidthPercent The next column's width percentage.
|
|
2197
|
-
* @param {number} tableWidth The total width of the table.
|
|
2198
|
-
* @param {MouseEvent} e The mouse event.
|
|
2199
|
-
*/
|
|
2200
|
-
_cellResize(col, nextCol, figure, tdEl, resizeLine, isLeftEdge, startX, startWidth, prevWidthPercent, nextColWidthPercent, tableWidth, e) {
|
|
2201
|
-
const deltaX = e.clientX - startX;
|
|
2202
|
-
const newWidthPx = startWidth + deltaX;
|
|
2203
|
-
const newWidthPercent = (newWidthPx / tableWidth) * 100;
|
|
2204
|
-
|
|
2205
|
-
if (newWidthPercent > 0) {
|
|
2206
|
-
col.style.width = `${newWidthPercent}%`;
|
|
2207
|
-
const delta = prevWidthPercent - newWidthPercent;
|
|
2208
|
-
nextCol.style.width = `${nextColWidthPercent + delta}%`;
|
|
2209
|
-
this._setResizeLinePosition(figure, tdEl, resizeLine, isLeftEdge);
|
|
2210
|
-
}
|
|
2211
|
-
}
|
|
2212
|
-
|
|
2213
|
-
/**
|
|
2214
|
-
* @private
|
|
2215
|
-
* @description Starts resizing a table row.
|
|
2216
|
-
* @param {HTMLElement} row The table row element.
|
|
2217
|
-
* @param {number} startY The starting Y position.
|
|
2218
|
-
* @param {number} startHeight The initial height of the row.
|
|
2219
|
-
*/
|
|
2220
|
-
_startRowResizing(row, startY, startHeight) {
|
|
2221
|
-
this._setResizeRowPosition(this._figure, row, this._resizeLinePrev);
|
|
2222
|
-
this._resizeLinePrev.style.display = 'block';
|
|
2223
|
-
const prevValue = row.style.height;
|
|
2224
|
-
|
|
2225
|
-
this._addResizeGlobalEvents(
|
|
2226
|
-
this._rowResize.bind(this, row, this._figure, this._resizeLine, startY, startHeight),
|
|
2227
|
-
() => {
|
|
2228
|
-
this.__removeGlobalEvents();
|
|
2229
|
-
this.history.push(true);
|
|
2230
|
-
},
|
|
2231
|
-
this._stopResize.bind(this, row, prevValue, 'height')
|
|
2232
|
-
);
|
|
2233
|
-
}
|
|
2234
|
-
|
|
2235
|
-
/**
|
|
2236
|
-
* @private
|
|
2237
|
-
* @description Resizes a table row.
|
|
2238
|
-
* @param {HTMLElement} row The table row element.
|
|
2239
|
-
* @param {HTMLElement} figure The table figure element.
|
|
2240
|
-
* @param {HTMLElement} resizeLine The resize line element.
|
|
2241
|
-
* @param {number} startY The starting Y position.
|
|
2242
|
-
* @param {number} startHeight The initial height of the row.
|
|
2243
|
-
* @param {MouseEvent} e The mouse event.
|
|
2244
|
-
*/
|
|
2245
|
-
_rowResize(row, figure, resizeLine, startY, startHeight, e) {
|
|
2246
|
-
const deltaY = e.clientY - startY;
|
|
2247
|
-
const newHeightPx = startHeight + deltaY;
|
|
2248
|
-
row.style.height = `${newHeightPx}px`;
|
|
2249
|
-
this._setResizeRowPosition(figure, row, resizeLine);
|
|
2250
|
-
}
|
|
2251
|
-
|
|
2252
|
-
/**
|
|
2253
|
-
* @private
|
|
2254
|
-
* @description Starts resizing the table figure.
|
|
2255
|
-
* @param {number} startX The starting X position.
|
|
2256
|
-
* @param {boolean} isLeftEdge Whether the resizing is on the left edge.
|
|
2257
|
-
*/
|
|
2258
|
-
_startFigureResizing(startX, isLeftEdge) {
|
|
2259
|
-
const figure = this._figure;
|
|
2260
|
-
this._setResizeLinePosition(figure, figure, this._resizeLinePrev, isLeftEdge);
|
|
2261
|
-
this._resizeLinePrev.style.display = 'block';
|
|
2262
|
-
const realWidth = converter.getWidthInPercentage(figure);
|
|
2263
|
-
|
|
2264
|
-
if (_DragHandle.get('__dragHandler')) _DragHandle.get('__dragHandler').style.display = 'none';
|
|
2265
|
-
this._addResizeGlobalEvents(
|
|
2266
|
-
this._figureResize.bind(this, figure, this._resizeLine, isLeftEdge, startX, figure.offsetWidth, numbers.get(realWidth, CELL_DECIMAL_END)),
|
|
2267
|
-
() => {
|
|
2268
|
-
this.__removeGlobalEvents();
|
|
2269
|
-
// figure reopen
|
|
2270
|
-
this.component.select(this._element, Table.key, { isInput: true });
|
|
2271
|
-
},
|
|
2272
|
-
this._stopResize.bind(this, figure, figure.style.width, 'width')
|
|
2273
|
-
);
|
|
2274
|
-
}
|
|
2275
|
-
|
|
2276
|
-
/**
|
|
2277
|
-
* @private
|
|
2278
|
-
* @description Resizes the table figure.
|
|
2279
|
-
* @param {HTMLElement} figure The table figure element.
|
|
2280
|
-
* @param {HTMLElement} resizeLine The resize line element.
|
|
2281
|
-
* @param {boolean} isLeftEdge Whether the resizing is on the left edge.
|
|
2282
|
-
* @param {number} startX The starting X position.
|
|
2283
|
-
* @param {number} startWidth The initial width of the figure.
|
|
2284
|
-
* @param {number} constNum A constant number used for width calculation.
|
|
2285
|
-
* @param {MouseEvent} e The mouse event.
|
|
2286
|
-
*/
|
|
2287
|
-
_figureResize(figure, resizeLine, isLeftEdge, startX, startWidth, constNum, e) {
|
|
2288
|
-
const deltaX = isLeftEdge ? startX - e.clientX : e.clientX - startX;
|
|
2289
|
-
const newWidthPx = startWidth + deltaX;
|
|
2290
|
-
const newWidthPercent = (newWidthPx / startWidth) * constNum;
|
|
2291
|
-
|
|
2292
|
-
if (newWidthPercent > 0) {
|
|
2293
|
-
figure.style.width = `${newWidthPercent}%`;
|
|
2294
|
-
this._setResizeLinePosition(figure, figure, resizeLine, isLeftEdge);
|
|
2295
|
-
}
|
|
2296
|
-
}
|
|
2297
|
-
|
|
2298
|
-
/**
|
|
2299
|
-
* @private
|
|
2300
|
-
* @description Sets the resize line position.
|
|
2301
|
-
* @param {HTMLElement} figure The table figure element.
|
|
2302
|
-
* @param {HTMLElement} target The target element.
|
|
2303
|
-
* @param {HTMLElement} resizeLine The resize line element.
|
|
2304
|
-
* @param {boolean} isLeftEdge Whether the resizing is on the left edge.
|
|
2305
|
-
*/
|
|
2306
|
-
_setResizeLinePosition(figure, target, resizeLine, isLeftEdge) {
|
|
2307
|
-
const tdOffset = this.offset.getLocal(target);
|
|
2308
|
-
const tableOffset = this.offset.getLocal(figure);
|
|
2309
|
-
resizeLine.style.left = `${tdOffset.left + (isLeftEdge ? 0 : target.offsetWidth)}px`;
|
|
2310
|
-
resizeLine.style.top = `${tableOffset.top}px`;
|
|
2311
|
-
resizeLine.style.height = `${figure.offsetHeight}px`;
|
|
2312
|
-
}
|
|
2313
|
-
|
|
2314
|
-
/**
|
|
2315
|
-
* @private
|
|
2316
|
-
* @description Sets the resize row position.
|
|
2317
|
-
* @param {HTMLElement} figure The table figure element.
|
|
2318
|
-
* @param {HTMLElement} target The target row element.
|
|
2319
|
-
* @param {HTMLElement} resizeLine The resize line element.
|
|
2320
|
-
*/
|
|
2321
|
-
_setResizeRowPosition(figure, target, resizeLine) {
|
|
2322
|
-
const rowOffset = this.offset.getLocal(target);
|
|
2323
|
-
const tableOffset = this.offset.getLocal(figure);
|
|
2324
|
-
resizeLine.style.top = `${rowOffset.top + target.offsetHeight}px`;
|
|
2325
|
-
resizeLine.style.left = `${tableOffset.left}px`;
|
|
2326
|
-
resizeLine.style.width = `${figure.offsetWidth}px`;
|
|
2327
|
-
}
|
|
2328
|
-
|
|
2329
|
-
/**
|
|
2330
|
-
* @private
|
|
2331
|
-
* @description Stops resizing the table.
|
|
2332
|
-
* @param {HTMLElement} target The target element.
|
|
2333
|
-
* @param {string} prevValue The previous style value.
|
|
2334
|
-
* @param {string} styleProp The CSS property being changed.
|
|
2335
|
-
* @param {KeyboardEvent} e The keyboard event.
|
|
2336
|
-
*/
|
|
2337
|
-
_stopResize(target, prevValue, styleProp, e) {
|
|
2338
|
-
if (!keyCodeMap.isEsc(e.code)) return;
|
|
2339
|
-
this.__removeGlobalEvents();
|
|
2340
|
-
target.style[styleProp] = prevValue;
|
|
2341
|
-
// figure reopen
|
|
2342
|
-
if (styleProp === 'width') {
|
|
2343
|
-
this.component.select(this._element, Table.key, { isInput: true });
|
|
2344
|
-
}
|
|
2345
|
-
}
|
|
2346
|
-
|
|
2347
|
-
/**
|
|
2348
|
-
* @private
|
|
2349
|
-
* @description Deletes styles from selected table cells.
|
|
2350
|
-
*/
|
|
2351
|
-
_deleteStyleSelectedCells() {
|
|
2352
|
-
dom.utils.removeClass([this._fixedCell, this._selectedCell], 'se-selected-cell-focus');
|
|
2353
|
-
const table = this._fixedCell?.closest('table');
|
|
2354
|
-
if (table) {
|
|
2355
|
-
const selectedCells = table.querySelectorAll('.se-selected-table-cell');
|
|
2356
|
-
for (let i = 0, len = selectedCells.length; i < len; i++) {
|
|
2357
|
-
dom.utils.removeClass(selectedCells[i], 'se-selected-table-cell');
|
|
2358
|
-
}
|
|
2359
|
-
}
|
|
2360
|
-
}
|
|
2361
|
-
|
|
2362
|
-
/**
|
|
2363
|
-
* @private
|
|
2364
|
-
* @description Restores styles for selected table cells.
|
|
2365
|
-
*/
|
|
2366
|
-
_recallStyleSelectedCells() {
|
|
2367
|
-
if (this._selectedCells) {
|
|
2368
|
-
const selectedCells = this._selectedCells;
|
|
2369
|
-
for (let i = 0, len = selectedCells.length; i < len; i++) {
|
|
2370
|
-
dom.utils.addClass(selectedCells[i], 'se-selected-table-cell');
|
|
2371
|
-
}
|
|
2372
|
-
}
|
|
2373
|
-
}
|
|
2374
|
-
|
|
2375
|
-
/**
|
|
2376
|
-
* @private
|
|
2377
|
-
* @description Adds global event listeners for resizing.
|
|
2378
|
-
* @param {(...args: *) => void} resizeFn The function handling the resize event.
|
|
2379
|
-
* @param {(...args: *) => void} stopFn The function handling the stop event.
|
|
2380
|
-
* @param {(...args: *) => void} keyDownFn The function handling the keydown event.
|
|
2381
|
-
*/
|
|
2382
|
-
_addResizeGlobalEvents(resizeFn, stopFn, keyDownFn) {
|
|
2383
|
-
this.__globalEvents.resize = this.eventManager.addGlobalEvent('mousemove', resizeFn, false);
|
|
2384
|
-
this.__globalEvents.resizeStop = this.eventManager.addGlobalEvent('mouseup', stopFn, false);
|
|
2385
|
-
this.__globalEvents.resizeKeyDown = this.eventManager.addGlobalEvent('keydown', keyDownFn, false);
|
|
2386
|
-
this._resizing = true;
|
|
2387
|
-
}
|
|
2388
|
-
|
|
2389
|
-
/**
|
|
2390
|
-
* @private
|
|
2391
|
-
* @description Enables or disables editor mode.
|
|
2392
|
-
* @param {boolean} enabled Whether to enable or disable the editor.
|
|
2393
|
-
*/
|
|
2394
|
-
_toggleEditor(enabled) {
|
|
2395
|
-
const wysiwyg = this.editor.frameContext.get('wysiwyg');
|
|
2396
|
-
wysiwyg.setAttribute('contenteditable', enabled.toString());
|
|
2397
|
-
if (enabled) dom.utils.removeClass(wysiwyg, 'se-disabled');
|
|
2398
|
-
else dom.utils.addClass(wysiwyg, 'se-disabled');
|
|
2399
|
-
}
|
|
2400
|
-
|
|
2401
|
-
/**
|
|
2402
|
-
* @private
|
|
2403
|
-
* @description Updates control properties.
|
|
2404
|
-
* @param {string} type The type of control property.
|
|
2405
|
-
*/
|
|
2406
|
-
_setCtrlProps(type) {
|
|
2407
|
-
this._typeCache = type;
|
|
2408
|
-
const isTable = type === 'table';
|
|
2409
|
-
const targets = isTable ? [this._element] : this._selectedCells;
|
|
2410
|
-
if (!targets || targets.length === 0) return;
|
|
2411
|
-
|
|
2412
|
-
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;
|
|
2413
|
-
const { border, backgroundColor, color, textAlign, verticalAlign, fontWeight, textDecoration, fontStyle } = _w.getComputedStyle(targets[0]);
|
|
2414
|
-
const cellBorder = this._getBorderStyle(border);
|
|
2415
|
-
|
|
2416
|
-
/** @type {HTMLElement} */ (cell_alignment.querySelector('[data-value="justify"]')).style.display = isTable ? 'none' : '';
|
|
2417
|
-
cell_alignment_table_text.style.display = isTable ? '' : 'none';
|
|
2418
|
-
if (isTable) cell_alignment_vertical.style.display = 'none';
|
|
2419
|
-
else cell_alignment_vertical.style.display = '';
|
|
2420
|
-
|
|
2421
|
-
let b_color = converter.rgb2hex(cellBorder.c),
|
|
2422
|
-
b_style = cellBorder.s,
|
|
2423
|
-
b_width = cellBorder.w,
|
|
2424
|
-
backColor = converter.rgb2hex(backgroundColor),
|
|
2425
|
-
fontColor = converter.rgb2hex(color),
|
|
2426
|
-
bold = /.+/.test(fontWeight),
|
|
2427
|
-
underline = /underline/i.test(textDecoration),
|
|
2428
|
-
strike = /line-through/i.test(textDecoration),
|
|
2429
|
-
italic = /italic/i.test(fontStyle),
|
|
2430
|
-
align = isTable ? this._figure?.style.float : textAlign,
|
|
2431
|
-
align_v = verticalAlign;
|
|
2432
|
-
this._propsCache = [];
|
|
2433
|
-
|
|
2434
|
-
const tempColorStyles = _w.getComputedStyle(this.eventManager.__focusTemp);
|
|
2435
|
-
for (let i = 0, t, isBreak; (t = targets[i]); i++) {
|
|
2436
|
-
// eslint-disable-next-line no-shadow
|
|
2437
|
-
const { cssText, border, backgroundColor, color, textAlign, verticalAlign, fontWeight, textDecoration, fontStyle } = t.style;
|
|
2438
|
-
this._propsCache.push([t, cssText]);
|
|
2439
|
-
if (isBreak) continue;
|
|
2440
|
-
|
|
2441
|
-
const { c, s, w } = this._getBorderStyle(border);
|
|
2442
|
-
|
|
2443
|
-
// colors
|
|
2444
|
-
let hexBackColor = backgroundColor;
|
|
2445
|
-
let hexColor = color;
|
|
2446
|
-
if (hexBackColor) {
|
|
2447
|
-
this.eventManager.__focusTemp.style.backgroundColor = hexBackColor;
|
|
2448
|
-
hexBackColor = tempColorStyles.backgroundColor;
|
|
2449
|
-
}
|
|
2450
|
-
if (hexColor) {
|
|
2451
|
-
this.eventManager.__focusTemp.style.color = hexColor;
|
|
2452
|
-
hexColor = tempColorStyles.color;
|
|
2453
|
-
}
|
|
2454
|
-
|
|
2455
|
-
if (b_color && cellBorder.c !== c) b_color = '';
|
|
2456
|
-
if (b_style && cellBorder.s !== s) b_style = '';
|
|
2457
|
-
if (b_width && cellBorder.w !== w) b_width = '';
|
|
2458
|
-
if (backColor !== converter.rgb2hex(hexBackColor)) backColor = '';
|
|
2459
|
-
if (fontColor !== converter.rgb2hex(hexColor)) fontColor = '';
|
|
2460
|
-
if (align !== (isTable ? this._figure?.style.float : textAlign)) align = '';
|
|
2461
|
-
if (align_v && align_v !== verticalAlign) align_v = '';
|
|
2462
|
-
if (bold && bold !== /.+/.test(fontWeight)) bold = false;
|
|
2463
|
-
if (underline && underline !== /underline/i.test(textDecoration)) underline = false;
|
|
2464
|
-
if (strike && strike !== /line-through/i.test(textDecoration)) strike = false;
|
|
2465
|
-
if (italic && italic !== /italic/i.test(fontStyle)) italic = false;
|
|
2466
|
-
if (!b_color || !b_style || !b_width || !backColor || !fontColor) {
|
|
2467
|
-
isBreak = true;
|
|
2468
|
-
}
|
|
2469
|
-
}
|
|
2470
|
-
|
|
2471
|
-
// border - format
|
|
2472
|
-
border_format.firstElementChild.innerHTML = this.icons[BORDER_FORMATS[targets.length === 1 ? 'outside' : 'all']];
|
|
2473
|
-
border_format.setAttribute('se-border-format', 'all');
|
|
2474
|
-
dom.utils.removeClass(border_format, 'active');
|
|
2475
|
-
|
|
2476
|
-
// border - styles
|
|
2477
|
-
b_style = b_style || BORDER_LIST[0];
|
|
2478
|
-
border_style.textContent = b_style;
|
|
2479
|
-
border_color.style.borderColor = border_color.value = b_color;
|
|
2480
|
-
border_width.value = b_width;
|
|
2481
|
-
this._disableBorderProps(b_style === BORDER_LIST[0]);
|
|
2482
|
-
|
|
2483
|
-
// back, font color
|
|
2484
|
-
back_color.value = back_color.style.borderColor = backColor;
|
|
2485
|
-
font_color.value = font_color.style.borderColor = fontColor;
|
|
2486
|
-
|
|
2487
|
-
// font style
|
|
2488
|
-
if (bold) dom.utils.addClass(font_bold, 'on');
|
|
2489
|
-
if (underline) dom.utils.addClass(font_underline, 'on');
|
|
2490
|
-
if (strike) dom.utils.addClass(font_strike, 'on');
|
|
2491
|
-
if (italic) dom.utils.addClass(font_italic, 'on');
|
|
2492
|
-
|
|
2493
|
-
// align
|
|
2494
|
-
this._setAlignProps(cell_alignment, (this._propsAlignCache = align), true);
|
|
2495
|
-
this._setAlignProps(cell_alignment_vertical, (this._propsVerticalAlignCache = align_v), true);
|
|
2496
|
-
}
|
|
2497
|
-
|
|
2498
|
-
/**
|
|
2499
|
-
* @private
|
|
2500
|
-
* @description Sets text alignment properties.
|
|
2501
|
-
* @param {Element} el The element to apply alignment to.
|
|
2502
|
-
* @param {string} align The alignment value.
|
|
2503
|
-
* @param {boolean} reset Whether to reset the alignment.
|
|
2504
|
-
*/
|
|
2505
|
-
_setAlignProps(el, align, reset) {
|
|
2506
|
-
dom.utils.removeClass(el.querySelectorAll('button'), 'on');
|
|
2507
|
-
|
|
2508
|
-
if (!reset && el.getAttribute('se-cell-align') === align) {
|
|
2509
|
-
el.setAttribute('se-cell-align', '');
|
|
2510
|
-
return;
|
|
2511
|
-
}
|
|
2512
|
-
|
|
2513
|
-
dom.utils.addClass(el.querySelector(`[data-value="${align}"]`), 'on');
|
|
2514
|
-
el.setAttribute('se-cell-align', align);
|
|
2515
|
-
}
|
|
2516
|
-
|
|
2517
|
-
/**
|
|
2518
|
-
* @private
|
|
2519
|
-
* @description Disables or enables border properties.
|
|
2520
|
-
* @param {boolean} disabled Whether to disable or enable border properties.
|
|
2521
|
-
*/
|
|
2522
|
-
_disableBorderProps(disabled) {
|
|
2523
|
-
const { border_color, border_width, palette_border_button } = this.propTargets;
|
|
2524
|
-
if (disabled) {
|
|
2525
|
-
border_color.disabled = true;
|
|
2526
|
-
border_width.disabled = true;
|
|
2527
|
-
palette_border_button.disabled = true;
|
|
2528
|
-
border_width.disabled = true;
|
|
2529
|
-
} else {
|
|
2530
|
-
border_color.disabled = false;
|
|
2531
|
-
border_width.disabled = false;
|
|
2532
|
-
palette_border_button.disabled = false;
|
|
2533
|
-
border_width.disabled = false;
|
|
2534
|
-
}
|
|
2535
|
-
}
|
|
2536
|
-
|
|
2537
|
-
/**
|
|
2538
|
-
* @private
|
|
2539
|
-
* @description Gets the border style.
|
|
2540
|
-
* @param {string} borderStyle The border style string.
|
|
2541
|
-
* @returns {{w: string, s: string, c: string}} The parsed border style object.
|
|
2542
|
-
* - w: The border width.
|
|
2543
|
-
* - s: The border style.
|
|
2544
|
-
* - c: The border color.
|
|
2545
|
-
*/
|
|
2546
|
-
_getBorderStyle(borderStyle) {
|
|
2547
|
-
const parts = borderStyle.split(/\s(?![^()]*\))/);
|
|
2548
|
-
let w = '',
|
|
2549
|
-
s = '',
|
|
2550
|
-
c = '';
|
|
2551
|
-
|
|
2552
|
-
if (parts.length === 3) {
|
|
2553
|
-
w = parts[0];
|
|
2554
|
-
s = parts[1];
|
|
2555
|
-
c = parts[2];
|
|
2556
|
-
} else if (parts.length === 2) {
|
|
2557
|
-
if (/\d/.test(parts[0])) {
|
|
2558
|
-
w = parts[0];
|
|
2559
|
-
s = parts[1];
|
|
2560
|
-
} else {
|
|
2561
|
-
s = parts[0];
|
|
2562
|
-
c = parts[1];
|
|
2563
|
-
}
|
|
2564
|
-
} else if (parts.length === 1) {
|
|
2565
|
-
if (/\d/.test(parts[0])) {
|
|
2566
|
-
w = parts[0];
|
|
2567
|
-
} else {
|
|
2568
|
-
s = parts[0];
|
|
2569
|
-
}
|
|
2570
|
-
}
|
|
2571
|
-
|
|
2572
|
-
return { w, s, c: converter.rgb2hex(c) };
|
|
2573
|
-
}
|
|
2574
|
-
|
|
2575
|
-
/**
|
|
2576
|
-
* @private
|
|
2577
|
-
* @description Applies properties to table cells.
|
|
2578
|
-
* @param {HTMLButtonElement} target The target element.
|
|
2579
|
-
*/
|
|
2580
|
-
_submitProps(target) {
|
|
2581
|
-
try {
|
|
2582
|
-
target.disabled = true;
|
|
2583
|
-
|
|
2584
|
-
const isTable = this.controller_table.form.contains(this.controller_props.currentTarget);
|
|
2585
|
-
const targets = isTable ? [this._element] : this._selectedCells;
|
|
2586
|
-
const tr = /** @type {HTMLTableCellElement} */ (targets[0]);
|
|
2587
|
-
const trStyles = _w.getComputedStyle(tr);
|
|
2588
|
-
const { border_format, border_color, border_style, border_width, back_color, font_color, cell_alignment, cell_alignment_vertical } = this.propTargets;
|
|
2589
|
-
|
|
2590
|
-
const borderFormat = border_format.getAttribute('se-border-format') || '';
|
|
2591
|
-
const hasFormat = borderFormat !== 'all';
|
|
2592
|
-
const borderStyle = (border_style.textContent === 'none' ? '' : border_style.textContent) || '';
|
|
2593
|
-
const isNoneFormat = borderFormat === 'none' || !borderStyle;
|
|
2594
|
-
|
|
2595
|
-
const cellAlignment = cell_alignment.getAttribute('se-cell-align') || '';
|
|
2596
|
-
const cellAlignmentVertical = cell_alignment_vertical.getAttribute('se-cell-align') || '';
|
|
2597
|
-
const borderColor = isNoneFormat ? '' : border_color.value.trim() || trStyles.borderColor;
|
|
2598
|
-
let borderWidth = isNoneFormat ? '' : border_width.value.trim() || trStyles.borderWidth;
|
|
2599
|
-
borderWidth = borderWidth + (numbers.is(borderWidth) ? DEFAULT_BORDER_UNIT : '');
|
|
2600
|
-
const backColor = back_color.value.trim();
|
|
2601
|
-
const fontColor = font_color.value.trim();
|
|
2602
|
-
const hasBorder = hasFormat && !isNoneFormat && borderWidth;
|
|
2603
|
-
const borderCss = `${borderWidth} ${borderStyle} ${borderColor}`;
|
|
2604
|
-
const cells = {
|
|
2605
|
-
left: [],
|
|
2606
|
-
top: [],
|
|
2607
|
-
right: [],
|
|
2608
|
-
bottom: [],
|
|
2609
|
-
middle: [],
|
|
2610
|
-
all: null
|
|
2611
|
-
};
|
|
2612
|
-
|
|
2613
|
-
if (!isTable) {
|
|
2614
|
-
const trRow = /** @type {HTMLTableRowElement} */ (tr.parentElement);
|
|
2615
|
-
// --- target cells roof
|
|
2616
|
-
let { rs, re, cs, ce } = this._ref || {
|
|
2617
|
-
rs: trRow.rowIndex || 0,
|
|
2618
|
-
re: trRow.rowIndex || 0,
|
|
2619
|
-
cs: tr.cellIndex || 0,
|
|
2620
|
-
ce: tr.cellIndex || 0
|
|
2621
|
-
};
|
|
2622
|
-
const mergeInfo = new Array(re - rs + 1).fill(0).map(() => new Array(ce - cs + 1).fill(0));
|
|
2623
|
-
const cellStartIndex = cs;
|
|
2624
|
-
re -= rs;
|
|
2625
|
-
rs -= rs;
|
|
2626
|
-
ce -= cs;
|
|
2627
|
-
cs -= cs;
|
|
2628
|
-
let prevRow = /** @type {HTMLElement} */ (trRow);
|
|
2629
|
-
for (let i = 0, cellCnt = 0, len = targets.length, e, es, rowIndex = 0, cellIndex, colspan, rowspan; i < len; i++, cellCnt++) {
|
|
2630
|
-
e = /** @type {HTMLTableCellElement} */ (targets[i]);
|
|
2631
|
-
colspan = e.colSpan;
|
|
2632
|
-
rowspan = e.rowSpan;
|
|
2633
|
-
cellIndex = e.cellIndex - cellStartIndex;
|
|
2634
|
-
|
|
2635
|
-
if (prevRow !== e.parentElement) {
|
|
2636
|
-
rowIndex++;
|
|
2637
|
-
cellCnt = 0;
|
|
2638
|
-
prevRow = e.parentElement;
|
|
2639
|
-
}
|
|
2640
|
-
|
|
2641
|
-
let c = 0;
|
|
2642
|
-
while (c <= cellIndex) {
|
|
2643
|
-
cellIndex += mergeInfo[rowIndex][c] || 0;
|
|
2644
|
-
c++;
|
|
2645
|
-
}
|
|
2646
|
-
|
|
2647
|
-
/* eslint-disable @typescript-eslint/no-unused-vars */
|
|
2648
|
-
try {
|
|
2649
|
-
if (rowspan > 1) {
|
|
2650
|
-
const rowspanNum = rowspan - 1;
|
|
2651
|
-
for (let r = rowIndex; r <= rowIndex + rowspanNum; r++) {
|
|
2652
|
-
mergeInfo[r][cellIndex] += colspan - (rowIndex === r ? 1 : 0);
|
|
2653
|
-
}
|
|
2654
|
-
} else if (colspan > 1) {
|
|
2655
|
-
mergeInfo[rowIndex][cellIndex] += colspan - 1;
|
|
2656
|
-
}
|
|
2657
|
-
} catch (err) {
|
|
2658
|
-
// ignore error
|
|
2659
|
-
}
|
|
2660
|
-
/* eslint-disable @typescript-eslint/no-unused-vars */
|
|
2661
|
-
|
|
2662
|
-
const isBottom = rowIndex + rowspan - 1 === re;
|
|
2663
|
-
if (rowIndex === rs) cells.top.push(e);
|
|
2664
|
-
if (rowIndex === re || isBottom) cells.bottom.push(e);
|
|
2665
|
-
if (cellIndex === cs) cells.left.push(e);
|
|
2666
|
-
if (cellIndex === ce || cellIndex + colspan - 1 === ce) cells.right.push(e);
|
|
2667
|
-
if (!isBottom && rowIndex !== rs && rowIndex !== re && cellIndex !== cs && cellIndex !== ce) cells.middle.push(e);
|
|
2668
|
-
|
|
2669
|
-
// --- set styles
|
|
2670
|
-
es = e.style;
|
|
2671
|
-
// alignment
|
|
2672
|
-
es.textAlign = cellAlignment;
|
|
2673
|
-
es.verticalAlign = cellAlignmentVertical;
|
|
2674
|
-
// back
|
|
2675
|
-
es.backgroundColor = backColor;
|
|
2676
|
-
// font
|
|
2677
|
-
es.color = fontColor;
|
|
2678
|
-
// font style
|
|
2679
|
-
this._setFontStyle(es);
|
|
2680
|
-
// border
|
|
2681
|
-
if (hasBorder) continue;
|
|
2682
|
-
// border - all || none
|
|
2683
|
-
if (isNoneFormat) {
|
|
2684
|
-
es.border = es.borderLeft = es.borderTop = es.borderRight = es.borderBottom = '';
|
|
2685
|
-
} else {
|
|
2686
|
-
es.border = borderCss;
|
|
2687
|
-
}
|
|
2688
|
-
}
|
|
2689
|
-
|
|
2690
|
-
if (cells.middle.length === 0) {
|
|
2691
|
-
cells.middle = targets;
|
|
2692
|
-
}
|
|
2693
|
-
} else {
|
|
2694
|
-
// -- table styles
|
|
2695
|
-
const es = tr.style;
|
|
2696
|
-
// alignment
|
|
2697
|
-
if (this._figure) {
|
|
2698
|
-
this._figure.style.float = cellAlignment;
|
|
2699
|
-
this._figure.style.verticalAlign = cellAlignmentVertical;
|
|
2700
|
-
}
|
|
2701
|
-
// back
|
|
2702
|
-
es.backgroundColor = backColor;
|
|
2703
|
-
// font
|
|
2704
|
-
es.color = fontColor;
|
|
2705
|
-
// font style
|
|
2706
|
-
this._setFontStyle(es);
|
|
2707
|
-
// border
|
|
2708
|
-
if (!hasBorder) {
|
|
2709
|
-
// border - all || none
|
|
2710
|
-
if (isNoneFormat) {
|
|
2711
|
-
es.border = es.borderLeft = es.borderTop = es.borderRight = es.borderBottom = '';
|
|
2712
|
-
} else {
|
|
2713
|
-
es.border = borderCss;
|
|
2714
|
-
}
|
|
2715
|
-
}
|
|
2716
|
-
|
|
2717
|
-
cells.left = cells.top = cells.right = cells.bottom = targets;
|
|
2718
|
-
}
|
|
2719
|
-
|
|
2720
|
-
cells.all = targets;
|
|
2721
|
-
|
|
2722
|
-
// border format
|
|
2723
|
-
if (hasBorder) {
|
|
2724
|
-
this._setBorderStyles(cells, borderFormat, borderCss);
|
|
2725
|
-
}
|
|
2726
|
-
|
|
2727
|
-
this._historyPush();
|
|
2728
|
-
|
|
2729
|
-
// set cells style
|
|
2730
|
-
this.controller_props.close();
|
|
2731
|
-
if (this._tdElement) {
|
|
2732
|
-
this._recallStyleSelectedCells();
|
|
2733
|
-
this.setCellInfo(this._tdElement, true);
|
|
2734
|
-
dom.utils.addClass(this._tdElement, 'se-selected-cell-focus');
|
|
2735
|
-
}
|
|
2736
|
-
} catch (err) {
|
|
2737
|
-
console.warn('[SUNEDITOR.plugins.table.setProps.error]', err);
|
|
2738
|
-
} finally {
|
|
2739
|
-
target.disabled = false;
|
|
2740
|
-
}
|
|
2741
|
-
}
|
|
2742
|
-
|
|
2743
|
-
/**
|
|
2744
|
-
* @private
|
|
2745
|
-
* @description Sets font styles.
|
|
2746
|
-
* @param {CSSStyleDeclaration} styles The style object to modify.
|
|
2747
|
-
*/
|
|
2748
|
-
_setFontStyle(styles) {
|
|
2749
|
-
const { font_bold, font_italic, font_strike, font_underline } = this.propTargets;
|
|
2750
|
-
styles.fontWeight = dom.utils.hasClass(font_bold, 'on') ? 'bold' : '';
|
|
2751
|
-
styles.fontStyle = dom.utils.hasClass(font_italic, 'on') ? 'italic' : '';
|
|
2752
|
-
styles.textDecoration = ((dom.utils.hasClass(font_strike, 'on') ? 'line-through ' : '') + (dom.utils.hasClass(font_underline, 'on') ? 'underline' : '')).trim();
|
|
2753
|
-
}
|
|
2754
|
-
|
|
2755
|
-
/**
|
|
2756
|
-
* @private
|
|
2757
|
-
* @description Sets border format and styles.
|
|
2758
|
-
* @param {{left: Node[], top: Node[], right: Node[], bottom: Node[], all: Node[]}} cells The table cells categorized by border positions.
|
|
2759
|
-
* @param {string} borderKey Border style ("all"|"inside"|"horizon"|"vertical"|"outside"|"left"|"top"|"right"|"bottom")
|
|
2760
|
-
* @param {string} s The border style value.
|
|
2761
|
-
*/
|
|
2762
|
-
_setBorderStyles(cells, borderKey, s) {
|
|
2763
|
-
const { left, top, right, bottom, all } = cells;
|
|
2764
|
-
switch (borderKey) {
|
|
2765
|
-
case 'inside':
|
|
2766
|
-
if (all.length === 1) return;
|
|
2767
|
-
dom.utils.setStyle(
|
|
2768
|
-
all.filter((c) => !bottom.includes(c)),
|
|
2769
|
-
BORDER_NS.b,
|
|
2770
|
-
s
|
|
2771
|
-
);
|
|
2772
|
-
dom.utils.setStyle(
|
|
2773
|
-
all.filter((c) => !right.includes(c)),
|
|
2774
|
-
BORDER_NS.r,
|
|
2775
|
-
s
|
|
2776
|
-
);
|
|
2777
|
-
break;
|
|
2778
|
-
case 'horizon':
|
|
2779
|
-
if (all.length === 1) return;
|
|
2780
|
-
dom.utils.setStyle(
|
|
2781
|
-
all.filter((c) => !bottom.includes(c)),
|
|
2782
|
-
BORDER_NS.b,
|
|
2783
|
-
s
|
|
2784
|
-
);
|
|
2785
|
-
break;
|
|
2786
|
-
case 'vertical':
|
|
2787
|
-
if (all.length === 1) return;
|
|
2788
|
-
dom.utils.setStyle(
|
|
2789
|
-
all.filter((c) => !right.includes(c)),
|
|
2790
|
-
BORDER_NS.r,
|
|
2791
|
-
s
|
|
2792
|
-
);
|
|
2793
|
-
break;
|
|
2794
|
-
case 'outside':
|
|
2795
|
-
dom.utils.setStyle(left, BORDER_NS.l, s);
|
|
2796
|
-
dom.utils.setStyle(top, BORDER_NS.t, s);
|
|
2797
|
-
dom.utils.setStyle(right, BORDER_NS.r, s);
|
|
2798
|
-
dom.utils.setStyle(bottom, BORDER_NS.b, s);
|
|
2799
|
-
break;
|
|
2800
|
-
case 'left':
|
|
2801
|
-
dom.utils.setStyle(left, BORDER_NS.l, s);
|
|
2802
|
-
break;
|
|
2803
|
-
case 'top':
|
|
2804
|
-
dom.utils.setStyle(top, BORDER_NS.t, s);
|
|
2805
|
-
break;
|
|
2806
|
-
case 'right':
|
|
2807
|
-
dom.utils.setStyle(right, BORDER_NS.r, s);
|
|
2808
|
-
break;
|
|
2809
|
-
case 'bottom':
|
|
2810
|
-
dom.utils.setStyle(bottom, BORDER_NS.b, s);
|
|
2811
|
-
break;
|
|
2812
|
-
}
|
|
2813
|
-
}
|
|
2814
|
-
|
|
2815
|
-
/**
|
|
2816
|
-
* @private
|
|
2817
|
-
* @description Selects multiple table cells and applies selection styles.
|
|
2818
|
-
* @param {Node} startCell The first cell in the selection.
|
|
2819
|
-
* @param {Node} endCell The last cell in the selection.
|
|
2820
|
-
*/
|
|
2821
|
-
_setMultiCells(startCell, endCell) {
|
|
2822
|
-
const rows = this._selectedTable.rows;
|
|
2823
|
-
this._deleteStyleSelectedCells();
|
|
2824
|
-
|
|
2825
|
-
dom.utils.addClass(startCell, 'se-selected-table-cell');
|
|
2826
|
-
|
|
2827
|
-
if (startCell === endCell) {
|
|
2828
|
-
if (!this._shift) return;
|
|
2829
|
-
}
|
|
2830
|
-
|
|
2831
|
-
let findSelectedCell = true;
|
|
2832
|
-
let spanIndex = [];
|
|
2833
|
-
let rowSpanArr = [];
|
|
2834
|
-
const ref = (this._ref = { _i: 0, cs: null, ce: null, rs: null, re: null });
|
|
2835
|
-
|
|
2836
|
-
for (let i = 0, len = rows.length, cells, colSpan; i < len; i++) {
|
|
2837
|
-
cells = rows[i].cells;
|
|
2838
|
-
colSpan = 0;
|
|
2839
|
-
|
|
2840
|
-
for (let c = 0, cLen = cells.length, cell, logcalIndex, cs, rs; c < cLen; c++) {
|
|
2841
|
-
cell = cells[c];
|
|
2842
|
-
cs = cell.colSpan - 1;
|
|
2843
|
-
rs = cell.rowSpan - 1;
|
|
2844
|
-
logcalIndex = c + colSpan;
|
|
2845
|
-
|
|
2846
|
-
if (spanIndex.length > 0) {
|
|
2847
|
-
for (let r = 0, arr; r < spanIndex.length; r++) {
|
|
2848
|
-
arr = spanIndex[r];
|
|
2849
|
-
if (arr.row > i) continue;
|
|
2850
|
-
if (logcalIndex >= arr.index) {
|
|
2851
|
-
colSpan += arr.cs;
|
|
2852
|
-
logcalIndex += arr.cs;
|
|
2853
|
-
arr.rs -= 1;
|
|
2854
|
-
arr.row = i + 1;
|
|
2855
|
-
if (arr.rs < 1) {
|
|
2856
|
-
spanIndex.splice(r, 1);
|
|
2857
|
-
r--;
|
|
2858
|
-
}
|
|
2859
|
-
} else if (c === cLen - 1) {
|
|
2860
|
-
arr.rs -= 1;
|
|
2861
|
-
arr.row = i + 1;
|
|
2862
|
-
if (arr.rs < 1) {
|
|
2863
|
-
spanIndex.splice(r, 1);
|
|
2864
|
-
r--;
|
|
2865
|
-
}
|
|
2866
|
-
}
|
|
2867
|
-
}
|
|
2868
|
-
}
|
|
2869
|
-
|
|
2870
|
-
if (findSelectedCell) {
|
|
2871
|
-
if (cell === startCell || cell === endCell) {
|
|
2872
|
-
ref.cs = ref.cs !== null && ref.cs < logcalIndex ? ref.cs : logcalIndex;
|
|
2873
|
-
ref.ce = ref.ce !== null && ref.ce > logcalIndex + cs ? ref.ce : logcalIndex + cs;
|
|
2874
|
-
ref.rs = ref.rs !== null && ref.rs < i ? ref.rs : i;
|
|
2875
|
-
ref.re = ref.re !== null && ref.re > i + rs ? ref.re : i + rs;
|
|
2876
|
-
ref._i += 1;
|
|
2877
|
-
}
|
|
2878
|
-
|
|
2879
|
-
if (ref._i === 2) {
|
|
2880
|
-
findSelectedCell = false;
|
|
2881
|
-
spanIndex = [];
|
|
2882
|
-
rowSpanArr = [];
|
|
2883
|
-
i = -1;
|
|
2884
|
-
break;
|
|
2885
|
-
}
|
|
2886
|
-
} else if (numbers.getOverlapRangeAtIndex(ref.cs, ref.ce, logcalIndex, logcalIndex + cs) && numbers.getOverlapRangeAtIndex(ref.rs, ref.re, i, i + rs)) {
|
|
2887
|
-
const newCs = ref.cs < logcalIndex ? ref.cs : logcalIndex;
|
|
2888
|
-
const newCe = ref.ce > logcalIndex + cs ? ref.ce : logcalIndex + cs;
|
|
2889
|
-
const newRs = ref.rs < i ? ref.rs : i;
|
|
2890
|
-
const newRe = ref.re > i + rs ? ref.re : i + rs;
|
|
2891
|
-
|
|
2892
|
-
if (ref.cs !== newCs || ref.ce !== newCe || ref.rs !== newRs || ref.re !== newRe) {
|
|
2893
|
-
ref.cs = newCs;
|
|
2894
|
-
ref.ce = newCe;
|
|
2895
|
-
ref.rs = newRs;
|
|
2896
|
-
ref.re = newRe;
|
|
2897
|
-
i = -1;
|
|
2898
|
-
|
|
2899
|
-
spanIndex = [];
|
|
2900
|
-
rowSpanArr = [];
|
|
2901
|
-
break;
|
|
2902
|
-
}
|
|
2903
|
-
|
|
2904
|
-
dom.utils.addClass(cell, 'se-selected-table-cell');
|
|
2905
|
-
}
|
|
2906
|
-
|
|
2907
|
-
if (rs > 0) {
|
|
2908
|
-
rowSpanArr.push({
|
|
2909
|
-
index: logcalIndex,
|
|
2910
|
-
cs: cs + 1,
|
|
2911
|
-
rs: rs,
|
|
2912
|
-
row: -1
|
|
2913
|
-
});
|
|
2914
|
-
}
|
|
2915
|
-
|
|
2916
|
-
colSpan += cell.colSpan - 1;
|
|
2917
|
-
}
|
|
2918
|
-
|
|
2919
|
-
spanIndex = spanIndex.concat(rowSpanArr).sort((a, b) => {
|
|
2920
|
-
return a.index - b.index;
|
|
2921
|
-
});
|
|
2922
|
-
rowSpanArr = [];
|
|
2923
|
-
}
|
|
2924
|
-
}
|
|
2925
|
-
|
|
2926
|
-
/**
|
|
2927
|
-
* @private
|
|
2928
|
-
* @description Resets the table picker display.
|
|
2929
|
-
*/
|
|
2930
|
-
_resetTablePicker() {
|
|
2931
|
-
if (!this.tableHighlight) return;
|
|
2932
|
-
|
|
2933
|
-
const highlight = this.tableHighlight.style;
|
|
2934
|
-
const unHighlight = this.tableUnHighlight.style;
|
|
2935
|
-
|
|
2936
|
-
highlight.width = '1em';
|
|
2937
|
-
highlight.height = '1em';
|
|
2938
|
-
unHighlight.width = '10em';
|
|
2939
|
-
unHighlight.height = '10em';
|
|
2940
|
-
|
|
2941
|
-
dom.utils.changeTxt(this.tableDisplay, '1 x 1');
|
|
2942
|
-
this.menu.dropdownOff();
|
|
2943
|
-
}
|
|
2944
|
-
|
|
2945
|
-
/**
|
|
2946
|
-
* @private
|
|
2947
|
-
* @description Resets the alignment properties for table cells.
|
|
2948
|
-
*/
|
|
2949
|
-
_resetPropsAlign() {
|
|
2950
|
-
const { cell_alignment } = this.propTargets;
|
|
2951
|
-
const left = cell_alignment.querySelector('[data-value="left"]');
|
|
2952
|
-
const right = cell_alignment.querySelector('[data-value="right"]');
|
|
2953
|
-
const l_parent = left.parentElement;
|
|
2954
|
-
const r_parent = right.parentElement;
|
|
2955
|
-
l_parent.appendChild(right);
|
|
2956
|
-
r_parent.appendChild(left);
|
|
2957
|
-
}
|
|
2958
|
-
|
|
2959
|
-
/**
|
|
2960
|
-
* @private
|
|
2961
|
-
* @description Handles color selection from the color palette.
|
|
2962
|
-
* @param {Node} button The button triggering the color palette.
|
|
2963
|
-
* @param {string} type The type of color selection.
|
|
2964
|
-
* @param {HTMLInputElement} color Color text input element.
|
|
2965
|
-
*/
|
|
2966
|
-
_onColorPalette(button, type, color) {
|
|
2967
|
-
if (this.controller_colorPicker.isOpen && type === this.sliderType) {
|
|
2968
|
-
this.controller_colorPicker.close();
|
|
2969
|
-
} else {
|
|
2970
|
-
this.sliderType = type;
|
|
2971
|
-
dom.utils.addClass(button, 'on');
|
|
2972
|
-
this.colorPicker.init(color?.value || '', button);
|
|
2973
|
-
this.controller_colorPicker.open(button, null, { isWWTarget: false, initMethod: null, addOffset: null });
|
|
2974
|
-
}
|
|
2975
|
-
}
|
|
2976
|
-
|
|
2977
|
-
/**
|
|
2978
|
-
* @private
|
|
2979
|
-
* @description Closes table-related controllers.
|
|
2980
|
-
*/
|
|
2981
|
-
_closeController() {
|
|
2982
|
-
this.controller_table.close();
|
|
2983
|
-
this.controller_cell.close();
|
|
2984
|
-
}
|
|
2985
|
-
|
|
2986
|
-
/**
|
|
2987
|
-
* @private
|
|
2988
|
-
* @description Closes table-related controllers and table figure
|
|
2989
|
-
*/
|
|
2990
|
-
_closeTableSelectInfo() {
|
|
2991
|
-
this.component.deselect();
|
|
2992
|
-
this._closeController();
|
|
2993
|
-
}
|
|
2994
|
-
|
|
2995
|
-
/**
|
|
2996
|
-
* @private
|
|
2997
|
-
* @description Hides the resize line if it is visible.
|
|
2998
|
-
*/
|
|
2999
|
-
__hideResizeLine() {
|
|
3000
|
-
if (this._resizeLine) {
|
|
3001
|
-
this._resizeLine.style.display = 'none';
|
|
3002
|
-
this._resizeLine = null;
|
|
3003
|
-
}
|
|
3004
|
-
}
|
|
3005
|
-
|
|
3006
|
-
/**
|
|
3007
|
-
* @private
|
|
3008
|
-
* @description Removes global event listeners and resets resize-related properties.
|
|
3009
|
-
*/
|
|
3010
|
-
__removeGlobalEvents() {
|
|
3011
|
-
this._toggleEditor(true);
|
|
3012
|
-
this._resizing = false;
|
|
3013
|
-
this.ui.disableBackWrapper();
|
|
3014
|
-
this.__hideResizeLine();
|
|
3015
|
-
if (this._resizeLinePrev) {
|
|
3016
|
-
this._resizeLinePrev.style.display = 'none';
|
|
3017
|
-
this._resizeLinePrev = null;
|
|
3018
|
-
}
|
|
3019
|
-
const globalEvents = this.__globalEvents;
|
|
3020
|
-
for (const k in globalEvents) {
|
|
3021
|
-
if (globalEvents[k]) globalEvents[k] = this.eventManager.removeGlobalEvent(globalEvents[k]);
|
|
3022
|
-
}
|
|
3023
|
-
}
|
|
3024
|
-
|
|
3025
|
-
/**
|
|
3026
|
-
* @description Clone a table element and map selected cells to the cloned table
|
|
3027
|
-
* @param {HTMLTableElement} table <table> element
|
|
3028
|
-
* @param {HTMLTableCellElement[]} selectedCells Selected cells array
|
|
3029
|
-
* @returns {{ cloneTable: HTMLTableElement, clonedSelectedCells: HTMLTableCellElement[] }}
|
|
3030
|
-
*/
|
|
3031
|
-
#cloneTable(table, selectedCells) {
|
|
3032
|
-
/** @type {HTMLTableElement} */
|
|
3033
|
-
const cloneTable = dom.utils.clone(table, true);
|
|
3034
|
-
|
|
3035
|
-
const originalCells = Array.from(table.querySelectorAll('td, th'));
|
|
3036
|
-
const clonedCells = Array.from(cloneTable.querySelectorAll('td, th'));
|
|
3037
|
-
|
|
3038
|
-
const clonedSelectedCells = /** @type {HTMLTableCellElement[]} */ (
|
|
3039
|
-
selectedCells
|
|
3040
|
-
.map((cell) => {
|
|
3041
|
-
const index = originalCells.indexOf(cell);
|
|
3042
|
-
return index > -1 ? clonedCells[index] : null;
|
|
3043
|
-
})
|
|
3044
|
-
.filter((cell) => cell !== null)
|
|
3045
|
-
);
|
|
3046
|
-
|
|
3047
|
-
return {
|
|
3048
|
-
cloneTable,
|
|
3049
|
-
clonedSelectedCells
|
|
3050
|
-
};
|
|
3051
|
-
}
|
|
3052
|
-
|
|
3053
|
-
/**
|
|
3054
|
-
* @description Selects cells in a table, handling single and multi-cell selection, and managing shift key behavior for extended selection.
|
|
3055
|
-
* @param {HTMLTableCellElement} tdElement The target table cell (`<td>`) element that is being selected.
|
|
3056
|
-
* @param {boolean} shift A flag indicating whether the shift key is held down for multi-cell selection.
|
|
3057
|
-
* If `true`, the selection will extend to include adjacent cells, otherwise it selects only the provided cell.
|
|
3058
|
-
*/
|
|
3059
|
-
#StyleSelectCells(tdElement, shift) {
|
|
3060
|
-
this.__s = shift;
|
|
3061
|
-
if (!this._shift && !this._ref) this.__removeGlobalEvents();
|
|
3062
|
-
|
|
3063
|
-
this._shift = shift;
|
|
3064
|
-
this._fixedCell = tdElement;
|
|
3065
|
-
if (!this._selectedCells?.length) this._selectedCells = [tdElement];
|
|
3066
|
-
this._fixedCellName = tdElement.nodeName;
|
|
3067
|
-
this._selectedTable = dom.query.getParentElement(tdElement, 'TABLE');
|
|
3068
|
-
|
|
3069
|
-
this._deleteStyleSelectedCells();
|
|
3070
|
-
dom.utils.addClass(tdElement, 'se-selected-cell-focus');
|
|
3071
|
-
|
|
3072
|
-
if (!shift) {
|
|
3073
|
-
this.__globalEvents.on = this.eventManager.addGlobalEvent('mousemove', this._bindMultiOn, false);
|
|
3074
|
-
} else {
|
|
3075
|
-
this.__globalEvents.shiftOff = this.eventManager.addGlobalEvent('keyup', this._bindShiftOff, false);
|
|
3076
|
-
this.__globalEvents.on = this.eventManager.addGlobalEvent('mousedown', this._bindMultiOn, false);
|
|
3077
|
-
}
|
|
3078
|
-
|
|
3079
|
-
this.__globalEvents.off = this.eventManager.addGlobalEvent('mouseup', this._bindMultiOff, false);
|
|
3080
|
-
this.__globalEvents.touchOff = this.eventManager.addGlobalEvent('touchmove', this._bindTouchOff, false);
|
|
3081
|
-
}
|
|
3082
|
-
|
|
3083
|
-
/**
|
|
3084
|
-
* @description Splits a table cell either vertically or horizontally.
|
|
3085
|
-
* @param {"vertical"|"horizontal"} direction The direction to split the cell.
|
|
3086
|
-
*/
|
|
3087
|
-
#OnSplitCells(direction) {
|
|
3088
|
-
const vertical = direction === 'vertical';
|
|
3089
|
-
const currentCell = this._tdElement;
|
|
3090
|
-
const rows = this._trElements;
|
|
3091
|
-
const currentRow = this._trElement;
|
|
3092
|
-
const index = this._logical_cellIndex;
|
|
3093
|
-
const rowIndex = this._rowIndex;
|
|
3094
|
-
const newCell = CreateCellsHTML(currentCell.nodeName);
|
|
3095
|
-
|
|
3096
|
-
// vertical
|
|
3097
|
-
if (vertical) {
|
|
3098
|
-
const currentColSpan = currentCell.colSpan;
|
|
3099
|
-
newCell.rowSpan = currentCell.rowSpan;
|
|
3100
|
-
|
|
3101
|
-
// colspan > 1
|
|
3102
|
-
if (currentColSpan > 1) {
|
|
3103
|
-
newCell.colSpan = Math.floor(currentColSpan / 2);
|
|
3104
|
-
currentCell.colSpan = currentColSpan - newCell.colSpan;
|
|
3105
|
-
currentRow.insertBefore(newCell, currentCell.nextElementSibling);
|
|
3106
|
-
} else {
|
|
3107
|
-
// colspan - 1
|
|
3108
|
-
let rowSpanArr = [];
|
|
3109
|
-
let spanIndex = [];
|
|
3110
|
-
|
|
3111
|
-
for (let i = 0, len = this._rowCnt, cells, colSpan; i < len; i++) {
|
|
3112
|
-
cells = rows[i].cells;
|
|
3113
|
-
colSpan = 0;
|
|
3114
|
-
for (let c = 0, cLen = cells.length, cell, cs, rs, logcalIndex; c < cLen; c++) {
|
|
3115
|
-
cell = cells[c];
|
|
3116
|
-
cs = cell.colSpan - 1;
|
|
3117
|
-
rs = cell.rowSpan - 1;
|
|
3118
|
-
logcalIndex = c + colSpan;
|
|
3119
|
-
|
|
3120
|
-
if (spanIndex.length > 0) {
|
|
3121
|
-
for (let r = 0, arr; r < spanIndex.length; r++) {
|
|
3122
|
-
arr = spanIndex[r];
|
|
3123
|
-
if (arr.row > i) continue;
|
|
3124
|
-
if (logcalIndex >= arr.index) {
|
|
3125
|
-
colSpan += arr.cs;
|
|
3126
|
-
logcalIndex += arr.cs;
|
|
3127
|
-
arr.rs -= 1;
|
|
3128
|
-
arr.row = i + 1;
|
|
3129
|
-
if (arr.rs < 1) {
|
|
3130
|
-
spanIndex.splice(r, 1);
|
|
3131
|
-
r--;
|
|
3132
|
-
}
|
|
3133
|
-
} else if (c === cLen - 1) {
|
|
3134
|
-
arr.rs -= 1;
|
|
3135
|
-
arr.row = i + 1;
|
|
3136
|
-
if (arr.rs < 1) {
|
|
3137
|
-
spanIndex.splice(r, 1);
|
|
3138
|
-
r--;
|
|
3139
|
-
}
|
|
3140
|
-
}
|
|
3141
|
-
}
|
|
3142
|
-
}
|
|
3143
|
-
|
|
3144
|
-
if (logcalIndex <= index && rs > 0) {
|
|
3145
|
-
rowSpanArr.push({
|
|
3146
|
-
index: logcalIndex,
|
|
3147
|
-
cs: cs + 1,
|
|
3148
|
-
rs: rs,
|
|
3149
|
-
row: -1
|
|
3150
|
-
});
|
|
3151
|
-
}
|
|
3152
|
-
|
|
3153
|
-
if (cell !== currentCell && logcalIndex <= index && logcalIndex + cs >= index + currentColSpan - 1) {
|
|
3154
|
-
cell.colSpan += 1;
|
|
3155
|
-
break;
|
|
3156
|
-
}
|
|
3157
|
-
|
|
3158
|
-
if (logcalIndex > index) break;
|
|
3159
|
-
|
|
3160
|
-
colSpan += cs;
|
|
3161
|
-
}
|
|
3162
|
-
|
|
3163
|
-
spanIndex = spanIndex.concat(rowSpanArr).sort(function (a, b) {
|
|
3164
|
-
return a.index - b.index;
|
|
3165
|
-
});
|
|
3166
|
-
rowSpanArr = [];
|
|
3167
|
-
}
|
|
3168
|
-
|
|
3169
|
-
currentRow.insertBefore(newCell, currentCell.nextElementSibling);
|
|
3170
|
-
}
|
|
3171
|
-
} else {
|
|
3172
|
-
// horizontal
|
|
3173
|
-
const currentRowSpan = currentCell.rowSpan;
|
|
3174
|
-
newCell.colSpan = currentCell.colSpan;
|
|
3175
|
-
|
|
3176
|
-
// rowspan > 1
|
|
3177
|
-
if (currentRowSpan > 1) {
|
|
3178
|
-
newCell.rowSpan = Math.floor(currentRowSpan / 2);
|
|
3179
|
-
const newRowSpan = currentRowSpan - newCell.rowSpan;
|
|
3180
|
-
|
|
3181
|
-
const rowSpanArr = [];
|
|
3182
|
-
const nextRowIndex = dom.utils.getArrayIndex(rows, currentRow) + newRowSpan;
|
|
3183
|
-
|
|
3184
|
-
for (let i = 0, cells, colSpan; i < nextRowIndex; i++) {
|
|
3185
|
-
cells = rows[i].cells;
|
|
3186
|
-
colSpan = 0;
|
|
3187
|
-
for (let c = 0, cLen = cells.length, cell, cs, logcalIndex; c < cLen; c++) {
|
|
3188
|
-
logcalIndex = c + colSpan;
|
|
3189
|
-
if (logcalIndex >= index) break;
|
|
3190
|
-
|
|
3191
|
-
cell = cells[c];
|
|
3192
|
-
cs = cell.rowSpan - 1;
|
|
3193
|
-
if (cs > 0 && cs + i >= nextRowIndex && logcalIndex < index) {
|
|
3194
|
-
rowSpanArr.push({
|
|
3195
|
-
index: logcalIndex,
|
|
3196
|
-
cs: cell.colSpan
|
|
3197
|
-
});
|
|
3198
|
-
}
|
|
3199
|
-
colSpan += cell.colSpan - 1;
|
|
3200
|
-
}
|
|
3201
|
-
}
|
|
3202
|
-
|
|
3203
|
-
const nextRow = rows[nextRowIndex];
|
|
3204
|
-
const nextCells = nextRow.cells;
|
|
3205
|
-
let rs = rowSpanArr.shift();
|
|
3206
|
-
|
|
3207
|
-
for (let c = 0, cLen = nextCells.length, colSpan = 0, cell, cs, logcalIndex, insertIndex; c < cLen; c++) {
|
|
3208
|
-
logcalIndex = c + colSpan;
|
|
3209
|
-
cell = nextCells[c];
|
|
3210
|
-
cs = cell.colSpan - 1;
|
|
3211
|
-
insertIndex = logcalIndex + cs + 1;
|
|
3212
|
-
|
|
3213
|
-
if (rs && insertIndex >= rs.index) {
|
|
3214
|
-
colSpan += rs.cs;
|
|
3215
|
-
insertIndex += rs.cs;
|
|
3216
|
-
rs = rowSpanArr.shift();
|
|
3217
|
-
}
|
|
3218
|
-
|
|
3219
|
-
if (insertIndex >= index || c === cLen - 1) {
|
|
3220
|
-
nextRow.insertBefore(newCell, cell.nextElementSibling);
|
|
3221
|
-
break;
|
|
3222
|
-
}
|
|
3223
|
-
|
|
3224
|
-
colSpan += cs;
|
|
3225
|
-
}
|
|
3226
|
-
|
|
3227
|
-
currentCell.rowSpan = newRowSpan;
|
|
3228
|
-
} else {
|
|
3229
|
-
// rowspan - 1
|
|
3230
|
-
newCell.rowSpan = currentCell.rowSpan;
|
|
3231
|
-
const newRow = dom.utils.createElement('TR');
|
|
3232
|
-
newRow.appendChild(newCell);
|
|
3233
|
-
|
|
3234
|
-
for (let i = 0, cells; i < rowIndex; i++) {
|
|
3235
|
-
cells = rows[i].cells;
|
|
3236
|
-
if (cells.length === 0) return;
|
|
3237
|
-
|
|
3238
|
-
for (let c = 0, cLen = cells.length; c < cLen; c++) {
|
|
3239
|
-
if (i + cells[c].rowSpan - 1 >= rowIndex) {
|
|
3240
|
-
cells[c].rowSpan += 1;
|
|
3241
|
-
}
|
|
3242
|
-
}
|
|
3243
|
-
}
|
|
3244
|
-
|
|
3245
|
-
const physicalIndex = this._physical_cellIndex;
|
|
3246
|
-
const cells = currentRow.cells;
|
|
3247
|
-
|
|
3248
|
-
for (let c = 0, cLen = cells.length; c < cLen; c++) {
|
|
3249
|
-
if (c === physicalIndex) continue;
|
|
3250
|
-
cells[c].rowSpan += 1;
|
|
3251
|
-
}
|
|
3252
|
-
|
|
3253
|
-
currentRow.parentNode.insertBefore(newRow, currentRow.nextElementSibling);
|
|
3254
|
-
}
|
|
3255
|
-
}
|
|
3256
|
-
|
|
3257
|
-
this.selectMenu_split.close();
|
|
3258
|
-
this.#focusEdge(currentCell);
|
|
3259
|
-
|
|
3260
|
-
this._deleteStyleSelectedCells();
|
|
3261
|
-
this.history.push(false);
|
|
3262
|
-
|
|
3263
|
-
this._setController(currentCell);
|
|
3264
|
-
this._selectedCell = this._fixedCell = currentCell;
|
|
3265
|
-
if (!this._selectedCells?.length) this._selectedCells = [currentCell];
|
|
3266
|
-
}
|
|
3267
|
-
|
|
3268
|
-
/**
|
|
3269
|
-
* @description Handles column operations such as insert and delete.
|
|
3270
|
-
* @param {"insert-left"|"insert-right"|"delete"} command The column operation to perform.
|
|
3271
|
-
*/
|
|
3272
|
-
#OnColumnEdit(command) {
|
|
3273
|
-
switch (command) {
|
|
3274
|
-
case 'insert-left':
|
|
3275
|
-
this.editTable('cell', 'left');
|
|
3276
|
-
break;
|
|
3277
|
-
case 'insert-right':
|
|
3278
|
-
this.editTable('cell', 'right');
|
|
3279
|
-
break;
|
|
3280
|
-
case 'delete':
|
|
3281
|
-
this.editTable('cell', null);
|
|
3282
|
-
}
|
|
3283
|
-
|
|
3284
|
-
this._historyPush();
|
|
3285
|
-
}
|
|
3286
|
-
|
|
3287
|
-
/**
|
|
3288
|
-
* @description Handles row operations such as insert and delete.
|
|
3289
|
-
* @param {"insert-above"|"insert-below"|"delete"} command The row operation to perform.
|
|
3290
|
-
*/
|
|
3291
|
-
#OnRowEdit(command) {
|
|
3292
|
-
switch (command) {
|
|
3293
|
-
case 'insert-above':
|
|
3294
|
-
this.editTable('row', 'up');
|
|
3295
|
-
break;
|
|
3296
|
-
case 'insert-below':
|
|
3297
|
-
this.editTable('row', 'down');
|
|
3298
|
-
break;
|
|
3299
|
-
case 'delete':
|
|
3300
|
-
this.editTable('row', null);
|
|
3301
|
-
}
|
|
3302
|
-
|
|
3303
|
-
this._historyPush();
|
|
3304
|
-
}
|
|
3305
|
-
|
|
3306
|
-
/**
|
|
3307
|
-
* @description Handles mouse movement within the table picker.
|
|
3308
|
-
* @param {MouseEvent} e The mouse event.
|
|
3309
|
-
*/
|
|
3310
|
-
#OnMouseMoveTablePicker(e) {
|
|
3311
|
-
e.stopPropagation();
|
|
3312
|
-
|
|
3313
|
-
let x = Math.ceil(e.offsetX / 18);
|
|
3314
|
-
let y = Math.ceil(e.offsetY / 18);
|
|
3315
|
-
x = x < 1 ? 1 : x;
|
|
3316
|
-
y = y < 1 ? 1 : y;
|
|
3317
|
-
|
|
3318
|
-
if (this.options.get('_rtl')) {
|
|
3319
|
-
this.tableHighlight.style.left = x * 18 - 13 + 'px';
|
|
3320
|
-
x = 11 - x;
|
|
3321
|
-
}
|
|
3322
|
-
|
|
3323
|
-
this.tableHighlight.style.width = x + 'em';
|
|
3324
|
-
this.tableHighlight.style.height = y + 'em';
|
|
3325
|
-
|
|
3326
|
-
const x_u = x < 5 ? 5 : x > 8 ? 10 : x + 2;
|
|
3327
|
-
const y_u = y < 5 ? 5 : y > 8 ? 10 : y + 2;
|
|
3328
|
-
this.tableUnHighlight.style.width = x_u + 'em';
|
|
3329
|
-
this.tableUnHighlight.style.height = y_u + 'em';
|
|
3330
|
-
|
|
3331
|
-
dom.utils.changeTxt(this.tableDisplay, x + ' x ' + y);
|
|
3332
|
-
this._tableXY = [x, y];
|
|
3333
|
-
}
|
|
3334
|
-
|
|
3335
|
-
/**
|
|
3336
|
-
* @description Executes the selected action when the table picker is clicked.
|
|
3337
|
-
*/
|
|
3338
|
-
#OnClickTablePicker() {
|
|
3339
|
-
this.action();
|
|
3340
|
-
}
|
|
3341
|
-
|
|
3342
|
-
/**
|
|
3343
|
-
* @description Handles multi-selection of table cells.
|
|
3344
|
-
* @param {MouseEvent} e The mouse event.
|
|
3345
|
-
*/
|
|
3346
|
-
#OnCellMultiSelect(e) {
|
|
3347
|
-
this.editor._preventBlur = true;
|
|
3348
|
-
const target = /** @type {HTMLTableCellElement} */ (dom.query.getParentElement(dom.query.getEventTarget(e), dom.check.isTableCell));
|
|
3349
|
-
|
|
3350
|
-
if (this._shift) {
|
|
3351
|
-
if (target === this._fixedCell) {
|
|
3352
|
-
this._shift = false;
|
|
3353
|
-
this._deleteStyleSelectedCells();
|
|
3354
|
-
this._toggleEditor(true);
|
|
3355
|
-
this.__removeGlobalEvents();
|
|
3356
|
-
return;
|
|
3357
|
-
} else {
|
|
3358
|
-
this._toggleEditor(false);
|
|
3359
|
-
}
|
|
3360
|
-
} else if (!this._ref) {
|
|
3361
|
-
if (target === this._fixedCell) return;
|
|
3362
|
-
else this._toggleEditor(false);
|
|
3363
|
-
}
|
|
3364
|
-
|
|
3365
|
-
if (!target || target === this._selectedCell || this._fixedCellName !== target.nodeName || this._selectedTable !== dom.query.getParentElement(target, 'TABLE')) {
|
|
3366
|
-
return;
|
|
3367
|
-
}
|
|
3368
|
-
|
|
3369
|
-
this._setMultiCells(this._fixedCell, (this._selectedCell = target));
|
|
3370
|
-
}
|
|
3371
|
-
|
|
3372
|
-
/**
|
|
3373
|
-
* @description Stops multi-selection of table cells.
|
|
3374
|
-
* @param {MouseEvent} e The mouse event.
|
|
3375
|
-
*/
|
|
3376
|
-
#OffCellMultiSelect(e) {
|
|
3377
|
-
e.stopPropagation();
|
|
3378
|
-
|
|
3379
|
-
if (!this._shift) {
|
|
3380
|
-
this._toggleEditor(true);
|
|
3381
|
-
this.__removeGlobalEvents();
|
|
3382
|
-
} else if (this.__globalEvents.touchOff) {
|
|
3383
|
-
this.__globalEvents.touchOff = this.eventManager.removeGlobalEvent(this.__globalEvents.touchOff);
|
|
3384
|
-
}
|
|
3385
|
-
|
|
3386
|
-
if (!this._fixedCell || !this._selectedTable) return;
|
|
3387
|
-
|
|
3388
|
-
this._setMergeSplitButton();
|
|
3389
|
-
this._selectedCells = Array.from(this._selectedTable.querySelectorAll('.se-selected-table-cell'));
|
|
3390
|
-
|
|
3391
|
-
if (this._shift) return;
|
|
3392
|
-
|
|
3393
|
-
if (this._fixedCell && this._selectedCell) {
|
|
3394
|
-
this.#focusEdge(this._fixedCell);
|
|
3395
|
-
if (this._fixedCell === this._selectedCell) {
|
|
3396
|
-
dom.utils.removeClass(this._fixedCell, 'se-selected-table-cell');
|
|
3397
|
-
}
|
|
3398
|
-
}
|
|
3399
|
-
|
|
3400
|
-
const displayCell = this._selectedCells?.length > 0 ? this._selectedCell : this._fixedCell;
|
|
3401
|
-
this._setController(displayCell);
|
|
3402
|
-
}
|
|
3403
|
-
|
|
3404
|
-
/**
|
|
3405
|
-
* @description Handles the removal of shift-based selection.
|
|
3406
|
-
*/
|
|
3407
|
-
#OffCellShift() {
|
|
3408
|
-
if (!this._ref) {
|
|
3409
|
-
this._closeController();
|
|
3410
|
-
} else {
|
|
3411
|
-
this.__removeGlobalEvents();
|
|
3412
|
-
this._toggleEditor(true);
|
|
3413
|
-
|
|
3414
|
-
this.#focusEdge(this._fixedCell);
|
|
3415
|
-
|
|
3416
|
-
const displayCell = this._selectedCells?.length > 0 ? this._selectedCell : this._fixedCell;
|
|
3417
|
-
this._setController(displayCell);
|
|
3418
|
-
}
|
|
3419
|
-
}
|
|
3420
|
-
|
|
3421
|
-
/**
|
|
3422
|
-
* @description Handles the removal of touch-based selection.
|
|
3423
|
-
*/
|
|
3424
|
-
#OffCellTouch() {
|
|
3425
|
-
this.close();
|
|
3426
|
-
}
|
|
3427
|
-
|
|
3428
|
-
/**
|
|
3429
|
-
* @description Focus cell
|
|
3430
|
-
* @param {HTMLElement} cell Target node
|
|
3431
|
-
*/
|
|
3432
|
-
#focusEdge(cell) {
|
|
3433
|
-
if (!env.isMobile) this.editor.focusEdge(cell);
|
|
3434
|
-
}
|
|
3435
|
-
}
|
|
3436
|
-
|
|
3437
|
-
/**
|
|
3438
|
-
* @private
|
|
3439
|
-
* @description Checks if the given node is a resizable table element.
|
|
3440
|
-
* @param {Node} node The DOM node to check.
|
|
3441
|
-
* @returns {boolean} True if the node is a table-related resizable element.
|
|
3442
|
-
*/
|
|
3443
|
-
function IsResizeEls(node) {
|
|
3444
|
-
return /^(TD|TH|TR)$/i.test(node?.nodeName);
|
|
3445
|
-
}
|
|
3446
|
-
|
|
3447
|
-
/**
|
|
3448
|
-
* @private
|
|
3449
|
-
* @description Checks if a table cell is at its edge based on the mouse event.
|
|
3450
|
-
* @param {MouseEvent} event The mouse event.
|
|
3451
|
-
* @param {Element} tableCell The table cell to check.
|
|
3452
|
-
* @returns {Object} An object containing edge detection details.
|
|
3453
|
-
*/
|
|
3454
|
-
function CheckCellEdge(event, tableCell) {
|
|
3455
|
-
const startX = event.clientX;
|
|
3456
|
-
const startWidth = numbers.get(_w.getComputedStyle(tableCell).width, CELL_DECIMAL_END);
|
|
3457
|
-
const rect = tableCell.getBoundingClientRect();
|
|
3458
|
-
const offsetX = Math.round(startX - rect.left);
|
|
3459
|
-
const isLeft = offsetX <= CELL_SELECT_MARGIN;
|
|
3460
|
-
const is = isLeft || startWidth - offsetX <= CELL_SELECT_MARGIN;
|
|
3461
|
-
|
|
3462
|
-
return {
|
|
3463
|
-
is,
|
|
3464
|
-
isLeft,
|
|
3465
|
-
startX
|
|
3466
|
-
};
|
|
3467
|
-
}
|
|
3468
|
-
|
|
3469
|
-
/**
|
|
3470
|
-
* @private
|
|
3471
|
-
* @description Checks if a row is at its edge based on the mouse event.
|
|
3472
|
-
* @param {MouseEvent} event The mouse event.
|
|
3473
|
-
* @param {Element} tableCell The table row cell to check.
|
|
3474
|
-
* @returns {Object} An object containing row edge detection details.
|
|
3475
|
-
*/
|
|
3476
|
-
function CheckRowEdge(event, tableCell) {
|
|
3477
|
-
const startY = event.clientY;
|
|
3478
|
-
const startHeight = numbers.get(_w.getComputedStyle(tableCell).height, CELL_DECIMAL_END);
|
|
3479
|
-
const rect = tableCell.getBoundingClientRect();
|
|
3480
|
-
const is = Math.ceil(startHeight + rect.top - startY) <= ROW_SELECT_MARGIN;
|
|
3481
|
-
|
|
3482
|
-
return {
|
|
3483
|
-
is,
|
|
3484
|
-
startY
|
|
3485
|
-
};
|
|
3486
|
-
}
|
|
3487
|
-
|
|
3488
|
-
/**
|
|
3489
|
-
* @private
|
|
3490
|
-
* @description Creates table cells as elements strings.
|
|
3491
|
-
* @param {string} nodeName The tag name of the cell (TD or TH).
|
|
3492
|
-
* @param {number} cnt The number of cells to create.
|
|
3493
|
-
* @returns {string} The created cells.
|
|
3494
|
-
*/
|
|
3495
|
-
function CreateCellsString(nodeName, cnt) {
|
|
3496
|
-
nodeName = nodeName.toLowerCase();
|
|
3497
|
-
return `<${nodeName}><div><br></div></${nodeName}>`.repeat(cnt);
|
|
3498
|
-
}
|
|
3499
|
-
|
|
3500
|
-
/**
|
|
3501
|
-
* @private
|
|
3502
|
-
* @description Creates table cells as element HTML.
|
|
3503
|
-
* @param {string} nodeName The tag name of the cell (TD or TH).
|
|
3504
|
-
* @returns {HTMLTableCellElement} The created cells.
|
|
3505
|
-
*/
|
|
3506
|
-
function CreateCellsHTML(nodeName) {
|
|
3507
|
-
nodeName = nodeName.toLowerCase();
|
|
3508
|
-
return /** @type {HTMLTableCellElement} */ (dom.utils.createElement(nodeName, null, '<div><br></div>'));
|
|
3509
|
-
}
|
|
3510
|
-
|
|
3511
|
-
/**
|
|
3512
|
-
* @private
|
|
3513
|
-
* @description Gets the maximum number of columns in a table.
|
|
3514
|
-
* @param {HTMLTableElement} table The table element.
|
|
3515
|
-
* @returns {number} The maximum number of columns in the table.
|
|
3516
|
-
*/
|
|
3517
|
-
function GetMaxColumns(table) {
|
|
3518
|
-
const rows = table.rows;
|
|
3519
|
-
let maxColumns = 0;
|
|
3520
|
-
|
|
3521
|
-
for (let i = 0, len = rows.length; i < len; i++) {
|
|
3522
|
-
const cells = rows[i].cells;
|
|
3523
|
-
let columnCount = 0;
|
|
3524
|
-
|
|
3525
|
-
for (let j = 0, jLen = cells.length; j < jLen; j++) {
|
|
3526
|
-
columnCount += cells[j].colSpan;
|
|
3527
|
-
}
|
|
3528
|
-
|
|
3529
|
-
maxColumns = Math.max(maxColumns, columnCount);
|
|
3530
|
-
}
|
|
3531
|
-
|
|
3532
|
-
return maxColumns;
|
|
3533
|
-
}
|
|
3534
|
-
|
|
3535
|
-
/**
|
|
3536
|
-
* @private
|
|
3537
|
-
* @description Handles border style changes in table properties.
|
|
3538
|
-
* @param {string} command The border style command.
|
|
3539
|
-
*/
|
|
3540
|
-
function OnPropsBorderEdit(command) {
|
|
3541
|
-
this.propTargets.border_style.textContent = command;
|
|
3542
|
-
this._disableBorderProps(command === BORDER_LIST[0]);
|
|
3543
|
-
this.selectMenu_props_border.close();
|
|
3544
|
-
}
|
|
3545
|
-
|
|
3546
|
-
/**
|
|
3547
|
-
* @private
|
|
3548
|
-
* @description Handles border format changes in table properties.
|
|
3549
|
-
* @param {string} defaultCommand The default border format command.
|
|
3550
|
-
* @param {string} command The new border format command.
|
|
3551
|
-
*/
|
|
3552
|
-
function OnPropsBorderFormatEdit(defaultCommand, command) {
|
|
3553
|
-
const { border_format } = this.propTargets;
|
|
3554
|
-
|
|
3555
|
-
border_format.setAttribute('se-border-format', command);
|
|
3556
|
-
border_format.firstElementChild.innerHTML = this.icons[BORDER_FORMATS[command]];
|
|
3557
|
-
if (command !== defaultCommand) dom.utils.addClass(border_format, 'active');
|
|
3558
|
-
else dom.utils.removeClass(border_format, 'active');
|
|
3559
|
-
|
|
3560
|
-
this.selectMenu_props_border_format.close();
|
|
3561
|
-
this.selectMenu_props_border_format_oneCell.close();
|
|
3562
|
-
}
|
|
3563
|
-
|
|
3564
|
-
/**
|
|
3565
|
-
* @description Creates the table properties controller.
|
|
3566
|
-
* @param {ClipboardEvent} e - Event object
|
|
3567
|
-
* @param {HTMLElement} container - The container element
|
|
3568
|
-
* @param {NodeListOf<HTMLTableCellElement>} selectedCells - The selected table cells
|
|
3569
|
-
*/
|
|
3570
|
-
function SetClipboardSelectedTableCells(e, container, selectedCells) {
|
|
3571
|
-
e.preventDefault();
|
|
3572
|
-
e.stopPropagation();
|
|
3573
|
-
|
|
3574
|
-
const originalTable = selectedCells[0].closest('table');
|
|
3575
|
-
const tempTable = originalTable.cloneNode(false);
|
|
3576
|
-
const tbody = dom.utils.createElement('tbody');
|
|
3577
|
-
tempTable.appendChild(tbody);
|
|
3578
|
-
|
|
3579
|
-
const cellPositions = new Map();
|
|
3580
|
-
selectedCells.forEach((cell) => {
|
|
3581
|
-
cellPositions.set(cell, true);
|
|
3582
|
-
});
|
|
3583
|
-
|
|
3584
|
-
const rows = originalTable.rows;
|
|
3585
|
-
const rowCount = rows.length;
|
|
3586
|
-
const colCount = Array.from(rows[0].cells).reduce((sum, cell) => sum + (cell.colSpan || 1), 0);
|
|
3587
|
-
const matrix = Array.from({ length: rowCount }, () => Array(colCount).fill(null));
|
|
3588
|
-
|
|
3589
|
-
// build matrix
|
|
3590
|
-
for (let r = 0, realRow = 0; r < rowCount; r++, realRow++) {
|
|
3591
|
-
const cells = rows[r].cells;
|
|
3592
|
-
for (let c = 0, realCol = 0, cLen = cells.length; c < cLen; c++) {
|
|
3593
|
-
while (matrix[realRow][realCol]) realCol++;
|
|
3594
|
-
const cell = cells[c];
|
|
3595
|
-
const rowspan = cell.rowSpan || 1;
|
|
3596
|
-
const colspan = cell.colSpan || 1;
|
|
3597
|
-
for (let i = 0; i < rowspan; i++) {
|
|
3598
|
-
for (let j = 0; j < colspan; j++) {
|
|
3599
|
-
matrix[realRow + i][realCol + j] = cell;
|
|
3600
|
-
}
|
|
3601
|
-
}
|
|
3602
|
-
realCol += colspan;
|
|
3603
|
-
}
|
|
3604
|
-
}
|
|
3605
|
-
|
|
3606
|
-
// construct new table
|
|
3607
|
-
for (let r = 0; r < rowCount; r++) {
|
|
3608
|
-
let newRow;
|
|
3609
|
-
for (let c = 0; c < colCount; c++) {
|
|
3610
|
-
const cell = matrix[r][c];
|
|
3611
|
-
if (!cell || !cellPositions.has(cell)) continue;
|
|
3612
|
-
|
|
3613
|
-
if (!newRow) {
|
|
3614
|
-
newRow = dom.utils.createElement('tr');
|
|
3615
|
-
tbody.appendChild(newRow);
|
|
3616
|
-
}
|
|
3617
|
-
|
|
3618
|
-
if (newRow.lastChild && matrix[r][c - 1] === cell) continue;
|
|
3619
|
-
if (r > 0 && matrix[r - 1][c] === cell) continue;
|
|
3620
|
-
|
|
3621
|
-
const clonedCell = cell.cloneNode(true);
|
|
3622
|
-
|
|
3623
|
-
// recalculate rowspan and colspan
|
|
3624
|
-
let rowspan = 1;
|
|
3625
|
-
let colspan = 1;
|
|
3626
|
-
while (r + rowspan < rowCount && matrix[r + rowspan][c] === cell) rowspan++;
|
|
3627
|
-
while (c + colspan < colCount && matrix[r][c + colspan] === cell) colspan++;
|
|
3628
|
-
|
|
3629
|
-
if (rowspan > 1) clonedCell.rowSpan = rowspan;
|
|
3630
|
-
if (colspan > 1) clonedCell.colSpan = colspan;
|
|
3631
|
-
|
|
3632
|
-
newRow.appendChild(clonedCell);
|
|
3633
|
-
}
|
|
3634
|
-
}
|
|
3635
|
-
|
|
3636
|
-
const figure = dom.utils.createElement('figure');
|
|
3637
|
-
figure.className = container.className;
|
|
3638
|
-
figure.appendChild(tempTable);
|
|
3639
|
-
|
|
3640
|
-
const htmlContent = `<html><body><!--StartFragment-->${figure.outerHTML}<!--EndFragment--></body></html>`;
|
|
3641
|
-
e.clipboardData.setData('text/html', htmlContent);
|
|
3642
|
-
}
|
|
3643
|
-
|
|
3644
|
-
function _CellFormZIndex(value) {
|
|
3645
|
-
this.controller_cell.bringToTop(value);
|
|
3646
|
-
}
|
|
3647
|
-
|
|
3648
|
-
/** --------------------- HTML Create --------------------- */
|
|
3649
|
-
// init element
|
|
3650
|
-
function CreateSplitMenu(lang) {
|
|
3651
|
-
const menus = dom.utils.createElement(
|
|
3652
|
-
'DIV',
|
|
3653
|
-
null,
|
|
3654
|
-
/*html*/ `
|
|
3655
|
-
<div title="${lang.verticalSplit}" aria-label="${lang.verticalSplit}">
|
|
3656
|
-
${lang.verticalSplit}
|
|
3657
|
-
</div>
|
|
3658
|
-
<div title="${lang.horizontalSplit}" aria-label="${lang.horizontalSplit}">
|
|
3659
|
-
${lang.horizontalSplit}
|
|
3660
|
-
</div>`
|
|
3661
|
-
);
|
|
3662
|
-
|
|
3663
|
-
return { items: ['vertical', 'horizontal'], menus: menus.querySelectorAll('div') };
|
|
3664
|
-
}
|
|
3665
|
-
|
|
3666
|
-
function CreateColumnMenu(lang, icons) {
|
|
3667
|
-
const menus = dom.utils.createElement(
|
|
3668
|
-
'DIV',
|
|
3669
|
-
null,
|
|
3670
|
-
/*html*/ `
|
|
3671
|
-
<div title="${lang.insertColumnBefore}" aria-label="${lang.insertColumnBefore}">
|
|
3672
|
-
<span class="se-list-icon">${icons.insert_column_left}</span><span class="se-txt">${lang.insertColumnBefore}</span>
|
|
3673
|
-
</div>
|
|
3674
|
-
<div title="${lang.insertColumnAfter}" aria-label="${lang.insertColumnAfter}">
|
|
3675
|
-
<span class="se-list-icon">${icons.insert_column_right}</span><span class="se-txt">${lang.insertColumnAfter}</span>
|
|
3676
|
-
</div>
|
|
3677
|
-
<div title="${lang.deleteColumn}" aria-label="${lang.deleteColumn}">
|
|
3678
|
-
<span class="se-list-icon">${icons.delete_column}</span><span class="se-txt">${lang.deleteColumn}</span>
|
|
3679
|
-
</div>`
|
|
3680
|
-
);
|
|
3681
|
-
|
|
3682
|
-
return { items: ['insert-left', 'insert-right', 'delete'], menus: menus.querySelectorAll('div') };
|
|
3683
|
-
}
|
|
3684
|
-
|
|
3685
|
-
function CreateRowMenu(lang, icons) {
|
|
3686
|
-
const menus = dom.utils.createElement(
|
|
3687
|
-
'DIV',
|
|
3688
|
-
null,
|
|
3689
|
-
/*html*/ `
|
|
3690
|
-
<div title="${lang.insertRowAbove}" aria-label="${lang.insertRowAbove}">
|
|
3691
|
-
<span class="se-list-icon">${icons.insert_row_above}</span><span class="se-txt">${lang.insertRowAbove}</span>
|
|
3692
|
-
</div>
|
|
3693
|
-
<div title="${lang.insertRowBelow}" aria-label="${lang.insertRowBelow}">
|
|
3694
|
-
<span class="se-list-icon">${icons.insert_row_below}</span><span class="se-txt">${lang.insertRowBelow}</span>
|
|
3695
|
-
</div>
|
|
3696
|
-
<div title="${lang.deleteRow}" aria-label="${lang.deleteRow}">
|
|
3697
|
-
<span class="se-list-icon">${icons.delete_row}</span><span class="se-txt">${lang.deleteRow}</span>
|
|
3698
|
-
</div>`
|
|
3699
|
-
);
|
|
3700
|
-
|
|
3701
|
-
return { items: ['insert-above', 'insert-below', 'delete'], menus: menus.querySelectorAll('div') };
|
|
3702
|
-
}
|
|
3703
|
-
|
|
3704
|
-
function CreateBorderMenu() {
|
|
3705
|
-
let html = '';
|
|
3706
|
-
|
|
3707
|
-
for (let i = 0, len = BORDER_LIST.length, s; i < len; i++) {
|
|
3708
|
-
s = BORDER_LIST[i];
|
|
3709
|
-
html += /*html*/ `
|
|
3710
|
-
<div title="${s}" aria-label="${s}" style="padding: 0 12px;">
|
|
3711
|
-
<span class="se-txt">${s}</span>
|
|
3712
|
-
</div>`;
|
|
3713
|
-
}
|
|
3714
|
-
|
|
3715
|
-
const menus = dom.utils.createElement('DIV', null, html);
|
|
3716
|
-
return { items: BORDER_LIST, menus: menus.querySelectorAll('div') };
|
|
3717
|
-
}
|
|
3718
|
-
|
|
3719
|
-
function CreateBorderFormatMenu(langs, icons, indideFormats) {
|
|
3720
|
-
const items = [];
|
|
3721
|
-
let html = '';
|
|
3722
|
-
|
|
3723
|
-
for (const k in BORDER_FORMATS) {
|
|
3724
|
-
if (indideFormats.includes(k)) continue;
|
|
3725
|
-
const s = BORDER_FORMATS[k];
|
|
3726
|
-
items.push(k);
|
|
3727
|
-
html += /*html*/ `
|
|
3728
|
-
<button type="button" class="se-btn se-tooltip">
|
|
3729
|
-
${icons[s]}
|
|
3730
|
-
<span class="se-tooltip-inner">
|
|
3731
|
-
<span class="se-tooltip-text">${langs[s]}</span>
|
|
3732
|
-
</span>
|
|
3733
|
-
</button>`;
|
|
3734
|
-
}
|
|
3735
|
-
|
|
3736
|
-
const menus = dom.utils.createElement('DIV', null, html);
|
|
3737
|
-
return { items, menus: menus.querySelectorAll('button') };
|
|
3738
|
-
}
|
|
3739
|
-
|
|
3740
|
-
function CreateHTML() {
|
|
3741
|
-
const html = /*html*/ `
|
|
3742
|
-
<div class="se-table-size">
|
|
3743
|
-
<div class="se-table-size-picker se-controller-table-picker"></div>
|
|
3744
|
-
<div class="se-table-size-highlighted"></div>
|
|
3745
|
-
<div class="se-table-size-unhighlighted"></div>
|
|
3746
|
-
</div>
|
|
3747
|
-
<div class="se-table-size-display">1 x 1</div>`;
|
|
3748
|
-
|
|
3749
|
-
return dom.utils.createElement('DIV', { class: 'se-dropdown se-selector-table' }, html);
|
|
3750
|
-
}
|
|
3751
|
-
|
|
3752
|
-
function CreateHTML_controller_table({ lang, icons }) {
|
|
3753
|
-
const html = /*html*/ `
|
|
3754
|
-
<div class="se-arrow se-arrow-down se-visible-hidden"></div>
|
|
3755
|
-
<div class="se-btn-group">
|
|
3756
|
-
<button type="button" data-command="openTableProperties" class="se-btn se-tooltip">
|
|
3757
|
-
${icons.table_properties}
|
|
3758
|
-
<span class="se-tooltip-inner">
|
|
3759
|
-
<span class="se-tooltip-text">${lang.tableProperties}</span>
|
|
3760
|
-
</span>
|
|
3761
|
-
</button>
|
|
3762
|
-
<button type="button" data-command="layout" class="se-btn se-tooltip _se_table_fixed_column">
|
|
3763
|
-
${icons.fixed_column_width}
|
|
3764
|
-
<span class="se-tooltip-inner">
|
|
3765
|
-
<span class="se-tooltip-text">${lang.fixedColumnWidth}</span>
|
|
3766
|
-
</span>
|
|
3767
|
-
</button>
|
|
3768
|
-
<button type="button" data-command="header" class="se-btn se-tooltip _se_table_header">
|
|
3769
|
-
${icons.table_header}
|
|
3770
|
-
<span class="se-tooltip-inner">
|
|
3771
|
-
<span class="se-tooltip-text">${lang.tableHeader}</span>
|
|
3772
|
-
</span>
|
|
3773
|
-
</button>
|
|
3774
|
-
<button type="button" data-command="caption" class="se-btn se-tooltip _se_table_caption">
|
|
3775
|
-
${icons.caption}
|
|
3776
|
-
<span class="se-tooltip-inner">
|
|
3777
|
-
<span class="se-tooltip-text">${lang.caption}</span>
|
|
3778
|
-
</span>
|
|
3779
|
-
</button>
|
|
3780
|
-
<button type="button" data-command="resize" class="se-btn se-tooltip _se_table_resize">
|
|
3781
|
-
${icons.reduction}
|
|
3782
|
-
<span class="se-tooltip-inner">
|
|
3783
|
-
<span class="se-tooltip-text">${lang.minSize}</span>
|
|
3784
|
-
</span>
|
|
3785
|
-
</button>
|
|
3786
|
-
<button type="button" data-command="copy" class="se-btn se-tooltip">
|
|
3787
|
-
${icons.copy}
|
|
3788
|
-
<span class="se-tooltip-inner">
|
|
3789
|
-
<span class="se-tooltip-text">${lang.copy}</span>
|
|
3790
|
-
</span>
|
|
3791
|
-
</button>
|
|
3792
|
-
<button type="button" data-command="remove" class="se-btn se-tooltip">
|
|
3793
|
-
${icons.delete}
|
|
3794
|
-
<span class="se-tooltip-inner">
|
|
3795
|
-
<span class="se-tooltip-text">${lang.remove}</span>
|
|
3796
|
-
</span>
|
|
3797
|
-
</button>
|
|
3798
|
-
</div>`;
|
|
3799
|
-
|
|
3800
|
-
return dom.utils.createElement('DIV', { class: 'se-controller se-controller-table' }, html);
|
|
3801
|
-
}
|
|
3802
|
-
|
|
3803
|
-
/**
|
|
3804
|
-
* @param {__se__EditorCore} editor
|
|
3805
|
-
* @returns {{ html: HTMLElement, splitButton: HTMLButtonElement, columnButton: HTMLButtonElement, rowButton: HTMLButtonElement, mergeButton: HTMLButtonElement, unmergeButton: HTMLButtonElement }}
|
|
3806
|
-
*/
|
|
3807
|
-
function CreateHTML_controller_cell({ lang, icons }, cellControllerTop) {
|
|
3808
|
-
const html = /*html*/ `
|
|
3809
|
-
<div class="se-arrow se-arrow-${cellControllerTop ? 'down se-visible-hidden' : 'up'}"></div>
|
|
3810
|
-
<div class="se-btn-group">
|
|
3811
|
-
<button type="button" data-command="openCellProperties" class="se-btn se-tooltip">
|
|
3812
|
-
${icons.cell_properties}
|
|
3813
|
-
<span class="se-tooltip-inner">
|
|
3814
|
-
<span class="se-tooltip-text">${lang.cellProperties}</span>
|
|
3815
|
-
</span>
|
|
3816
|
-
</button>
|
|
3817
|
-
<button type="button" data-command="oncolumn" class="se-btn se-tooltip">
|
|
3818
|
-
${icons.table_column}
|
|
3819
|
-
<span class="se-tooltip-inner">
|
|
3820
|
-
<span class="se-tooltip-text">${lang.column}</span>
|
|
3821
|
-
</span>
|
|
3822
|
-
</button>
|
|
3823
|
-
<button type="button" data-command="onrow" class="se-btn se-tooltip">
|
|
3824
|
-
${icons.table_row}
|
|
3825
|
-
<span class="se-tooltip-inner">
|
|
3826
|
-
<span class="se-tooltip-text">${lang.row}</span>
|
|
3827
|
-
</span>
|
|
3828
|
-
</button>
|
|
3829
|
-
<button type="button" data-command="merge" class="se-btn se-tooltip" style="display: none;">
|
|
3830
|
-
${icons.merge_cell}
|
|
3831
|
-
<span class="se-tooltip-inner">
|
|
3832
|
-
<span class="se-tooltip-text">${lang.mergeCells}</span>
|
|
3833
|
-
</span>
|
|
3834
|
-
</button>
|
|
3835
|
-
<button type="button" data-command="onsplit" class="se-btn se-tooltip">
|
|
3836
|
-
${icons.split_cell}
|
|
3837
|
-
<span class="se-tooltip-inner">
|
|
3838
|
-
<span class="se-tooltip-text">${lang.splitCells}</span>
|
|
3839
|
-
</span>
|
|
3840
|
-
</button>
|
|
3841
|
-
<button type="button" data-command="unmerge" class="se-btn se-tooltip">
|
|
3842
|
-
${icons.unmerge_cell}
|
|
3843
|
-
<span class="se-tooltip-inner">
|
|
3844
|
-
<span class="se-tooltip-text">${lang.unmergeCells}</span>
|
|
3845
|
-
</span>
|
|
3846
|
-
</button>
|
|
3847
|
-
</div>`;
|
|
3848
|
-
|
|
3849
|
-
const content = dom.utils.createElement('DIV', { class: 'se-controller se-controller-table-cell' }, html);
|
|
3850
|
-
|
|
3851
|
-
return {
|
|
3852
|
-
html: content,
|
|
3853
|
-
splitButton: content.querySelector('[data-command="onsplit"]'),
|
|
3854
|
-
columnButton: content.querySelector('[data-command="oncolumn"]'),
|
|
3855
|
-
rowButton: content.querySelector('[data-command="onrow"]'),
|
|
3856
|
-
mergeButton: content.querySelector('[data-command="merge"]'),
|
|
3857
|
-
unmergeButton: content.querySelector('[data-command="unmerge"]')
|
|
3858
|
-
};
|
|
3859
|
-
}
|
|
3860
|
-
|
|
3861
|
-
/**
|
|
3862
|
-
* @typedef {Object} TableCtrlProps
|
|
3863
|
-
* @property {HTMLElement} html
|
|
3864
|
-
* @property {HTMLElement} controller_props_title
|
|
3865
|
-
* @property {HTMLButtonElement} borderButton
|
|
3866
|
-
* @property {HTMLButtonElement} borderFormatButton
|
|
3867
|
-
* @property {HTMLElement} cell_alignment
|
|
3868
|
-
* @property {HTMLElement} cell_alignment_vertical
|
|
3869
|
-
* @property {HTMLElement} cell_alignment_table_text
|
|
3870
|
-
* @property {HTMLButtonElement} border_style
|
|
3871
|
-
* @property {HTMLInputElement} border_color
|
|
3872
|
-
* @property {HTMLInputElement} border_width
|
|
3873
|
-
* @property {HTMLInputElement} back_color
|
|
3874
|
-
* @property {HTMLInputElement} font_color
|
|
3875
|
-
* @property {HTMLButtonElement} palette_border_button
|
|
3876
|
-
* @property {HTMLButtonElement} font_bold
|
|
3877
|
-
* @property {HTMLButtonElement} font_underline
|
|
3878
|
-
* @property {HTMLButtonElement} font_italic
|
|
3879
|
-
* @property {HTMLButtonElement} font_strike
|
|
3880
|
-
*
|
|
3881
|
-
* @param {__se__EditorCore} editor - Editor instance
|
|
3882
|
-
* @returns {TableCtrlProps}
|
|
3883
|
-
*/
|
|
3884
|
-
function CreateHTML_controller_properties({ lang, icons, options }) {
|
|
3885
|
-
const alignItems = options.get('_rtl') ? ['right', 'center', 'left', 'justify'] : ['left', 'center', 'right', 'justify'];
|
|
3886
|
-
let alignHtml = '';
|
|
3887
|
-
for (let i = 0, item, text; i < alignItems.length; i++) {
|
|
3888
|
-
item = alignItems[i];
|
|
3889
|
-
text = lang['align' + item.charAt(0).toUpperCase() + item.slice(1)];
|
|
3890
|
-
alignHtml += /*html*/ `
|
|
3891
|
-
<button type="button" class="se-btn se-tooltip" data-command="props_align" data-value="${item}" title="${text}" aria-label="${text}">
|
|
3892
|
-
${icons['align_' + item]}
|
|
3893
|
-
<span class="se-tooltip-inner">
|
|
3894
|
-
<span class="se-tooltip-text">${text}</span>
|
|
3895
|
-
</span>
|
|
3896
|
-
</button>`;
|
|
3897
|
-
}
|
|
3898
|
-
|
|
3899
|
-
// vertical align html
|
|
3900
|
-
const verticalAligns = ['top', 'middle', 'bottom'];
|
|
3901
|
-
let verticalAlignHtml = '';
|
|
3902
|
-
for (let i = 0, item, text; i < verticalAligns.length; i++) {
|
|
3903
|
-
item = verticalAligns[i];
|
|
3904
|
-
text = lang['align' + item.charAt(0).toUpperCase() + item.slice(1)];
|
|
3905
|
-
verticalAlignHtml += /*html*/ `
|
|
3906
|
-
<button type="button" class="se-btn se-tooltip" data-command="props_align_vertical" data-value="${item}" title="${text}" aria-label="${text}">
|
|
3907
|
-
${icons['align_' + item]}
|
|
3908
|
-
<span class="se-tooltip-inner">
|
|
3909
|
-
<span class="se-tooltip-text">${text}</span>
|
|
3910
|
-
</span>
|
|
3911
|
-
</button>`;
|
|
3912
|
-
}
|
|
3913
|
-
|
|
3914
|
-
const html = /*html*/ `
|
|
3915
|
-
<div class="se-controller-content">
|
|
3916
|
-
<div class="se-controller-header">
|
|
3917
|
-
<button type="button" data-command="close_props" class="se-btn se-close-btn close" title="${lang.close}" aria-label="${lang.close}">${icons.cancel}</button>
|
|
3918
|
-
<span class="se-controller-title">${lang.tableProperties}</span>
|
|
3919
|
-
</div>
|
|
3920
|
-
<div class="se-controller-body">
|
|
3921
|
-
|
|
3922
|
-
<label>${lang.border}</label>
|
|
3923
|
-
<div class="se-form-group se-form-w0">
|
|
3924
|
-
<button type="button" data-command="props_onborder_format" class="se-btn se-tooltip">
|
|
3925
|
-
${icons[BORDER_FORMATS.all]}
|
|
3926
|
-
<span class="se-tooltip-inner">
|
|
3927
|
-
<span class="se-tooltip-text">${lang.border}</span>
|
|
3928
|
-
</span>
|
|
3929
|
-
</button>
|
|
3930
|
-
<button type="button" data-command="props_onborder_style" class="se-btn se-btn-select se-tooltip se-border-style">
|
|
3931
|
-
<span class="se-txt"></span>
|
|
3932
|
-
${icons.arrow_down}
|
|
3933
|
-
<span class="se-tooltip-inner">
|
|
3934
|
-
<span class="se-tooltip-text">${lang.border}</span>
|
|
3935
|
-
</span>
|
|
3936
|
-
</button>
|
|
3937
|
-
<input type="text" class="se-color-input __se_border_color" placeholder="${lang.color}" />
|
|
3938
|
-
<button type="button" data-command="props_onpalette" data-value="border" class="se-btn se-tooltip">
|
|
3939
|
-
${icons.color_palette}
|
|
3940
|
-
<span class="se-tooltip-inner">
|
|
3941
|
-
<span class="se-tooltip-text">${lang.colorPicker}</span>
|
|
3942
|
-
</span>
|
|
3943
|
-
</button>
|
|
3944
|
-
<input type="text" class="se-input-control __se__border_size" placeholder="${lang.width}" />
|
|
3945
|
-
</div>
|
|
3946
|
-
|
|
3947
|
-
<label>${lang.color}</label>
|
|
3948
|
-
<div class="se-form-group se-form-w0">
|
|
3949
|
-
<button type="button" data-command="props_onpalette" data-value="font" class="se-btn se-tooltip">
|
|
3950
|
-
${icons.font_color}
|
|
3951
|
-
<span class="se-tooltip-inner">
|
|
3952
|
-
<span class="se-tooltip-text">${lang.fontColor}</span>
|
|
3953
|
-
</span>
|
|
3954
|
-
</button>
|
|
3955
|
-
<input type="text" class="se-color-input __se_font_color" placeholder="${lang.fontColor}" />
|
|
3956
|
-
<button type="button" data-command="props_onpalette" data-value="back" class="se-btn se-tooltip">
|
|
3957
|
-
${icons.background_color}
|
|
3958
|
-
<span class="se-tooltip-inner">
|
|
3959
|
-
<span class="se-tooltip-text">${lang.backgroundColor}</span>
|
|
3960
|
-
</span>
|
|
3961
|
-
</button>
|
|
3962
|
-
<input type="text" class="se-color-input __se_back_color" placeholder="${lang.backgroundColor}" />
|
|
3963
|
-
</div>
|
|
3964
|
-
|
|
3965
|
-
<label>${lang.font}</label>
|
|
3966
|
-
<div class="se-form-group se-form-w0">
|
|
3967
|
-
<button type="button" data-command="props_font_style" data-value="bold" class="se-btn se-tooltip">
|
|
3968
|
-
${icons.bold}
|
|
3969
|
-
<span class="se-tooltip-inner">
|
|
3970
|
-
<span class="se-tooltip-text">${lang.bold}</span>
|
|
3971
|
-
</span>
|
|
3972
|
-
</button>
|
|
3973
|
-
<button type="button" data-command="props_font_style" data-value="underline" class="se-btn se-tooltip">
|
|
3974
|
-
${icons.underline}
|
|
3975
|
-
<span class="se-tooltip-inner">
|
|
3976
|
-
<span class="se-tooltip-text">${lang.underline}</span>
|
|
3977
|
-
</span>
|
|
3978
|
-
</button>
|
|
3979
|
-
<button type="button" data-command="props_font_style" data-value="italic" class="se-btn se-tooltip">
|
|
3980
|
-
${icons.italic}
|
|
3981
|
-
<span class="se-tooltip-inner">
|
|
3982
|
-
<span class="se-tooltip-text">${lang.italic}</span>
|
|
3983
|
-
</span>
|
|
3984
|
-
</button>
|
|
3985
|
-
<button type="button" data-command="props_font_style" data-value="strike" class="se-btn se-tooltip">
|
|
3986
|
-
${icons.strike}
|
|
3987
|
-
<span class="se-tooltip-inner">
|
|
3988
|
-
<span class="se-tooltip-text">${lang.strike}</span>
|
|
3989
|
-
</span>
|
|
3990
|
-
</button>
|
|
3991
|
-
</div>
|
|
3992
|
-
|
|
3993
|
-
<div class="se-table-props-align">
|
|
3994
|
-
<label>${lang.align} <span class="__se__a_table_t">( ${lang.table} )</span></label>
|
|
3995
|
-
<div class="se-form-group se-form-w0 se-list-inner">
|
|
3996
|
-
<div class="__se__a_h">
|
|
3997
|
-
${alignHtml}
|
|
3998
|
-
</div>
|
|
3999
|
-
<div class="__se__a_v">
|
|
4000
|
-
${verticalAlignHtml}
|
|
4001
|
-
</div>
|
|
4002
|
-
</div>
|
|
4003
|
-
</div>
|
|
4004
|
-
</div>
|
|
4005
|
-
<div class="se-form-group se-form-w0 se-form-flex-btn">
|
|
4006
|
-
<button type="button" class="se-btn se-btn-success" data-command="props_submit" title="${lang.submitButton}" aria-label="${lang.submitButton}">${icons.checked}</button>
|
|
4007
|
-
<button type="button" class="se-btn se-btn-danger" data-command="revert" title="${lang.revert}" aria-label="${lang.revert}">${icons.revert}</button>
|
|
4008
|
-
</div>
|
|
4009
|
-
</div>`;
|
|
4010
|
-
|
|
4011
|
-
const content = dom.utils.createElement('DIV', { class: 'se-controller se-table-props' }, html);
|
|
4012
|
-
|
|
4013
|
-
return {
|
|
4014
|
-
html: content,
|
|
4015
|
-
controller_props_title: content.querySelector('.se-controller-title'),
|
|
4016
|
-
borderButton: content.querySelector('[data-command="props_onborder_style"]'),
|
|
4017
|
-
borderFormatButton: content.querySelector('[data-command="props_onborder_format"]'),
|
|
4018
|
-
cell_alignment: content.querySelector('.se-table-props-align .__se__a_h'),
|
|
4019
|
-
cell_alignment_vertical: content.querySelector('.se-table-props-align .__se__a_v'),
|
|
4020
|
-
cell_alignment_table_text: content.querySelector('.se-table-props-align .__se__a_table_t'),
|
|
4021
|
-
border_style: content.querySelector('[data-command="props_onborder_style"] .se-txt'),
|
|
4022
|
-
border_color: content.querySelector('.__se_border_color'),
|
|
4023
|
-
border_width: content.querySelector('.__se__border_size'),
|
|
4024
|
-
back_color: content.querySelector('.__se_back_color'),
|
|
4025
|
-
font_color: content.querySelector('.__se_font_color'),
|
|
4026
|
-
palette_border_button: content.querySelector('[data-command="props_onpalette"][data-value="border"]'),
|
|
4027
|
-
font_bold: content.querySelector('[data-command="props_font_style"][data-value="bold"]'),
|
|
4028
|
-
font_underline: content.querySelector('[data-command="props_font_style"][data-value="underline"]'),
|
|
4029
|
-
font_italic: content.querySelector('[data-command="props_font_style"][data-value="italic"]'),
|
|
4030
|
-
font_strike: content.querySelector('[data-command="props_font_style"][data-value="strike"]')
|
|
4031
|
-
};
|
|
4032
|
-
}
|
|
4033
|
-
|
|
4034
|
-
export default Table;
|