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,37 +1,39 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { Modal, Controller,
|
|
1
|
+
import { PluginModal } from '../../interfaces';
|
|
2
|
+
import { Modal, Controller, Figure } from '../../modules/contract';
|
|
3
|
+
import { FileManager } from '../../modules/manager';
|
|
4
|
+
import { _DragHandle } from '../../modules/ui';
|
|
3
5
|
import { dom, numbers, env } from '../../helper';
|
|
4
6
|
const { NO_EVENT, ON_OVER_COMPONENT } = env;
|
|
5
7
|
|
|
6
|
-
/**
|
|
7
|
-
* @typedef {import('../../events').AudioInfo} AudioInfo_audio
|
|
8
|
-
*/
|
|
9
|
-
|
|
10
8
|
/**
|
|
11
9
|
* @typedef {Object} AudioPluginOptions
|
|
12
|
-
* @property {string} [defaultWidth="300px"] - The default width of the
|
|
13
|
-
* @property {string} [defaultHeight="150px"] - The default height of the
|
|
10
|
+
* @property {string} [defaultWidth="300px"] - The default width of the `AUDIO` tag (e.g., `"300px"`).
|
|
11
|
+
* @property {string} [defaultHeight="150px"] - The default height of the `AUDIO` tag (e.g., `"150px"`).
|
|
14
12
|
* @property {boolean} [createFileInput] - Whether to create a file input element.
|
|
15
|
-
* @property {boolean} [createUrlInput] - Whether to create a URL input element (default is true if file input is not created).
|
|
13
|
+
* @property {boolean} [createUrlInput] - Whether to create a URL input element (default is `true` if file input is not created).
|
|
16
14
|
* @property {string} [uploadUrl] - The URL to which files will be uploaded.
|
|
17
15
|
* @property {Object<string, string>} [uploadHeaders] - Headers to include in the file upload request.
|
|
18
16
|
* @property {number} [uploadSizeLimit] - The total upload size limit in bytes.
|
|
19
17
|
* @property {number} [uploadSingleSizeLimit] - The single file size limit in bytes.
|
|
20
18
|
* @property {boolean} [allowMultiple] - Whether to allow multiple file uploads.
|
|
21
|
-
* @property {string} [acceptedFormats="audio/*"] - Accepted file formats (default is "audio/*").
|
|
22
|
-
* @property {Object<string, string>} [audioTagAttributes] - Additional attributes to set on the
|
|
19
|
+
* @property {string} [acceptedFormats="audio/*"] - Accepted file formats (default is `"audio/*"`).
|
|
20
|
+
* @property {Object<string, string>} [audioTagAttributes] - Additional attributes to set on the `AUDIO` tag.
|
|
21
|
+
* @property {SunEditor.ComponentInsertType} [insertBehavior] - Component insertion behavior for selection and cursor placement. [default: `options.get('componentInsertBehavior')`]
|
|
22
|
+
* - `auto`: Move cursor to the next line if possible, otherwise select the component.
|
|
23
|
+
* - `select`: Always select the inserted component.
|
|
24
|
+
* - `line`: Move cursor to the next line if possible, or create a new line and move there.
|
|
25
|
+
* - `none`: Do nothing.
|
|
23
26
|
*/
|
|
24
27
|
|
|
25
28
|
/**
|
|
26
29
|
* @class
|
|
27
30
|
* @description Audio modal plugin.
|
|
28
31
|
*/
|
|
29
|
-
class Audio_ extends
|
|
32
|
+
class Audio_ extends PluginModal {
|
|
30
33
|
static key = 'audio';
|
|
31
|
-
static type = 'modal';
|
|
32
34
|
static className = '';
|
|
35
|
+
|
|
33
36
|
/**
|
|
34
|
-
* @this {Audio_}
|
|
35
37
|
* @param {HTMLElement} node - The node to check.
|
|
36
38
|
* @returns {HTMLElement|null} Returns a node if the node is a valid component.
|
|
37
39
|
*/
|
|
@@ -39,15 +41,20 @@ class Audio_ extends EditorInjector {
|
|
|
39
41
|
return /^AUDIO$/i.test(node?.nodeName) ? node : null;
|
|
40
42
|
}
|
|
41
43
|
|
|
44
|
+
#defaultWidth;
|
|
45
|
+
#defaultHeight;
|
|
46
|
+
#urlValue = '';
|
|
47
|
+
#element = null;
|
|
48
|
+
|
|
42
49
|
/**
|
|
43
50
|
* @constructor
|
|
44
|
-
* @param {
|
|
51
|
+
* @param {SunEditor.Kernel} editor - The core kernel
|
|
45
52
|
* @param {AudioPluginOptions} pluginOptions
|
|
46
53
|
*/
|
|
47
54
|
constructor(editor, pluginOptions) {
|
|
48
|
-
// plugin
|
|
55
|
+
// plugin basic properties
|
|
49
56
|
super(editor);
|
|
50
|
-
this.title = this
|
|
57
|
+
this.title = this.$.lang.audio;
|
|
51
58
|
this.icon = 'audio';
|
|
52
59
|
|
|
53
60
|
// define plugin options
|
|
@@ -62,24 +69,25 @@ class Audio_ extends EditorInjector {
|
|
|
62
69
|
uploadSingleSizeLimit: numbers.get(pluginOptions.uploadSingleSizeLimit, 0),
|
|
63
70
|
allowMultiple: !!pluginOptions.allowMultiple,
|
|
64
71
|
acceptedFormats: typeof pluginOptions.acceptedFormats !== 'string' || pluginOptions.acceptedFormats.trim() === '*' ? 'audio/*' : pluginOptions.acceptedFormats.trim() || 'audio/*',
|
|
65
|
-
audioTagAttributes: pluginOptions.audioTagAttributes || null
|
|
72
|
+
audioTagAttributes: pluginOptions.audioTagAttributes || null,
|
|
73
|
+
insertBehavior: pluginOptions.insertBehavior,
|
|
66
74
|
};
|
|
67
75
|
|
|
68
76
|
// create HTML
|
|
69
|
-
const modalEl = CreateHTML_modal(
|
|
70
|
-
const controllerEl = CreateHTML_controller(
|
|
77
|
+
const modalEl = CreateHTML_modal(this.$, this.pluginOptions);
|
|
78
|
+
const controllerEl = CreateHTML_controller(this.$);
|
|
71
79
|
|
|
72
80
|
// modules
|
|
73
|
-
this.modal = new Modal(this, modalEl);
|
|
74
|
-
this.controller = new Controller(this, controllerEl, { position: 'bottom', disabled: true });
|
|
75
|
-
this.fileManager = new FileManager(this, {
|
|
81
|
+
this.modal = new Modal(this, this.$, modalEl);
|
|
82
|
+
this.controller = new Controller(this, this.$, controllerEl, { position: 'bottom', disabled: true });
|
|
83
|
+
this.fileManager = new FileManager(this, this.$, {
|
|
76
84
|
query: 'audio',
|
|
77
|
-
|
|
78
|
-
|
|
85
|
+
loadEventName: 'onAudioLoad',
|
|
86
|
+
actionEventName: 'onAudioAction',
|
|
79
87
|
});
|
|
80
88
|
|
|
81
89
|
// members
|
|
82
|
-
this.figure = new Figure(this, null, {});
|
|
90
|
+
this.figure = new Figure(this, this.$, null, {});
|
|
83
91
|
|
|
84
92
|
/** @type {HTMLElement} */
|
|
85
93
|
this.fileModalWrapper = modalEl.querySelector('.se-flex-input-wrapper');
|
|
@@ -89,92 +97,99 @@ class Audio_ extends EditorInjector {
|
|
|
89
97
|
this.audioUrlFile = modalEl.querySelector('.se-input-url');
|
|
90
98
|
/** @type {HTMLElement} */
|
|
91
99
|
this.preview = modalEl.querySelector('.se-link-preview');
|
|
92
|
-
/** @type {HTMLAudioElement} */
|
|
93
|
-
this._element = null;
|
|
94
100
|
|
|
95
|
-
|
|
96
|
-
this
|
|
97
|
-
this
|
|
101
|
+
/** @type {HTMLAudioElement} */
|
|
102
|
+
this.#defaultWidth = this.pluginOptions.defaultWidth;
|
|
103
|
+
this.#defaultHeight = this.pluginOptions.defaultHeight;
|
|
98
104
|
|
|
99
105
|
const galleryButton = modalEl.querySelector('.__se__gallery');
|
|
100
|
-
if (galleryButton) this
|
|
106
|
+
if (galleryButton) this.$.eventManager.addEvent(galleryButton, 'click', this.#OpenGallery.bind(this));
|
|
101
107
|
|
|
102
108
|
// init
|
|
103
109
|
if (this.audioInputFile) {
|
|
104
|
-
this
|
|
110
|
+
this.$.eventManager.addEvent(modalEl.querySelector('.se-modal-files-edge-button'), 'click', this.#RemoveSelectedFiles.bind(this, this.audioUrlFile, this.preview));
|
|
105
111
|
if (this.audioUrlFile) {
|
|
106
|
-
this
|
|
112
|
+
this.$.eventManager.addEvent(this.audioInputFile, 'change', this.#FileInputChange.bind(this));
|
|
107
113
|
}
|
|
108
114
|
}
|
|
109
115
|
if (this.audioUrlFile) {
|
|
110
|
-
this
|
|
116
|
+
this.$.eventManager.addEvent(this.audioUrlFile, 'input', this.#OnLinkPreview.bind(this));
|
|
111
117
|
}
|
|
112
118
|
}
|
|
113
119
|
|
|
114
120
|
/**
|
|
115
|
-
* @
|
|
116
|
-
* @
|
|
121
|
+
* @override
|
|
122
|
+
* @type {PluginModal['open']}
|
|
117
123
|
*/
|
|
118
124
|
open() {
|
|
119
125
|
this.modal.open();
|
|
120
126
|
}
|
|
121
127
|
|
|
122
128
|
/**
|
|
123
|
-
* @
|
|
124
|
-
* @
|
|
125
|
-
* @param {boolean} isUpdate "Indicates whether the modal is for editing an existing component (true) or registering a new one (false)."
|
|
129
|
+
* @hook Editor.core
|
|
130
|
+
* @type {SunEditor.Hook.Core.RetainFormat}
|
|
126
131
|
*/
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
132
|
+
retainFormat() {
|
|
133
|
+
return {
|
|
134
|
+
query: 'audio',
|
|
135
|
+
method: (element) => {
|
|
136
|
+
const figureInfo = Figure.GetContainer(element);
|
|
137
|
+
if (figureInfo && figureInfo.container && figureInfo.cover) return;
|
|
138
|
+
|
|
139
|
+
this.#setTagAttrs(element);
|
|
140
|
+
const figure = Figure.CreateContainer(element.cloneNode(true), 'se-flex-component');
|
|
141
|
+
this.figure.retainFigureFormat(figure.container, element, null, this.fileManager);
|
|
142
|
+
},
|
|
143
|
+
};
|
|
136
144
|
}
|
|
137
145
|
|
|
138
146
|
/**
|
|
139
|
-
* @
|
|
140
|
-
* @
|
|
141
|
-
* @param {Object} params { frameContext, event, file }
|
|
142
|
-
* @param {__se__FrameContext} params.frameContext Frame context
|
|
143
|
-
* @param {ClipboardEvent} params.event Event object
|
|
144
|
-
* @param {File} params.file File object
|
|
145
|
-
* @returns {boolean} - If return false, the file upload will be canceled
|
|
147
|
+
* @hook Editor.EventManager
|
|
148
|
+
* @type {SunEditor.Hook.Event.OnFilePasteAndDrop}
|
|
146
149
|
*/
|
|
147
150
|
onFilePasteAndDrop({ file }) {
|
|
148
151
|
if (!/^audio/.test(file.type)) return;
|
|
149
152
|
|
|
150
153
|
this.submitFile([file]);
|
|
151
|
-
this.
|
|
154
|
+
this.$.focusManager.focus();
|
|
155
|
+
}
|
|
152
156
|
|
|
153
|
-
|
|
157
|
+
/**
|
|
158
|
+
* @hook Modules.Modal
|
|
159
|
+
* @type {SunEditor.Hook.Modal.On}
|
|
160
|
+
*/
|
|
161
|
+
modalOn(isUpdate) {
|
|
162
|
+
if (!isUpdate) {
|
|
163
|
+
if (this.audioInputFile && this.pluginOptions.allowMultiple) this.audioInputFile.setAttribute('multiple', 'multiple');
|
|
164
|
+
} else if (this.#element) {
|
|
165
|
+
this.#urlValue = this.preview.textContent = this.audioUrlFile.value = this.#element.src;
|
|
166
|
+
if (this.audioInputFile && this.pluginOptions.allowMultiple) this.audioInputFile.removeAttribute('multiple');
|
|
167
|
+
} else {
|
|
168
|
+
if (this.audioInputFile && this.pluginOptions.allowMultiple) this.audioInputFile.removeAttribute('multiple');
|
|
169
|
+
}
|
|
154
170
|
}
|
|
155
171
|
|
|
156
172
|
/**
|
|
157
|
-
* @
|
|
158
|
-
* @
|
|
159
|
-
* @returns {Promise<boolean>} Success or failure
|
|
173
|
+
* @hook Modules.Modal
|
|
174
|
+
* @type {SunEditor.Hook.Modal.Action}
|
|
160
175
|
*/
|
|
161
176
|
async modalAction() {
|
|
162
177
|
if (this.audioInputFile && this.audioInputFile?.files.length > 0) {
|
|
163
178
|
return await this.submitFile(this.audioInputFile.files);
|
|
164
|
-
} else if (this.audioUrlFile && this
|
|
165
|
-
return await this.submitURL(this
|
|
179
|
+
} else if (this.audioUrlFile && this.#urlValue.length > 0) {
|
|
180
|
+
return await this.submitURL(this.#urlValue);
|
|
166
181
|
}
|
|
167
182
|
return false;
|
|
168
183
|
}
|
|
169
184
|
|
|
170
185
|
/**
|
|
171
|
-
* @
|
|
172
|
-
* @
|
|
186
|
+
* @hook Modules.Modal
|
|
187
|
+
* @type {SunEditor.Hook.Modal.Init}
|
|
173
188
|
*/
|
|
174
|
-
|
|
189
|
+
modalInit() {
|
|
175
190
|
Modal.OnChangeFile(this.fileModalWrapper, []);
|
|
176
191
|
if (this.audioInputFile) this.audioInputFile.value = '';
|
|
177
|
-
if (this.audioUrlFile) this
|
|
192
|
+
if (this.audioUrlFile) this.#urlValue = this.preview.textContent = this.audioUrlFile.value = '';
|
|
178
193
|
if (this.audioInputFile && this.audioUrlFile) {
|
|
179
194
|
this.audioUrlFile.disabled = false;
|
|
180
195
|
this.preview.style.textDecoration = '';
|
|
@@ -182,155 +197,94 @@ class Audio_ extends EditorInjector {
|
|
|
182
197
|
}
|
|
183
198
|
|
|
184
199
|
/**
|
|
185
|
-
* @
|
|
186
|
-
* @
|
|
187
|
-
* @param {HTMLButtonElement} target Target button element
|
|
200
|
+
* @hook Modules.Controller
|
|
201
|
+
* @type {SunEditor.Hook.Controller.Action}
|
|
188
202
|
*/
|
|
189
203
|
controllerAction(target) {
|
|
190
204
|
switch (target.getAttribute('data-command')) {
|
|
191
205
|
case 'update':
|
|
192
|
-
if (this.audioUrlFile) this
|
|
206
|
+
if (this.audioUrlFile) this.#urlValue = this.preview.textContent = this.audioUrlFile.value = this.#element.src;
|
|
193
207
|
this.open();
|
|
194
208
|
break;
|
|
195
209
|
case 'copy': {
|
|
196
|
-
const figure = Figure.GetContainer(this
|
|
197
|
-
this
|
|
210
|
+
const figure = Figure.GetContainer(this.#element);
|
|
211
|
+
this.$.component.copy(figure.container);
|
|
198
212
|
break;
|
|
199
213
|
}
|
|
200
214
|
case 'delete':
|
|
201
|
-
this.
|
|
215
|
+
this.componentDestroy(null);
|
|
202
216
|
break;
|
|
203
217
|
}
|
|
204
218
|
}
|
|
205
219
|
|
|
206
220
|
/**
|
|
207
|
-
* @
|
|
208
|
-
* @
|
|
209
|
-
* - It ensures that the structure and attributes of the element are maintained and secure.
|
|
210
|
-
* - The method checks if the element is already wrapped in a valid container and updates its attributes if necessary.
|
|
211
|
-
* - If the element isn't properly contained, a new container is created to retain the format.
|
|
212
|
-
* @returns {{query: string, method: (element: HTMLAudioElement) => void}} The format retention object containing the query and method to process the element.
|
|
213
|
-
* - query: The selector query to identify the relevant elements (in this case, 'audio').
|
|
214
|
-
* - method:The function to execute on the element to validate and preserve its format.
|
|
215
|
-
* - The function takes the element as an argument, checks if it is contained correctly, and applies necessary adjustments.
|
|
221
|
+
* @hook Editor.Component
|
|
222
|
+
* @type {SunEditor.Hook.Component.Select}
|
|
216
223
|
*/
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
method: (element) => {
|
|
221
|
-
const figureInfo = Figure.GetContainer(element);
|
|
222
|
-
if (figureInfo && figureInfo.container && figureInfo.cover) return;
|
|
223
|
-
|
|
224
|
-
this._setTagAttrs(element);
|
|
225
|
-
const figure = Figure.CreateContainer(element.cloneNode(true), 'se-flex-component');
|
|
226
|
-
this.figure.retainFigureFormat(figure.container, element, null, this.fileManager);
|
|
227
|
-
}
|
|
228
|
-
};
|
|
224
|
+
componentSelect(target) {
|
|
225
|
+
this.figure.open(target, { nonResizing: true, nonSizeInfo: true, nonBorder: true, figureTarget: true, infoOnly: false });
|
|
226
|
+
this.#ready(target);
|
|
229
227
|
}
|
|
230
228
|
|
|
231
229
|
/**
|
|
232
|
-
* @
|
|
233
|
-
* @
|
|
234
|
-
* @param {HTMLElement} target Target component element
|
|
230
|
+
* @hook Editor.Component
|
|
231
|
+
* @type {SunEditor.Hook.Component.Destroy}
|
|
235
232
|
*/
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
this._ready(target);
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
/**
|
|
242
|
-
* @private
|
|
243
|
-
* @description Prepares the component for selection.
|
|
244
|
-
* - Ensures that the controller is properly positioned and initialized.
|
|
245
|
-
* - Prevents duplicate event handling if the component is already selected.
|
|
246
|
-
* @param {HTMLElement} target - The selected element.
|
|
247
|
-
*/
|
|
248
|
-
_ready(target) {
|
|
249
|
-
if (_DragHandle.get('__overInfo') === ON_OVER_COMPONENT) return;
|
|
250
|
-
this._element = /** @type {HTMLAudioElement} */ (target);
|
|
251
|
-
this.controller.open(target, null, { isWWTarget: false, addOffset: null });
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
/**
|
|
255
|
-
* @editorMethod Editor.Component
|
|
256
|
-
* @description Method to delete a component of a plugin, called by the "FileManager", "Controller" module.
|
|
257
|
-
* @param {HTMLElement=} target Target element, if null current selected element
|
|
258
|
-
* @returns {Promise<void>}
|
|
259
|
-
*/
|
|
260
|
-
async destroy(target) {
|
|
261
|
-
const element = target || this._element;
|
|
233
|
+
async componentDestroy(target) {
|
|
234
|
+
const element = target || this.#element;
|
|
262
235
|
const figure = Figure.GetContainer(element);
|
|
263
236
|
const container = figure.container || element;
|
|
264
237
|
const focusEl = container.previousElementSibling || container.nextElementSibling;
|
|
265
238
|
|
|
266
|
-
const message = await this.triggerEvent('onAudioDeleteBefore', { element: element, container: figure, url: element.getAttribute('src') });
|
|
239
|
+
const message = await this.$.eventManager.triggerEvent('onAudioDeleteBefore', { element: element, container: figure, url: element.getAttribute('src') });
|
|
267
240
|
if (message === false) return;
|
|
268
241
|
|
|
269
242
|
const emptyDiv = container.parentNode;
|
|
270
243
|
dom.utils.removeItem(container);
|
|
271
|
-
this.
|
|
244
|
+
this.modalInit();
|
|
272
245
|
this.controller.close();
|
|
273
246
|
|
|
274
|
-
if (emptyDiv !== this
|
|
275
|
-
this
|
|
247
|
+
if (emptyDiv !== this.$.frameContext.get('wysiwyg')) {
|
|
248
|
+
this.$.nodeTransform.removeAllParents(
|
|
276
249
|
emptyDiv,
|
|
277
250
|
function (current) {
|
|
278
251
|
return current.childNodes.length === 0;
|
|
279
252
|
},
|
|
280
|
-
null
|
|
253
|
+
null,
|
|
281
254
|
);
|
|
282
255
|
}
|
|
283
256
|
|
|
284
257
|
// focus
|
|
285
|
-
this.
|
|
286
|
-
this
|
|
258
|
+
this.$.focusManager.focusEdge(focusEl);
|
|
259
|
+
this.$.history.push(false);
|
|
287
260
|
}
|
|
288
261
|
|
|
289
262
|
/**
|
|
290
|
-
* @
|
|
291
|
-
* @description Registers uploaded audio files and creates the corresponding audio elements.
|
|
292
|
-
* - Iterates through the uploaded files and inserts them into the editor.
|
|
293
|
-
* @param {AudioInfo_audio} info - Upload metadata, including `isUpdate` flag and `element`.
|
|
294
|
-
* @param {Object<string, *>} response - Server response containing uploaded file details.
|
|
295
|
-
*/
|
|
296
|
-
_register(info, response) {
|
|
297
|
-
const fileList = response.result;
|
|
298
|
-
|
|
299
|
-
for (let i = 0, len = fileList.length, file, oAudio; i < len; i++) {
|
|
300
|
-
if (info.isUpdate) oAudio = info.element;
|
|
301
|
-
else oAudio = this._createAudioTag();
|
|
302
|
-
|
|
303
|
-
file = { name: fileList[i].name, size: fileList[i].size };
|
|
304
|
-
this._createComp(oAudio, fileList[i].url, file, info.isUpdate);
|
|
305
|
-
}
|
|
306
|
-
}
|
|
307
|
-
|
|
308
|
-
/**
|
|
309
|
-
* @description Create an "audio" component using the provided files.
|
|
263
|
+
* @description Create an `audio` component using the provided files.
|
|
310
264
|
* @param {FileList|File[]} fileList File object list
|
|
311
|
-
* @returns {Promise<boolean>} If return false
|
|
265
|
+
* @returns {Promise<boolean>} If return `false`, the file upload will be canceled
|
|
312
266
|
*/
|
|
313
267
|
async submitFile(fileList) {
|
|
314
268
|
if (fileList.length === 0) return false;
|
|
315
269
|
|
|
316
270
|
let fileSize = 0;
|
|
317
271
|
const files = [];
|
|
318
|
-
const
|
|
272
|
+
const singleSizeLimit = this.pluginOptions.uploadSingleSizeLimit;
|
|
319
273
|
for (let i = 0, len = fileList.length, f, s; i < len; i++) {
|
|
320
274
|
f = fileList[i];
|
|
321
275
|
if (!/audio/i.test(f.type)) continue;
|
|
322
276
|
|
|
323
277
|
s = f.size;
|
|
324
|
-
if (
|
|
325
|
-
const err = '[SUNEDITOR.audioUpload.fail] Size of uploadable single file: ' +
|
|
326
|
-
const message = await this.triggerEvent('onAudioUploadError', {
|
|
278
|
+
if (singleSizeLimit > 0 && s > singleSizeLimit) {
|
|
279
|
+
const err = '[SUNEDITOR.audioUpload.fail] Size of uploadable single file: ' + singleSizeLimit / 1000 + 'KB';
|
|
280
|
+
const message = await this.$.eventManager.triggerEvent('onAudioUploadError', {
|
|
327
281
|
error: err,
|
|
328
|
-
limitSize:
|
|
282
|
+
limitSize: singleSizeLimit,
|
|
329
283
|
uploadSize: s,
|
|
330
|
-
file: f
|
|
284
|
+
file: f,
|
|
331
285
|
});
|
|
332
286
|
|
|
333
|
-
this
|
|
287
|
+
this.$.ui.alertOpen(message === NO_EVENT ? err : message || err, 'error');
|
|
334
288
|
|
|
335
289
|
return false;
|
|
336
290
|
}
|
|
@@ -342,9 +296,9 @@ class Audio_ extends EditorInjector {
|
|
|
342
296
|
const limitSize = this.pluginOptions.uploadSizeLimit;
|
|
343
297
|
if (limitSize > 0 && fileSize + this.fileManager.getSize() > limitSize) {
|
|
344
298
|
const err = '[SUNEDITOR.audioUpload.fail] Size of uploadable total audios: ' + limitSize / 1000 + 'KB';
|
|
345
|
-
const message = await this.triggerEvent('onAudioUploadError', { error: err, limitSize, currentSize: this.fileManager.getSize(), uploadSize: fileSize });
|
|
299
|
+
const message = await this.$.eventManager.triggerEvent('onAudioUploadError', { error: err, limitSize, currentSize: this.fileManager.getSize(), uploadSize: fileSize });
|
|
346
300
|
|
|
347
|
-
this
|
|
301
|
+
this.$.ui.alertOpen(message === NO_EVENT ? err : message || err, 'error');
|
|
348
302
|
|
|
349
303
|
return false;
|
|
350
304
|
}
|
|
@@ -352,17 +306,17 @@ class Audio_ extends EditorInjector {
|
|
|
352
306
|
const audioInfo = {
|
|
353
307
|
files,
|
|
354
308
|
isUpdate: this.modal.isUpdate,
|
|
355
|
-
element: this
|
|
309
|
+
element: this.#element,
|
|
356
310
|
};
|
|
357
311
|
|
|
358
|
-
const handler = function (newInfos, infos) {
|
|
312
|
+
const handler = function (uploadCallback, newInfos, infos) {
|
|
359
313
|
infos = newInfos || infos;
|
|
360
|
-
|
|
361
|
-
}.bind(this, audioInfo);
|
|
314
|
+
uploadCallback(infos, infos.files);
|
|
315
|
+
}.bind(this, this.#serverUpload.bind(this), audioInfo);
|
|
362
316
|
|
|
363
|
-
const result = await this.triggerEvent('onAudioUploadBefore', {
|
|
317
|
+
const result = await this.$.eventManager.triggerEvent('onAudioUploadBefore', {
|
|
364
318
|
info: audioInfo,
|
|
365
|
-
handler
|
|
319
|
+
handler,
|
|
366
320
|
});
|
|
367
321
|
|
|
368
322
|
if (typeof result === 'undefined') return true;
|
|
@@ -375,7 +329,7 @@ class Audio_ extends EditorInjector {
|
|
|
375
329
|
}
|
|
376
330
|
|
|
377
331
|
/**
|
|
378
|
-
* @description Create an
|
|
332
|
+
* @description Create an `audio` component using the provided url.
|
|
379
333
|
* @param {string} url File url
|
|
380
334
|
* @returns {Promise<boolean>}
|
|
381
335
|
*/
|
|
@@ -387,17 +341,17 @@ class Audio_ extends EditorInjector {
|
|
|
387
341
|
url,
|
|
388
342
|
files: file,
|
|
389
343
|
isUpdate: this.modal.isUpdate,
|
|
390
|
-
element: this
|
|
344
|
+
element: this.#createAudioTag(),
|
|
391
345
|
};
|
|
392
346
|
|
|
393
|
-
const handler = function (newInfos, infos) {
|
|
347
|
+
const handler = function (uploadCallback, newInfos, infos) {
|
|
394
348
|
infos = newInfos || infos;
|
|
395
|
-
|
|
396
|
-
}.bind(this, audioInfo);
|
|
349
|
+
uploadCallback(infos.element, infos.url, infos.files, infos.isUpdate, true);
|
|
350
|
+
}.bind(this, this.create.bind(this), audioInfo);
|
|
397
351
|
|
|
398
|
-
const result = await this.triggerEvent('onAudioUploadBefore', {
|
|
352
|
+
const result = await this.$.eventManager.triggerEvent('onAudioUploadBefore', {
|
|
399
353
|
info: audioInfo,
|
|
400
|
-
handler
|
|
354
|
+
handler,
|
|
401
355
|
});
|
|
402
356
|
|
|
403
357
|
if (typeof result === 'undefined') return true;
|
|
@@ -410,66 +364,94 @@ class Audio_ extends EditorInjector {
|
|
|
410
364
|
}
|
|
411
365
|
|
|
412
366
|
/**
|
|
413
|
-
* @
|
|
414
|
-
* @description Creates or updates an audio component within the editor.
|
|
367
|
+
* @description Creates or updates an `audio` component within the editor.
|
|
415
368
|
* - If `isUpdate` is `true`, updates the existing element's `src`.
|
|
416
|
-
* - Otherwise, inserts a new audio component with the given file.
|
|
417
|
-
* @param {HTMLAudioElement} element - The target
|
|
369
|
+
* - Otherwise, inserts a new `audio` component with the given file.
|
|
370
|
+
* @param {HTMLAudioElement} element - The target `AUDIO` element.
|
|
418
371
|
* @param {string} src - The source URL of the audio file.
|
|
419
372
|
* @param {{name: string, size: number}} file - The file metadata (name, size).
|
|
420
373
|
* @param {boolean} isUpdate - Whether to update an existing element.
|
|
374
|
+
* @param {boolean} isLast - Indicates whether this is the last file in the batch (used for scroll and insert actions).
|
|
421
375
|
*/
|
|
422
|
-
|
|
376
|
+
create(element, src, file, isUpdate, isLast) {
|
|
423
377
|
// create new tag
|
|
424
378
|
if (!isUpdate) {
|
|
425
379
|
this.fileManager.setFileData(element, file);
|
|
426
380
|
element.src = src;
|
|
427
381
|
const figure = Figure.CreateContainer(element, 'se-flex-component');
|
|
428
|
-
if (!this
|
|
429
|
-
this.
|
|
382
|
+
if (!this.$.component.insert(figure.container, { scrollTo: isLast ? true : false, insertBehavior: isLast ? this.pluginOptions.insertBehavior : 'line' })) {
|
|
383
|
+
if (isLast) this.$.focusManager.focus();
|
|
430
384
|
return;
|
|
431
385
|
}
|
|
432
|
-
if (!this
|
|
433
|
-
const line = this
|
|
434
|
-
if (line) this
|
|
386
|
+
if (!this.$.options.get('componentInsertBehavior')) {
|
|
387
|
+
const line = this.$.format.addLine(figure.container, null);
|
|
388
|
+
if (line) this.$.selection.setRange(line, 0, line, 0);
|
|
435
389
|
}
|
|
436
390
|
} else {
|
|
437
|
-
if (this
|
|
391
|
+
if (this.#element) element = this.#element;
|
|
438
392
|
this.fileManager.setFileData(element, file);
|
|
439
393
|
if (element && element.src !== src) {
|
|
440
394
|
element.src = src;
|
|
441
|
-
this
|
|
395
|
+
this.$.component.select(element, Audio_.key);
|
|
442
396
|
} else {
|
|
443
|
-
this
|
|
397
|
+
this.$.component.select(element, Audio_.key);
|
|
444
398
|
return;
|
|
445
399
|
}
|
|
446
400
|
}
|
|
447
401
|
|
|
448
|
-
if (isUpdate) this
|
|
402
|
+
if (isUpdate) this.$.history.push(false);
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
/**
|
|
406
|
+
* @description Prepares the component for selection.
|
|
407
|
+
* - Ensures that the controller is properly positioned and initialized.
|
|
408
|
+
* - Prevents duplicate event handling if the component is already selected.
|
|
409
|
+
* @param {HTMLElement} target - The selected element.
|
|
410
|
+
*/
|
|
411
|
+
#ready(target) {
|
|
412
|
+
if (_DragHandle.get('__overInfo') === ON_OVER_COMPONENT) return;
|
|
413
|
+
this.#element = /** @type {HTMLAudioElement} */ (target);
|
|
414
|
+
this.controller.open(target, null, { isWWTarget: false, addOffset: null });
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
/**
|
|
418
|
+
* @description Registers uploaded audio files and creates the corresponding audio elements.
|
|
419
|
+
* - Iterates through the uploaded files and inserts them into the editor.
|
|
420
|
+
* @param {SunEditor.EventParams.AudioInfo} info - Upload metadata, including `isUpdate` flag and `element`.
|
|
421
|
+
* @param {Object<string, *>} response - Server response containing uploaded file details.
|
|
422
|
+
*/
|
|
423
|
+
#register(info, response) {
|
|
424
|
+
const fileList = response.result;
|
|
425
|
+
|
|
426
|
+
for (let i = 0, len = fileList.length, file, oAudio; i < len; i++) {
|
|
427
|
+
if (info.isUpdate) oAudio = info.element;
|
|
428
|
+
else oAudio = this.#createAudioTag();
|
|
429
|
+
|
|
430
|
+
file = { name: fileList[i].name, size: fileList[i].size };
|
|
431
|
+
this.create(oAudio, fileList[i].url, file, info.isUpdate, i === len - 1);
|
|
432
|
+
}
|
|
449
433
|
}
|
|
450
434
|
|
|
451
435
|
/**
|
|
452
|
-
* @
|
|
453
|
-
* @description Creates a new `<audio>` element with default attributes.
|
|
436
|
+
* @description Creates a new `AUDIO` element with default attributes.
|
|
454
437
|
* - Applies width, height, and additional attributes from plugin options.
|
|
455
|
-
* @returns {HTMLAudioElement} - The newly created
|
|
438
|
+
* @returns {HTMLAudioElement} - The newly created `AUDIO` element.
|
|
456
439
|
*/
|
|
457
|
-
|
|
458
|
-
const w = this
|
|
459
|
-
const h = this
|
|
440
|
+
#createAudioTag() {
|
|
441
|
+
const w = this.#defaultWidth;
|
|
442
|
+
const h = this.#defaultHeight;
|
|
460
443
|
/** @type {HTMLAudioElement} */
|
|
461
444
|
const oAudio = dom.utils.createElement('AUDIO', { style: (w ? 'width:' + w + '; ' : '') + (h ? 'height:' + h + ';' : '') });
|
|
462
|
-
this
|
|
445
|
+
this.#setTagAttrs(oAudio);
|
|
463
446
|
return oAudio;
|
|
464
447
|
}
|
|
465
448
|
|
|
466
449
|
/**
|
|
467
|
-
* @
|
|
468
|
-
* @description Sets attributes on an audio element based on plugin options.
|
|
450
|
+
* @description Sets attributes on an `AUDIO` element based on plugin options.
|
|
469
451
|
* - Adds the `controls` attribute and applies any custom attributes.
|
|
470
|
-
* @param {HTMLElement} element - The
|
|
452
|
+
* @param {HTMLElement} element - The `AUDIO` element to modify.
|
|
471
453
|
*/
|
|
472
|
-
|
|
454
|
+
#setTagAttrs(element) {
|
|
473
455
|
element.setAttribute('controls', 'true');
|
|
474
456
|
|
|
475
457
|
const attrs = this.pluginOptions.audioTagAttributes;
|
|
@@ -481,21 +463,19 @@ class Audio_ extends EditorInjector {
|
|
|
481
463
|
}
|
|
482
464
|
|
|
483
465
|
/**
|
|
484
|
-
* @private
|
|
485
466
|
* @description Uploads audio files to the server.
|
|
486
467
|
* - Sends a request to the configured upload URL and processes the response.
|
|
487
|
-
* @param {
|
|
468
|
+
* @param {SunEditor.EventParams.AudioInfo} info - Upload metadata, including `files` and `isUpdate`.
|
|
488
469
|
* @param {FileList|File[]} files - The files to be uploaded.
|
|
489
470
|
*/
|
|
490
|
-
|
|
471
|
+
#serverUpload(info, files) {
|
|
491
472
|
if (!files) return;
|
|
492
473
|
|
|
493
474
|
const uploadFiles = this.modal.isUpdate ? [files[0]] : files;
|
|
494
|
-
this.fileManager.upload(this.pluginOptions.uploadUrl, this.pluginOptions.uploadHeaders, uploadFiles, this.#UploadCallBack.bind(this, info), this.
|
|
475
|
+
this.fileManager.upload(this.pluginOptions.uploadUrl, this.pluginOptions.uploadHeaders, uploadFiles, this.#UploadCallBack.bind(this, info), this.#error.bind(this));
|
|
495
476
|
}
|
|
496
477
|
|
|
497
478
|
/**
|
|
498
|
-
* @private
|
|
499
479
|
* @description Handles errors that occur during the audio upload process.
|
|
500
480
|
* - Triggers the `onAudioUploadError` event to allow custom handling of errors.
|
|
501
481
|
* - Displays an error message in the editor's UI.
|
|
@@ -503,10 +483,10 @@ class Audio_ extends EditorInjector {
|
|
|
503
483
|
* @param {Object<string, *>} response - The error response object from the server or upload process.
|
|
504
484
|
* @returns {Promise<void>}
|
|
505
485
|
*/
|
|
506
|
-
async
|
|
507
|
-
const message = await this.triggerEvent('onAudioUploadError', { error: response });
|
|
486
|
+
async #error(response) {
|
|
487
|
+
const message = await this.$.eventManager.triggerEvent('onAudioUploadError', { error: response });
|
|
508
488
|
const err = message === NO_EVENT ? response.errorMessage : message || response.errorMessage;
|
|
509
|
-
this
|
|
489
|
+
this.$.ui.alertOpen(err, 'error');
|
|
510
490
|
console.error('[SUNEDITOR.plugin.audio.error]', err);
|
|
511
491
|
}
|
|
512
492
|
|
|
@@ -514,16 +494,16 @@ class Audio_ extends EditorInjector {
|
|
|
514
494
|
* @description Handles the server response after a file upload.
|
|
515
495
|
* - If the upload is successful, registers the uploaded audio.
|
|
516
496
|
* - If an error occurs, triggers an error event.
|
|
517
|
-
* @param {
|
|
497
|
+
* @param {SunEditor.EventParams.AudioInfo} info - Upload metadata.
|
|
518
498
|
* @param {XMLHttpRequest} xmlHttp - The completed XHR request.
|
|
519
499
|
*/
|
|
520
500
|
async #UploadCallBack(info, xmlHttp) {
|
|
521
|
-
if ((await this.triggerEvent('audioUploadHandler', { xmlHttp, info })) === NO_EVENT) {
|
|
501
|
+
if ((await this.$.eventManager.triggerEvent('audioUploadHandler', { xmlHttp, info })) === NO_EVENT) {
|
|
522
502
|
const response = JSON.parse(xmlHttp.responseText);
|
|
523
503
|
if (response.errorMessage) {
|
|
524
|
-
this
|
|
504
|
+
this.#error(response);
|
|
525
505
|
} else {
|
|
526
|
-
this
|
|
506
|
+
this.#register(info, response);
|
|
527
507
|
}
|
|
528
508
|
}
|
|
529
509
|
}
|
|
@@ -537,13 +517,13 @@ class Audio_ extends EditorInjector {
|
|
|
537
517
|
/** @type {HTMLInputElement} */
|
|
538
518
|
const target = dom.query.getEventTarget(e);
|
|
539
519
|
const value = target.value.trim();
|
|
540
|
-
this
|
|
520
|
+
this.#urlValue = this.preview.textContent = !value
|
|
541
521
|
? ''
|
|
542
|
-
: this
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
522
|
+
: this.$.options.get('defaultUrlProtocol') && !value.includes('://') && value.indexOf('#') !== 0
|
|
523
|
+
? this.$.options.get('defaultUrlProtocol') + value
|
|
524
|
+
: !value.includes('://')
|
|
525
|
+
? '/' + value
|
|
526
|
+
: value;
|
|
547
527
|
}
|
|
548
528
|
|
|
549
529
|
/**
|
|
@@ -551,14 +531,14 @@ class Audio_ extends EditorInjector {
|
|
|
551
531
|
* - Calls a function to populate the URL input with the selected audio file.
|
|
552
532
|
*/
|
|
553
533
|
#OpenGallery() {
|
|
554
|
-
this
|
|
534
|
+
this.$.plugins.audioGallery.open(this.#SetUrlInput.bind(this));
|
|
555
535
|
}
|
|
556
536
|
|
|
557
537
|
/**
|
|
558
538
|
* @param {HTMLInputElement} target - The target element.
|
|
559
539
|
*/
|
|
560
540
|
#SetUrlInput(target) {
|
|
561
|
-
this
|
|
541
|
+
this.#urlValue = this.preview.textContent = this.audioUrlFile.value = target.getAttribute('data-command') || target.src;
|
|
562
542
|
this.audioUrlFile.focus();
|
|
563
543
|
}
|
|
564
544
|
|
|
@@ -598,6 +578,11 @@ class Audio_ extends EditorInjector {
|
|
|
598
578
|
}
|
|
599
579
|
}
|
|
600
580
|
|
|
581
|
+
/**
|
|
582
|
+
* @param {SunEditor.Deps} $ - Kernel dependencies
|
|
583
|
+
* @param {import('./audio').AudioPluginOptions} pluginOptions - Audio plugin options
|
|
584
|
+
* @returns {HTMLElement}
|
|
585
|
+
*/
|
|
601
586
|
function CreateHTML_modal({ lang, icons, plugins }, pluginOptions) {
|
|
602
587
|
let html = /*html*/ `
|
|
603
588
|
<form method="post" enctype="multipart/form-data">
|
|
@@ -645,6 +630,10 @@ function CreateHTML_modal({ lang, icons, plugins }, pluginOptions) {
|
|
|
645
630
|
return dom.utils.createElement('DIV', { class: 'se-modal-content' }, html);
|
|
646
631
|
}
|
|
647
632
|
|
|
633
|
+
/**
|
|
634
|
+
* @param {SunEditor.Deps} $ - Kernel dependencies
|
|
635
|
+
* @returns {HTMLElement}
|
|
636
|
+
*/
|
|
648
637
|
function CreateHTML_controller({ lang, icons }) {
|
|
649
638
|
const html = /*html*/ `
|
|
650
639
|
<div class="se-arrow se-arrow-up"></div>
|