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
|
@@ -0,0 +1,942 @@
|
|
|
1
|
+
import { PluginModal } from '../../../interfaces';
|
|
2
|
+
import { Modal, Figure } from '../../../modules/contract';
|
|
3
|
+
import { FileManager } from '../../../modules/manager';
|
|
4
|
+
import { ModalAnchorEditor } from '../../../modules/ui';
|
|
5
|
+
import { dom, numbers, env } from '../../../helper';
|
|
6
|
+
|
|
7
|
+
import { DEFAULT_ACCEPTED_FORMATS, DEFAULT_SVG_SIZE, FORMAT_TYPE, SIZE_UNIT } from './shared/image.constants';
|
|
8
|
+
import { CreateHTML_modal } from './render/image.html';
|
|
9
|
+
import ImageSizeService from './services/image.size';
|
|
10
|
+
import ImageUploadService from './services/image.upload';
|
|
11
|
+
|
|
12
|
+
const { NO_EVENT } = env;
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* @typedef {Object} ImagePluginOptions
|
|
16
|
+
* @property {boolean} [canResize=true] - Whether the image element can be resized.
|
|
17
|
+
* @property {boolean} [showHeightInput=true] - Whether to display the height input field.
|
|
18
|
+
* @property {string} [defaultWidth="auto"] - The default width of the image. If a number is provided, `"px"` will be appended.
|
|
19
|
+
* @property {string} [defaultHeight="auto"] - The default height of the image. If a number is provided, `"px"` will be appended.
|
|
20
|
+
* @property {boolean} [percentageOnlySize=false] - Whether to allow only percentage-based sizing.
|
|
21
|
+
* @property {boolean} [createFileInput=true] - Whether to create a file input element for image uploads.
|
|
22
|
+
* @property {boolean} [createUrlInput=true] - Whether to create a URL input element for image insertion.
|
|
23
|
+
* @property {string} [uploadUrl] - The URL endpoint for image file uploads.
|
|
24
|
+
* @property {Object<string, string>} [uploadHeaders] - Additional headers to include in the file upload request.
|
|
25
|
+
* @property {number} [uploadSizeLimit] - The total upload size limit in bytes.
|
|
26
|
+
* @property {number} [uploadSingleSizeLimit] - The single file upload size limit in bytes.
|
|
27
|
+
* @property {boolean} [allowMultiple=false] - Whether multiple image uploads are allowed.
|
|
28
|
+
* @property {string} [acceptedFormats="image/*"] - The accepted file formats for image uploads.
|
|
29
|
+
* @property {boolean} [useFormatType=true] - Whether to enable format type selection (`block` or `inline`).
|
|
30
|
+
* @property {'block'|'inline'} [defaultFormatType="block"] - The default image format type (`"block"` or `"inline"`).
|
|
31
|
+
* @property {boolean} [keepFormatType=false] - Whether to retain the chosen format type after image insertion.
|
|
32
|
+
* @property {boolean} [linkEnableFileUpload] - Whether to enable file uploads for linked images.
|
|
33
|
+
* @property {SunEditor.Module.Figure.Controls} [controls] - Figure controls.
|
|
34
|
+
* @property {SunEditor.ComponentInsertType} [insertBehavior] - Component insertion behavior for selection and cursor placement. [default: `options.get('componentInsertBehavior')`]
|
|
35
|
+
* - For inline components: places the cursor near the inserted component or selects it if no nearby range is available.
|
|
36
|
+
* - For block components: executes behavior based on `selectMode`:
|
|
37
|
+
* - `auto`: Move cursor to the next line if possible, otherwise select the component.
|
|
38
|
+
* - `select`: Always select the inserted component.
|
|
39
|
+
* - `line`: Move cursor to the next line if possible, or create a new line and move there.
|
|
40
|
+
* - `none`: Do nothing.
|
|
41
|
+
*/
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* @typedef {Object} ImageState
|
|
45
|
+
* @property {string} sizeUnit - Size unit (`'px'` or `'%'`)
|
|
46
|
+
* @property {boolean} onlyPercentage - Whether only percentage sizing is allowed
|
|
47
|
+
* @property {number} produceIndex - Image production index for batch operations
|
|
48
|
+
*/
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* @class
|
|
52
|
+
* @description Image plugin.
|
|
53
|
+
* - This plugin provides image insertion functionality within the editor, supporting both file upload and URL input.
|
|
54
|
+
*/
|
|
55
|
+
class Image_ extends PluginModal {
|
|
56
|
+
static key = 'image';
|
|
57
|
+
static className = '';
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* @param {Element} node - The node to check.
|
|
61
|
+
* @returns {Element|null} Returns a node if the node is a valid component.
|
|
62
|
+
*/
|
|
63
|
+
static component(node) {
|
|
64
|
+
const compNode = dom.check.isFigure(node) || (/^span$/i.test(node.nodeName) && dom.check.isComponentContainer(node)) ? node.firstElementChild : node;
|
|
65
|
+
return /^IMG$/i.test(compNode?.nodeName) ? compNode : dom.check.isAnchor(compNode) && /^IMG$/i.test(compNode?.firstElementChild?.nodeName) ? compNode?.firstElementChild : null;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
#resizing;
|
|
69
|
+
#nonResizing;
|
|
70
|
+
|
|
71
|
+
#linkElement = null;
|
|
72
|
+
#linkValue = '';
|
|
73
|
+
#align = 'none';
|
|
74
|
+
#svgDefaultSize = DEFAULT_SVG_SIZE;
|
|
75
|
+
#element = null;
|
|
76
|
+
#cover = null;
|
|
77
|
+
#container = null;
|
|
78
|
+
#caption = null;
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* @constructor
|
|
82
|
+
* @param {SunEditor.Kernel} editor - The core kernel
|
|
83
|
+
* @param {ImagePluginOptions} pluginOptions
|
|
84
|
+
*/
|
|
85
|
+
constructor(editor, pluginOptions) {
|
|
86
|
+
// plugin basic properties
|
|
87
|
+
super(editor);
|
|
88
|
+
this.title = this.$.lang.image;
|
|
89
|
+
this.icon = 'image';
|
|
90
|
+
|
|
91
|
+
this.pluginOptions = {
|
|
92
|
+
canResize: pluginOptions.canResize === undefined ? true : pluginOptions.canResize,
|
|
93
|
+
showHeightInput: pluginOptions.showHeightInput === undefined ? true : !!pluginOptions.showHeightInput,
|
|
94
|
+
defaultWidth: !pluginOptions.defaultWidth ? 'auto' : numbers.is(pluginOptions.defaultWidth) ? pluginOptions.defaultWidth + SIZE_UNIT.PIXEL : pluginOptions.defaultWidth,
|
|
95
|
+
defaultHeight: !pluginOptions.defaultHeight ? 'auto' : numbers.is(pluginOptions.defaultHeight) ? pluginOptions.defaultHeight + SIZE_UNIT.PIXEL : pluginOptions.defaultHeight,
|
|
96
|
+
percentageOnlySize: !!pluginOptions.percentageOnlySize,
|
|
97
|
+
createFileInput: pluginOptions.createFileInput === undefined ? true : pluginOptions.createFileInput,
|
|
98
|
+
createUrlInput: pluginOptions.createUrlInput === undefined || !pluginOptions.createFileInput ? true : pluginOptions.createUrlInput,
|
|
99
|
+
uploadUrl: typeof pluginOptions.uploadUrl === 'string' ? pluginOptions.uploadUrl : null,
|
|
100
|
+
uploadHeaders: pluginOptions.uploadHeaders || null,
|
|
101
|
+
uploadSizeLimit: numbers.get(pluginOptions.uploadSizeLimit, 0),
|
|
102
|
+
uploadSingleSizeLimit: numbers.get(pluginOptions.uploadSingleSizeLimit, 0),
|
|
103
|
+
allowMultiple: !!pluginOptions.allowMultiple,
|
|
104
|
+
acceptedFormats: typeof pluginOptions.acceptedFormats !== 'string' || pluginOptions.acceptedFormats.trim() === '*' ? DEFAULT_ACCEPTED_FORMATS : pluginOptions.acceptedFormats.trim() || DEFAULT_ACCEPTED_FORMATS,
|
|
105
|
+
useFormatType: pluginOptions.useFormatType ?? true,
|
|
106
|
+
defaultFormatType: [FORMAT_TYPE.BLOCK, FORMAT_TYPE.INLINE].includes(pluginOptions.defaultFormatType) ? pluginOptions.defaultFormatType : FORMAT_TYPE.BLOCK,
|
|
107
|
+
keepFormatType: pluginOptions.keepFormatType ?? false,
|
|
108
|
+
insertBehavior: pluginOptions.insertBehavior,
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
// create HTML
|
|
112
|
+
const sizeUnit = this.pluginOptions.percentageOnlySize ? SIZE_UNIT.PERCENTAGE : SIZE_UNIT.PIXEL;
|
|
113
|
+
const modalEl = CreateHTML_modal(this.$, this.pluginOptions);
|
|
114
|
+
const ctrlAs = this.pluginOptions.useFormatType ? 'as' : '';
|
|
115
|
+
const figureControls =
|
|
116
|
+
pluginOptions.controls ||
|
|
117
|
+
(!this.pluginOptions.canResize
|
|
118
|
+
? [[ctrlAs, 'mirror_h', 'mirror_v', 'align', 'caption', 'edit', 'revert', 'copy', 'remove']]
|
|
119
|
+
: [
|
|
120
|
+
[ctrlAs, 'resize_auto,100,75,50', 'rotate_l', 'rotate_r', 'mirror_h', 'mirror_v'],
|
|
121
|
+
['edit', 'align', 'caption', 'revert', 'copy', 'remove'],
|
|
122
|
+
]);
|
|
123
|
+
|
|
124
|
+
// show align
|
|
125
|
+
this.alignForm = modalEl.alignForm;
|
|
126
|
+
if (!figureControls.some((subArray) => subArray.includes('align'))) this.alignForm.style.display = 'none';
|
|
127
|
+
|
|
128
|
+
// modules
|
|
129
|
+
const Link = this.$.plugins.link ? this.$.plugins.link.pluginOptions : {};
|
|
130
|
+
this.anchor = new ModalAnchorEditor(this.$, modalEl.html, {
|
|
131
|
+
...Link,
|
|
132
|
+
textToDisplay: false,
|
|
133
|
+
title: true,
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
this.modal = new Modal(this, this.$, modalEl.html);
|
|
137
|
+
|
|
138
|
+
this.figure = new Figure(this, this.$, figureControls, {
|
|
139
|
+
sizeUnit: sizeUnit,
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
this.fileManager = new FileManager(this, this.$, {
|
|
143
|
+
query: 'img',
|
|
144
|
+
loadEventName: 'onImageLoad',
|
|
145
|
+
actionEventName: 'onImageAction',
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
// members
|
|
149
|
+
/** @type {ImageState} */
|
|
150
|
+
this.state = {
|
|
151
|
+
sizeUnit: sizeUnit,
|
|
152
|
+
onlyPercentage: this.pluginOptions.percentageOnlySize,
|
|
153
|
+
produceIndex: 0,
|
|
154
|
+
};
|
|
155
|
+
|
|
156
|
+
this.fileModalWrapper = modalEl.fileModalWrapper;
|
|
157
|
+
this.imgInputFile = modalEl.imgInputFile;
|
|
158
|
+
this.imgUrlFile = modalEl.imgUrlFile;
|
|
159
|
+
this.focusElement = this.imgInputFile || this.imgUrlFile;
|
|
160
|
+
this.altText = modalEl.altText;
|
|
161
|
+
this.captionCheckEl = modalEl.captionCheckEl;
|
|
162
|
+
this.captionEl = this.captionCheckEl?.parentElement;
|
|
163
|
+
this.previewSrc = modalEl.previewSrc;
|
|
164
|
+
|
|
165
|
+
this.as = FORMAT_TYPE.BLOCK;
|
|
166
|
+
this.#resizing = this.pluginOptions.canResize;
|
|
167
|
+
this.#nonResizing = !this.#resizing || !this.pluginOptions.showHeightInput || this.pluginOptions.percentageOnlySize;
|
|
168
|
+
|
|
169
|
+
this.sizeService = new ImageSizeService(this, modalEl);
|
|
170
|
+
this.uploadService = new ImageUploadService(this);
|
|
171
|
+
|
|
172
|
+
// init
|
|
173
|
+
this.$.eventManager.addEvent(modalEl.tabs, 'click', this.#OpenTab.bind(this));
|
|
174
|
+
if (this.imgInputFile) this.$.eventManager.addEvent(modalEl.fileRemoveBtn, 'click', this.#RemoveSelectedFiles.bind(this));
|
|
175
|
+
if (this.imgUrlFile) this.$.eventManager.addEvent(this.imgUrlFile, 'input', this.#OnLinkPreview.bind(this));
|
|
176
|
+
if (this.imgInputFile && this.imgUrlFile) this.$.eventManager.addEvent(this.imgInputFile, 'change', this.#OnfileInputChange.bind(this));
|
|
177
|
+
|
|
178
|
+
const galleryButton = modalEl.galleryButton;
|
|
179
|
+
if (galleryButton) this.$.eventManager.addEvent(galleryButton, 'click', this.#OpenGallery.bind(this));
|
|
180
|
+
|
|
181
|
+
if (this.pluginOptions.useFormatType) {
|
|
182
|
+
this.as = this.pluginOptions.defaultFormatType;
|
|
183
|
+
this.asBlock = modalEl.asBlock;
|
|
184
|
+
this.asInline = modalEl.asInline;
|
|
185
|
+
this.$.eventManager.addEvent([this.asBlock, this.asInline], 'click', this.#OnClickAsButton.bind(this));
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
/**
|
|
190
|
+
* @template {keyof ImageState} K
|
|
191
|
+
* @param {K} key
|
|
192
|
+
* @param {ImageState[K]} value
|
|
193
|
+
*/
|
|
194
|
+
setState(key, value) {
|
|
195
|
+
this.state[key] = value;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
* @override
|
|
200
|
+
* @type {PluginModal['open']}
|
|
201
|
+
*/
|
|
202
|
+
open() {
|
|
203
|
+
this.state.produceIndex = 0;
|
|
204
|
+
this.modal.open();
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
/**
|
|
208
|
+
* @hook Editor.Core
|
|
209
|
+
* @type {SunEditor.Hook.Core.RetainFormat}
|
|
210
|
+
*/
|
|
211
|
+
retainFormat() {
|
|
212
|
+
return {
|
|
213
|
+
query: 'img',
|
|
214
|
+
/** @param {HTMLImageElement} element */
|
|
215
|
+
method: (element) => {
|
|
216
|
+
const figureInfo = Figure.GetContainer(element);
|
|
217
|
+
if (figureInfo && figureInfo.container && (figureInfo.cover || figureInfo.inlineCover)) return;
|
|
218
|
+
|
|
219
|
+
const { w, h } = this.#ready(element, true);
|
|
220
|
+
this.#fileCheck(w, h);
|
|
221
|
+
},
|
|
222
|
+
};
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
/**
|
|
226
|
+
* @hook Editor.EventManager
|
|
227
|
+
* @type {SunEditor.Hook.Event.OnFilePasteAndDrop}
|
|
228
|
+
*/
|
|
229
|
+
onFilePasteAndDrop({ file }) {
|
|
230
|
+
if (!/^image/.test(file.type)) return;
|
|
231
|
+
|
|
232
|
+
this.submitFile([file]);
|
|
233
|
+
this.$.focusManager.focus();
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
/**
|
|
237
|
+
* @hook Modules.Modal
|
|
238
|
+
* @type {SunEditor.Hook.Modal.On}
|
|
239
|
+
*/
|
|
240
|
+
modalOn(isUpdate) {
|
|
241
|
+
if (!isUpdate) {
|
|
242
|
+
this.sizeService.on();
|
|
243
|
+
if (this.imgInputFile && this.pluginOptions.allowMultiple) this.imgInputFile.setAttribute('multiple', 'multiple');
|
|
244
|
+
} else {
|
|
245
|
+
if (this.imgInputFile && this.pluginOptions.allowMultiple) this.imgInputFile.removeAttribute('multiple');
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
this.anchor.on(isUpdate);
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
/**
|
|
252
|
+
* @hook Modules.Modal
|
|
253
|
+
* @type {SunEditor.Hook.Modal.Action}
|
|
254
|
+
*/
|
|
255
|
+
async modalAction() {
|
|
256
|
+
this.#align = /** @type {HTMLInputElement} */ (this.modal.form.querySelector('input[name="suneditor_image_radio"]:checked')).value;
|
|
257
|
+
|
|
258
|
+
if (this.modal.isUpdate) {
|
|
259
|
+
this.#fixTagStructure();
|
|
260
|
+
this.$.history.push(false);
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
if (this.imgInputFile && this.imgInputFile.files.length > 0) {
|
|
264
|
+
return await this.submitFile(this.imgInputFile.files);
|
|
265
|
+
} else if (this.imgUrlFile && this.#linkValue.length > 0) {
|
|
266
|
+
return await this.submitURL(this.#linkValue);
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
return false;
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
/**
|
|
273
|
+
* @hook Modules.Modal
|
|
274
|
+
* @type {SunEditor.Hook.Modal.Init}
|
|
275
|
+
*/
|
|
276
|
+
modalInit() {
|
|
277
|
+
Modal.OnChangeFile(this.fileModalWrapper, []);
|
|
278
|
+
if (this.imgInputFile) this.imgInputFile.value = '';
|
|
279
|
+
if (this.imgUrlFile) this.#linkValue = this.previewSrc.textContent = this.imgUrlFile.value = '';
|
|
280
|
+
if (this.imgInputFile && this.imgUrlFile) {
|
|
281
|
+
this.imgUrlFile.disabled = false;
|
|
282
|
+
this.previewSrc.style.textDecoration = '';
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
this.altText.value = '';
|
|
286
|
+
/** @type {HTMLInputElement} */ (this.modal.form.querySelector('input[name="suneditor_image_radio"][value="none"]')).checked = true;
|
|
287
|
+
this.captionCheckEl.checked = false;
|
|
288
|
+
this.#element = null;
|
|
289
|
+
this.#OpenTab('init');
|
|
290
|
+
|
|
291
|
+
this.sizeService.init();
|
|
292
|
+
|
|
293
|
+
if (this.pluginOptions.useFormatType) {
|
|
294
|
+
this.#activeAsInline((this.pluginOptions.keepFormatType ? this.as : this.pluginOptions.defaultFormatType) === FORMAT_TYPE.INLINE);
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
this.anchor.init();
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
/**
|
|
301
|
+
* @hook Editor.Component
|
|
302
|
+
* @type {SunEditor.Hook.Component.Select}
|
|
303
|
+
*/
|
|
304
|
+
componentSelect(target) {
|
|
305
|
+
this.#ready(target);
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
/**
|
|
309
|
+
* @hook Editor.Component
|
|
310
|
+
* @type {SunEditor.Hook.Component.Edit}
|
|
311
|
+
*/
|
|
312
|
+
componentEdit() {
|
|
313
|
+
this.modal.open();
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
/**
|
|
317
|
+
* @hook Editor.Component
|
|
318
|
+
* @type {SunEditor.Hook.Component.Destroy}
|
|
319
|
+
*/
|
|
320
|
+
async componentDestroy(target) {
|
|
321
|
+
const targetEl = target || this.#element;
|
|
322
|
+
const container = dom.query.getParentElement(targetEl, Figure.is) || targetEl;
|
|
323
|
+
const focusEl = container.previousElementSibling || container.nextElementSibling;
|
|
324
|
+
const emptyDiv = container.parentNode;
|
|
325
|
+
|
|
326
|
+
const message = await this.$.eventManager.triggerEvent('onImageDeleteBefore', { element: targetEl, container, align: this.#align, alt: this.altText.value, url: this.#linkValue });
|
|
327
|
+
if (message === false) return;
|
|
328
|
+
|
|
329
|
+
dom.utils.removeItem(container);
|
|
330
|
+
this.modalInit();
|
|
331
|
+
|
|
332
|
+
if (emptyDiv !== this.$.frameContext.get('wysiwyg')) {
|
|
333
|
+
this.$.nodeTransform.removeAllParents(
|
|
334
|
+
emptyDiv,
|
|
335
|
+
function (current) {
|
|
336
|
+
return current.childNodes.length === 0;
|
|
337
|
+
},
|
|
338
|
+
null,
|
|
339
|
+
);
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
// focus
|
|
343
|
+
this.$.focusManager.focusEdge(focusEl);
|
|
344
|
+
this.$.history.push(false);
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
/**
|
|
348
|
+
* @description Create an `image` component using the provided files.
|
|
349
|
+
* @param {FileList|File[]} fileList File object list
|
|
350
|
+
* @returns {Promise<boolean>} If return `false`, the file upload will be canceled
|
|
351
|
+
*/
|
|
352
|
+
async submitFile(fileList) {
|
|
353
|
+
if (fileList.length === 0) return false;
|
|
354
|
+
|
|
355
|
+
let fileSize = 0;
|
|
356
|
+
const files = [];
|
|
357
|
+
const singleSizeLimit = this.pluginOptions.uploadSingleSizeLimit;
|
|
358
|
+
for (let i = 0, len = fileList.length, f, s; i < len; i++) {
|
|
359
|
+
f = fileList[i];
|
|
360
|
+
if (!/image/i.test(f.type)) continue;
|
|
361
|
+
|
|
362
|
+
s = f.size;
|
|
363
|
+
if (singleSizeLimit > 0 && s > singleSizeLimit) {
|
|
364
|
+
const err = '[SUNEDITOR.imageUpload.fail] Size of uploadable single file: ' + singleSizeLimit / 1000 + 'KB';
|
|
365
|
+
const message = await this.$.eventManager.triggerEvent('onImageUploadError', {
|
|
366
|
+
error: err,
|
|
367
|
+
limitSize: singleSizeLimit,
|
|
368
|
+
uploadSize: s,
|
|
369
|
+
file: f,
|
|
370
|
+
});
|
|
371
|
+
|
|
372
|
+
this.$.ui.alertOpen(message === NO_EVENT ? err : message || err, 'error');
|
|
373
|
+
|
|
374
|
+
return false;
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
files.push(f);
|
|
378
|
+
fileSize += s;
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
const limitSize = this.pluginOptions.uploadSizeLimit;
|
|
382
|
+
const currentSize = this.fileManager.getSize();
|
|
383
|
+
if (limitSize > 0 && fileSize + currentSize > limitSize) {
|
|
384
|
+
const err = '[SUNEDITOR.imageUpload.fail] Size of uploadable total images: ' + limitSize / 1000 + 'KB';
|
|
385
|
+
const message = await this.$.eventManager.triggerEvent('onImageUploadError', {
|
|
386
|
+
error: err,
|
|
387
|
+
limitSize,
|
|
388
|
+
currentSize,
|
|
389
|
+
uploadSize: fileSize,
|
|
390
|
+
});
|
|
391
|
+
|
|
392
|
+
this.$.ui.alertOpen(message === NO_EVENT ? err : message || err, 'error');
|
|
393
|
+
|
|
394
|
+
return false;
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
const imgInfo = { files, ...this.#getInfo() };
|
|
398
|
+
const handler = function (uploadCallback, infos, newInfos) {
|
|
399
|
+
infos = newInfos || infos;
|
|
400
|
+
uploadCallback(infos);
|
|
401
|
+
}.bind(this, this.uploadService.serverUpload.bind(this.uploadService), imgInfo);
|
|
402
|
+
|
|
403
|
+
const result = await this.$.eventManager.triggerEvent('onImageUploadBefore', {
|
|
404
|
+
info: imgInfo,
|
|
405
|
+
handler,
|
|
406
|
+
});
|
|
407
|
+
|
|
408
|
+
if (result === undefined) return true;
|
|
409
|
+
if (result === false) return false;
|
|
410
|
+
if (result !== null && typeof result === 'object') handler(result);
|
|
411
|
+
|
|
412
|
+
if (result === true || result === NO_EVENT) handler(null);
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
/**
|
|
416
|
+
* @description Create an `image` component using the provided url.
|
|
417
|
+
* @param {string} url File url
|
|
418
|
+
* @returns {Promise<boolean>} If return `false`, the file upload will be canceled
|
|
419
|
+
*/
|
|
420
|
+
async submitURL(url) {
|
|
421
|
+
if (!(url ||= this.#linkValue)) return false;
|
|
422
|
+
|
|
423
|
+
const file = { name: url.split('/').pop(), size: 0 };
|
|
424
|
+
const imgInfo = {
|
|
425
|
+
url,
|
|
426
|
+
files: file,
|
|
427
|
+
...this.#getInfo(),
|
|
428
|
+
};
|
|
429
|
+
|
|
430
|
+
const handler = function (uploadCallback, infos, newInfos) {
|
|
431
|
+
infos = newInfos || infos;
|
|
432
|
+
uploadCallback(infos);
|
|
433
|
+
}.bind(this, this.uploadService.urlUpload.bind(this.uploadService), imgInfo);
|
|
434
|
+
|
|
435
|
+
const result = await this.$.eventManager.triggerEvent('onImageUploadBefore', {
|
|
436
|
+
info: imgInfo,
|
|
437
|
+
handler,
|
|
438
|
+
});
|
|
439
|
+
|
|
440
|
+
if (result === undefined) return true;
|
|
441
|
+
if (result === false) return false;
|
|
442
|
+
if (result !== null && typeof result === 'object') handler(result);
|
|
443
|
+
|
|
444
|
+
if (result === true || result === NO_EVENT) handler(null);
|
|
445
|
+
|
|
446
|
+
return true;
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
/**
|
|
450
|
+
* @description Creates a new image component, wraps it in a figure container with an optional anchor,
|
|
451
|
+
* - applies size and alignment settings, and inserts it into the editor.
|
|
452
|
+
* @param {string} src - The URL of the image to be inserted.
|
|
453
|
+
* @param {?Node} anchor - An optional anchor element to wrap the image. If provided, a clone is used.
|
|
454
|
+
* @param {string} width - The width value to be applied to the image.
|
|
455
|
+
* @param {string} height - The height value to be applied to the image.
|
|
456
|
+
* @param {string} align - The alignment setting for the image (e.g., 'left', 'center', 'right').
|
|
457
|
+
* @param {{name: string, size: number}} file - File metadata associated with the image
|
|
458
|
+
* @param {string} alt - The alternative text for the image.
|
|
459
|
+
* @param {boolean} isLast - Indicates whether this is the last file in the batch (used for scroll and insert actions).
|
|
460
|
+
*/
|
|
461
|
+
create(src, anchor, width, height, align, file, alt, isLast) {
|
|
462
|
+
/** @type {HTMLImageElement} */
|
|
463
|
+
const oImg = dom.utils.createElement('IMG');
|
|
464
|
+
oImg.src = src;
|
|
465
|
+
oImg.alt = alt;
|
|
466
|
+
anchor = this.#setAnchor(oImg, anchor ? anchor.cloneNode(false) : null);
|
|
467
|
+
|
|
468
|
+
const figureInfo = Figure.CreateContainer(anchor, 'se-image-container');
|
|
469
|
+
const cover = figureInfo.cover;
|
|
470
|
+
const container = figureInfo.container;
|
|
471
|
+
|
|
472
|
+
// caption
|
|
473
|
+
if (this.captionCheckEl.checked) {
|
|
474
|
+
this.#caption = Figure.CreateCaption(cover, this.$.lang.caption);
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
this.#element = oImg;
|
|
478
|
+
this.#cover = cover;
|
|
479
|
+
this.#container = container;
|
|
480
|
+
this.figure.open(oImg, { nonResizing: this.#nonResizing, nonSizeInfo: false, nonBorder: false, figureTarget: false, infoOnly: true });
|
|
481
|
+
|
|
482
|
+
// set size
|
|
483
|
+
this.sizeService.applySize(width, height);
|
|
484
|
+
|
|
485
|
+
// align
|
|
486
|
+
this.figure.setAlign(oImg, align);
|
|
487
|
+
|
|
488
|
+
this.fileManager.setFileData(oImg, file);
|
|
489
|
+
|
|
490
|
+
this.setState('produceIndex', this.state.produceIndex + 1);
|
|
491
|
+
oImg.onload = this.#OnloadImg.bind(this, oImg, this.#svgDefaultSize, container);
|
|
492
|
+
this.$.component.insert(container, { scrollTo: isLast ? true : false, insertBehavior: isLast ? null : 'line' });
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
/**
|
|
496
|
+
* @description Creates a new inline image component, wraps it in an inline figure container with an optional anchor,
|
|
497
|
+
* - applies size settings, and inserts it into the editor.
|
|
498
|
+
* @param {string} src - The URL of the image to be inserted.
|
|
499
|
+
* @param {?Node} anchor - An optional anchor element to wrap the image. If provided, a clone is used.
|
|
500
|
+
* @param {string} width - The width value to be applied to the image.
|
|
501
|
+
* @param {string} height - The height value to be applied to the image.
|
|
502
|
+
* @param {{name: string, size: number}} file - File metadata associated with the image
|
|
503
|
+
* @param {string} alt - The alternative text for the image.
|
|
504
|
+
* @param {boolean} isLast - Indicates whether this is the last file in the batch (used for scroll and insert actions).
|
|
505
|
+
*/
|
|
506
|
+
createInline(src, anchor, width, height, file, alt, isLast) {
|
|
507
|
+
/** @type {HTMLImageElement} */
|
|
508
|
+
const oImg = dom.utils.createElement('IMG');
|
|
509
|
+
oImg.src = src;
|
|
510
|
+
oImg.alt = alt;
|
|
511
|
+
anchor = this.#setAnchor(oImg, anchor ? anchor.cloneNode(false) : null);
|
|
512
|
+
|
|
513
|
+
const figureInfo = Figure.CreateInlineContainer(anchor, 'se-image-container');
|
|
514
|
+
const container = figureInfo.container;
|
|
515
|
+
|
|
516
|
+
this.#element = oImg;
|
|
517
|
+
this.#container = container;
|
|
518
|
+
this.figure.open(oImg, { nonResizing: this.#nonResizing, nonSizeInfo: false, nonBorder: false, figureTarget: false, infoOnly: true });
|
|
519
|
+
|
|
520
|
+
// set size
|
|
521
|
+
this.sizeService.applySize(width, height);
|
|
522
|
+
|
|
523
|
+
this.fileManager.setFileData(oImg, file);
|
|
524
|
+
|
|
525
|
+
this.setState('produceIndex', this.state.produceIndex + 1);
|
|
526
|
+
oImg.onload = this.#OnloadImg.bind(this, oImg, this.#svgDefaultSize, container);
|
|
527
|
+
this.$.component.insert(container, { scrollTo: isLast ? true : false, insertBehavior: isLast ? null : 'line' });
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
/**
|
|
531
|
+
* @description Prepares the component for selection.
|
|
532
|
+
* - Ensures that the controller is properly positioned and initialized.
|
|
533
|
+
* - Prevents duplicate event handling if the component is already selected.
|
|
534
|
+
* @param {HTMLElement} target - The selected element.
|
|
535
|
+
* @param {boolean} [infoOnly=false] - If `true`, only retrieves information without opening the controller.
|
|
536
|
+
* @returns {{w: string, h: string}} - The width and height of the component.
|
|
537
|
+
*/
|
|
538
|
+
#ready(target, infoOnly = false) {
|
|
539
|
+
if (!target) return;
|
|
540
|
+
const figureInfo = this.figure.open(target, { nonResizing: this.#nonResizing, nonSizeInfo: false, nonBorder: false, figureTarget: false, infoOnly });
|
|
541
|
+
this.anchor.set(dom.check.isAnchor(target.parentNode) ? target.parentNode : null);
|
|
542
|
+
|
|
543
|
+
this.#linkElement = this.anchor.currentTarget;
|
|
544
|
+
this.#element = target;
|
|
545
|
+
this.#cover = figureInfo.cover;
|
|
546
|
+
this.#container = figureInfo.container;
|
|
547
|
+
this.#caption = figureInfo.caption;
|
|
548
|
+
this.#align = figureInfo.align;
|
|
549
|
+
target.style.float = '';
|
|
550
|
+
|
|
551
|
+
this.sizeService.setOriginSize(String(figureInfo.originWidth || figureInfo.w || ''), String(figureInfo.originHeight || figureInfo.h || ''));
|
|
552
|
+
this.altText.value = this.#element.alt;
|
|
553
|
+
|
|
554
|
+
if (this.imgUrlFile) this.#linkValue = this.previewSrc.textContent = this.imgUrlFile.value = this.#element.src;
|
|
555
|
+
|
|
556
|
+
/** @type {HTMLInputElement} */
|
|
557
|
+
const activeAlign = this.modal.form.querySelector('input[name="suneditor_image_radio"][value="' + this.#align + '"]') || this.modal.form.querySelector('input[name="suneditor_image_radio"][value="none"]');
|
|
558
|
+
activeAlign.checked = true;
|
|
559
|
+
this.captionCheckEl.checked = !!this.#caption;
|
|
560
|
+
|
|
561
|
+
const { dw, dh } = this.figure.getSize(target);
|
|
562
|
+
|
|
563
|
+
if (!this.#resizing) return { w: dw, h: dh };
|
|
564
|
+
|
|
565
|
+
this.sizeService.ready(figureInfo, dw, dh);
|
|
566
|
+
|
|
567
|
+
if (this.pluginOptions.useFormatType) {
|
|
568
|
+
this.#activeAsInline(this.$.component.isInline(figureInfo.container));
|
|
569
|
+
}
|
|
570
|
+
|
|
571
|
+
return { w: dw, h: dh };
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
/**
|
|
575
|
+
* @description Retrieves the current image information.
|
|
576
|
+
* @returns {*} - The image data.
|
|
577
|
+
*/
|
|
578
|
+
#getInfo() {
|
|
579
|
+
const { w, h } = this.sizeService.getInputSize();
|
|
580
|
+
return {
|
|
581
|
+
element: this.#element,
|
|
582
|
+
anchor: this.anchor.create(true),
|
|
583
|
+
inputWidth: w,
|
|
584
|
+
inputHeight: h,
|
|
585
|
+
align: this.#align,
|
|
586
|
+
isUpdate: this.modal.isUpdate,
|
|
587
|
+
alt: this.altText.value,
|
|
588
|
+
};
|
|
589
|
+
}
|
|
590
|
+
|
|
591
|
+
/**
|
|
592
|
+
* @description Toggles between `block` and `inline` image format.
|
|
593
|
+
* @param {boolean} isInline - Whether the image should be `inline`.
|
|
594
|
+
*/
|
|
595
|
+
#activeAsInline(isInline) {
|
|
596
|
+
if (isInline) {
|
|
597
|
+
dom.utils.addClass(this.asInline, 'on');
|
|
598
|
+
dom.utils.removeClass(this.asBlock, 'on');
|
|
599
|
+
this.as = FORMAT_TYPE.INLINE;
|
|
600
|
+
// buttns
|
|
601
|
+
if (this.alignForm) this.alignForm.style.display = 'none';
|
|
602
|
+
// caption
|
|
603
|
+
if (this.captionEl) this.captionEl.style.display = 'none';
|
|
604
|
+
} else {
|
|
605
|
+
dom.utils.addClass(this.asBlock, 'on');
|
|
606
|
+
dom.utils.removeClass(this.asInline, 'on');
|
|
607
|
+
this.as = FORMAT_TYPE.BLOCK;
|
|
608
|
+
// buttns
|
|
609
|
+
if (this.alignForm) this.alignForm.style.display = '';
|
|
610
|
+
// caption
|
|
611
|
+
if (this.captionEl) this.captionEl.style.display = '';
|
|
612
|
+
}
|
|
613
|
+
}
|
|
614
|
+
|
|
615
|
+
/**
|
|
616
|
+
* @description Updates the selected image size, alt text, and caption.
|
|
617
|
+
*/
|
|
618
|
+
#fixTagStructure() {
|
|
619
|
+
const { w, h } = this.sizeService.getInputSize();
|
|
620
|
+
const width = w || 'auto';
|
|
621
|
+
const height = h || 'auto';
|
|
622
|
+
|
|
623
|
+
let imageEl = this.#element;
|
|
624
|
+
|
|
625
|
+
// as (block | inline)
|
|
626
|
+
if ((this.as === FORMAT_TYPE.BLOCK && !this.#cover) || (this.as === FORMAT_TYPE.INLINE && this.#cover)) {
|
|
627
|
+
imageEl = this.figure.convertAsFormat(imageEl, this.as);
|
|
628
|
+
}
|
|
629
|
+
|
|
630
|
+
// --- update image ---
|
|
631
|
+
const cover = this.#cover;
|
|
632
|
+
const container = this.#container === this.#cover ? null : this.#container;
|
|
633
|
+
|
|
634
|
+
// check size
|
|
635
|
+
let changeSize;
|
|
636
|
+
const x = numbers.is(width) ? width + this.state.sizeUnit : width;
|
|
637
|
+
const y = numbers.is(height) ? height + this.state.sizeUnit : height;
|
|
638
|
+
if (/%$/.test(imageEl.style.width)) {
|
|
639
|
+
changeSize = x !== container.style.width || y !== container.style.height;
|
|
640
|
+
} else {
|
|
641
|
+
changeSize = x !== imageEl.style.width || y !== imageEl.style.height;
|
|
642
|
+
}
|
|
643
|
+
|
|
644
|
+
// alt
|
|
645
|
+
imageEl.alt = this.altText.value;
|
|
646
|
+
|
|
647
|
+
// caption
|
|
648
|
+
let modifiedCaption = false;
|
|
649
|
+
if (this.captionCheckEl.checked) {
|
|
650
|
+
if (!this.#caption) {
|
|
651
|
+
this.#caption = Figure.CreateCaption(cover, this.$.lang.caption);
|
|
652
|
+
modifiedCaption = true;
|
|
653
|
+
}
|
|
654
|
+
} else {
|
|
655
|
+
if (this.#caption) {
|
|
656
|
+
dom.utils.removeItem(this.#caption);
|
|
657
|
+
this.#caption = null;
|
|
658
|
+
modifiedCaption = true;
|
|
659
|
+
}
|
|
660
|
+
}
|
|
661
|
+
|
|
662
|
+
// link
|
|
663
|
+
let isNewAnchor = false;
|
|
664
|
+
const anchor = this.anchor.create(true);
|
|
665
|
+
if (anchor) {
|
|
666
|
+
if (this.#linkElement !== anchor || !container.contains(anchor)) {
|
|
667
|
+
this.#linkElement = anchor.cloneNode(false);
|
|
668
|
+
cover.insertBefore(this.#setAnchor(imageEl, this.#linkElement), this.#caption);
|
|
669
|
+
isNewAnchor = true;
|
|
670
|
+
}
|
|
671
|
+
} else if (this.#linkElement !== null) {
|
|
672
|
+
if (cover.contains(this.#linkElement)) {
|
|
673
|
+
const newEl = imageEl.cloneNode(true);
|
|
674
|
+
cover.removeChild(this.#linkElement);
|
|
675
|
+
cover.insertBefore(newEl, this.#caption);
|
|
676
|
+
imageEl = newEl;
|
|
677
|
+
}
|
|
678
|
+
}
|
|
679
|
+
|
|
680
|
+
if (isNewAnchor) {
|
|
681
|
+
dom.utils.removeItem(anchor);
|
|
682
|
+
}
|
|
683
|
+
|
|
684
|
+
// size
|
|
685
|
+
if (this.#resizing && changeSize) {
|
|
686
|
+
this.sizeService.applySize(width, height);
|
|
687
|
+
}
|
|
688
|
+
|
|
689
|
+
// transform
|
|
690
|
+
if (modifiedCaption || (!this.state.onlyPercentage && changeSize)) {
|
|
691
|
+
if (/\d+/.test(imageEl.style.height) || (this.figure.isVertical && this.captionCheckEl.checked)) {
|
|
692
|
+
if (/auto|%$/.test(width) || /auto|%$/.test(height)) {
|
|
693
|
+
this.figure.deleteTransform(imageEl);
|
|
694
|
+
} else if (!this.#resizing || !changeSize || !this.figure.isVertical) {
|
|
695
|
+
this.figure.setTransform(imageEl, width, height, 0);
|
|
696
|
+
}
|
|
697
|
+
}
|
|
698
|
+
}
|
|
699
|
+
|
|
700
|
+
// align
|
|
701
|
+
this.figure.setAlign(imageEl, this.#align);
|
|
702
|
+
|
|
703
|
+
// select
|
|
704
|
+
imageEl.onload = () => {
|
|
705
|
+
this.componentSelect(imageEl);
|
|
706
|
+
};
|
|
707
|
+
}
|
|
708
|
+
|
|
709
|
+
/**
|
|
710
|
+
* @description Validates the image size and applies necessary transformations.
|
|
711
|
+
* @param {string} width - The width of the image.
|
|
712
|
+
* @param {string} height - The height of the image.
|
|
713
|
+
*/
|
|
714
|
+
#fileCheck(width, height) {
|
|
715
|
+
const { w, h } = this.sizeService.getInputSize();
|
|
716
|
+
width ||= w || 'auto';
|
|
717
|
+
height ||= h || 'auto';
|
|
718
|
+
|
|
719
|
+
let imageEl = this.#element;
|
|
720
|
+
let cover = this.#cover;
|
|
721
|
+
let inlineCover = null;
|
|
722
|
+
let container = this.#container === this.#cover ? null : this.#container;
|
|
723
|
+
let isNewContainer = false;
|
|
724
|
+
|
|
725
|
+
if (!cover || !container) {
|
|
726
|
+
isNewContainer = true;
|
|
727
|
+
imageEl = this.#element.cloneNode(true);
|
|
728
|
+
const figureInfo =
|
|
729
|
+
this.pluginOptions.useFormatType && width !== 'auto' && (/^span$/i.test(this.#element.parentElement?.nodeName) || this.$.format.isLine(this.#element.parentElement))
|
|
730
|
+
? Figure.CreateInlineContainer(imageEl, 'se-image-container')
|
|
731
|
+
: Figure.CreateContainer(imageEl, 'se-image-container');
|
|
732
|
+
cover = figureInfo.cover;
|
|
733
|
+
container = figureInfo.container;
|
|
734
|
+
inlineCover = figureInfo.inlineCover;
|
|
735
|
+
this.figure.open(imageEl, { nonResizing: true, nonSizeInfo: false, nonBorder: false, figureTarget: false, infoOnly: true });
|
|
736
|
+
}
|
|
737
|
+
|
|
738
|
+
// alt
|
|
739
|
+
imageEl.alt = this.altText.value;
|
|
740
|
+
|
|
741
|
+
// caption
|
|
742
|
+
let modifiedCaption = false;
|
|
743
|
+
if (!inlineCover) {
|
|
744
|
+
if (this.captionCheckEl.checked) {
|
|
745
|
+
if (!this.#caption || isNewContainer) {
|
|
746
|
+
this.#caption = Figure.CreateCaption(cover, this.$.lang.caption);
|
|
747
|
+
modifiedCaption = true;
|
|
748
|
+
}
|
|
749
|
+
} else {
|
|
750
|
+
if (this.#caption) {
|
|
751
|
+
dom.utils.removeItem(this.#caption);
|
|
752
|
+
this.#caption = null;
|
|
753
|
+
modifiedCaption = true;
|
|
754
|
+
}
|
|
755
|
+
}
|
|
756
|
+
}
|
|
757
|
+
|
|
758
|
+
// link
|
|
759
|
+
let isNewAnchor = null;
|
|
760
|
+
const anchor = this.anchor.create(true);
|
|
761
|
+
if (anchor) {
|
|
762
|
+
if (this.#linkElement !== anchor || (isNewContainer && !container.contains(anchor))) {
|
|
763
|
+
this.#linkElement = anchor.cloneNode(false);
|
|
764
|
+
cover.insertBefore(this.#setAnchor(imageEl, this.#linkElement), this.#caption);
|
|
765
|
+
isNewAnchor = this.#element;
|
|
766
|
+
}
|
|
767
|
+
} else if (this.#linkElement !== null) {
|
|
768
|
+
if (cover.contains(this.#linkElement)) {
|
|
769
|
+
const newEl = imageEl.cloneNode(true);
|
|
770
|
+
cover.removeChild(this.#linkElement);
|
|
771
|
+
cover.insertBefore(newEl, this.#caption);
|
|
772
|
+
imageEl = newEl;
|
|
773
|
+
}
|
|
774
|
+
}
|
|
775
|
+
|
|
776
|
+
if (isNewContainer) {
|
|
777
|
+
imageEl = this.#element;
|
|
778
|
+
this.figure.retainFigureFormat(container, this.#element, isNewAnchor ? anchor : null, this.fileManager);
|
|
779
|
+
this.#element = imageEl = container.querySelector('img');
|
|
780
|
+
this.#cover = cover;
|
|
781
|
+
this.#container = container;
|
|
782
|
+
}
|
|
783
|
+
|
|
784
|
+
// size
|
|
785
|
+
imageEl.style.width = '';
|
|
786
|
+
imageEl.style.height = '';
|
|
787
|
+
imageEl.removeAttribute('width');
|
|
788
|
+
imageEl.removeAttribute('height');
|
|
789
|
+
this.sizeService.applySize(width, height);
|
|
790
|
+
|
|
791
|
+
if (isNewAnchor) {
|
|
792
|
+
if (!isNewContainer) {
|
|
793
|
+
dom.utils.removeItem(anchor);
|
|
794
|
+
} else {
|
|
795
|
+
dom.utils.removeItem(isNewAnchor);
|
|
796
|
+
if (dom.query.getListChildren(anchor, (current) => /IMG/i.test(current.tagName), null).length === 0) {
|
|
797
|
+
dom.utils.removeItem(anchor);
|
|
798
|
+
}
|
|
799
|
+
}
|
|
800
|
+
}
|
|
801
|
+
|
|
802
|
+
// transform
|
|
803
|
+
if (modifiedCaption || !this.state.onlyPercentage) {
|
|
804
|
+
if (/\d+/.test(imageEl.style.height) || (this.figure.isVertical && this.captionCheckEl.checked)) {
|
|
805
|
+
if (/auto|%$/.test(width) || /auto|%$/.test(height)) {
|
|
806
|
+
this.figure.deleteTransform(imageEl);
|
|
807
|
+
} else {
|
|
808
|
+
this.figure.setTransform(imageEl, width, height, 0);
|
|
809
|
+
}
|
|
810
|
+
}
|
|
811
|
+
}
|
|
812
|
+
|
|
813
|
+
// align
|
|
814
|
+
this.figure.setAlign(imageEl, this.#align);
|
|
815
|
+
}
|
|
816
|
+
|
|
817
|
+
/**
|
|
818
|
+
* @description Wraps an image element with an anchor if provided.
|
|
819
|
+
* @param {Node} imgTag - The image element to be wrapped.
|
|
820
|
+
* @param {?Node} anchor - The anchor element to wrap around the image. If `null`, returns the image itself.
|
|
821
|
+
* @returns {Node} - The wrapped image inside the anchor or the original image element.
|
|
822
|
+
*/
|
|
823
|
+
#setAnchor(imgTag, anchor) {
|
|
824
|
+
if (anchor) {
|
|
825
|
+
anchor.appendChild(imgTag);
|
|
826
|
+
return anchor;
|
|
827
|
+
}
|
|
828
|
+
|
|
829
|
+
return imgTag;
|
|
830
|
+
}
|
|
831
|
+
|
|
832
|
+
/**
|
|
833
|
+
* @description Opens a specific tab inside the modal.
|
|
834
|
+
* @param {MouseEvent|string} e - The event object or tab name.
|
|
835
|
+
* @returns {boolean} - Whether the tab was successfully opened.
|
|
836
|
+
*/
|
|
837
|
+
#OpenTab(e) {
|
|
838
|
+
const modalForm = this.modal.form;
|
|
839
|
+
const targetElement = typeof e === 'string' ? modalForm.querySelector('._se_tab_link') : dom.query.getEventTarget(e);
|
|
840
|
+
|
|
841
|
+
if (!/^BUTTON$/i.test(targetElement.tagName)) {
|
|
842
|
+
return false;
|
|
843
|
+
}
|
|
844
|
+
|
|
845
|
+
// Declare all variables
|
|
846
|
+
const tabName = targetElement.getAttribute('data-tab-link');
|
|
847
|
+
let i;
|
|
848
|
+
|
|
849
|
+
// Get all elements with class="tabcontent" and hide them
|
|
850
|
+
const tabContent = /** @type {HTMLCollectionOf<HTMLElement>}*/ (modalForm.getElementsByClassName('_se_tab_content'));
|
|
851
|
+
for (i = 0; i < tabContent.length; i++) {
|
|
852
|
+
tabContent[i].style.display = 'none';
|
|
853
|
+
}
|
|
854
|
+
|
|
855
|
+
// Get all elements with class="tablinks" and remove the class "active"
|
|
856
|
+
const tabLinks = modalForm.getElementsByClassName('_se_tab_link');
|
|
857
|
+
for (i = 0; i < tabLinks.length; i++) {
|
|
858
|
+
dom.utils.removeClass(tabLinks[i], 'active');
|
|
859
|
+
}
|
|
860
|
+
|
|
861
|
+
// Show the current tab, and add an "active" class to the button that opened the tab
|
|
862
|
+
/** @type {HTMLElement}*/ (modalForm.querySelector('._se_tab_content_' + tabName)).style.display = 'block';
|
|
863
|
+
dom.utils.addClass(targetElement, 'active');
|
|
864
|
+
|
|
865
|
+
// focus
|
|
866
|
+
if (e !== 'init') {
|
|
867
|
+
if (tabName === 'image') {
|
|
868
|
+
this.focusElement.focus();
|
|
869
|
+
} else if (tabName === 'url') {
|
|
870
|
+
this.anchor.urlInput.focus();
|
|
871
|
+
}
|
|
872
|
+
}
|
|
873
|
+
|
|
874
|
+
return false;
|
|
875
|
+
}
|
|
876
|
+
|
|
877
|
+
#RemoveSelectedFiles() {
|
|
878
|
+
this.imgInputFile.value = '';
|
|
879
|
+
if (this.imgUrlFile) {
|
|
880
|
+
this.imgUrlFile.disabled = false;
|
|
881
|
+
this.previewSrc.style.textDecoration = '';
|
|
882
|
+
}
|
|
883
|
+
|
|
884
|
+
// inputFile check
|
|
885
|
+
Modal.OnChangeFile(this.fileModalWrapper, []);
|
|
886
|
+
}
|
|
887
|
+
|
|
888
|
+
#OnClickAsButton({ target }) {
|
|
889
|
+
this.#activeAsInline(target.getAttribute('data-command') === 'asInline');
|
|
890
|
+
}
|
|
891
|
+
|
|
892
|
+
#OnLinkPreview(e) {
|
|
893
|
+
const value = e.target.value.trim();
|
|
894
|
+
this.#linkValue = this.previewSrc.textContent = !value
|
|
895
|
+
? ''
|
|
896
|
+
: this.$.options.get('defaultUrlProtocol') && !value.includes('://') && value.indexOf('#') !== 0
|
|
897
|
+
? this.$.options.get('defaultUrlProtocol') + value
|
|
898
|
+
: !value.includes('://')
|
|
899
|
+
? '/' + value
|
|
900
|
+
: value;
|
|
901
|
+
}
|
|
902
|
+
|
|
903
|
+
#OnfileInputChange({ target }) {
|
|
904
|
+
if (!this.imgInputFile.value) {
|
|
905
|
+
this.imgUrlFile.disabled = false;
|
|
906
|
+
this.previewSrc.style.textDecoration = '';
|
|
907
|
+
} else {
|
|
908
|
+
this.imgUrlFile.disabled = true;
|
|
909
|
+
this.previewSrc.style.textDecoration = 'line-through';
|
|
910
|
+
}
|
|
911
|
+
|
|
912
|
+
// inputFile check
|
|
913
|
+
Modal.OnChangeFile(this.fileModalWrapper, target.files);
|
|
914
|
+
}
|
|
915
|
+
|
|
916
|
+
#OpenGallery() {
|
|
917
|
+
this.$.plugins.imageGallery.open(this.#SetUrlInput.bind(this));
|
|
918
|
+
}
|
|
919
|
+
|
|
920
|
+
#SetUrlInput(target) {
|
|
921
|
+
this.altText.value = target.getAttribute('data-value') || target.alt;
|
|
922
|
+
this.#linkValue = this.previewSrc.textContent = this.imgUrlFile.value = target.getAttribute('data-command') || target.src;
|
|
923
|
+
this.imgUrlFile.focus();
|
|
924
|
+
}
|
|
925
|
+
|
|
926
|
+
#OnloadImg(oImg, _svgDefaultSize, container) {
|
|
927
|
+
this.setState('produceIndex', this.state.produceIndex - 1);
|
|
928
|
+
delete oImg.onload;
|
|
929
|
+
|
|
930
|
+
// svg exception handling
|
|
931
|
+
if (oImg.offsetWidth === 0) this.sizeService.applySize(_svgDefaultSize, '');
|
|
932
|
+
|
|
933
|
+
if (this.state.produceIndex === 0) {
|
|
934
|
+
this.$.component.applyInsertBehavior(container, null, this.pluginOptions.insertBehavior || this.$.options.get('componentInsertBehavior'));
|
|
935
|
+
|
|
936
|
+
this.$.ui._iframeAutoHeight(this.$.frameContext);
|
|
937
|
+
this.$.history.push(false);
|
|
938
|
+
}
|
|
939
|
+
}
|
|
940
|
+
}
|
|
941
|
+
|
|
942
|
+
export default Image_;
|