suneditor 3.0.0-beta.3 → 3.0.0-beta.30
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CONTRIBUTING.md +8 -8
- package/README.md +44 -49
- package/dist/suneditor.min.css +1 -1
- package/dist/suneditor.min.js +1 -1
- package/package.json +95 -53
- package/src/assets/design/color.css +2 -2
- package/src/assets/design/size.css +2 -0
- package/src/assets/icons/defaultIcons.js +16 -1
- package/src/assets/suneditor-contents.css +9 -8
- package/src/assets/suneditor.css +29 -26
- package/src/core/{section → base}/actives.js +20 -12
- package/src/core/base/history.js +4 -4
- package/src/core/class/char.js +10 -10
- package/src/core/class/component.js +146 -57
- package/src/core/class/format.js +94 -2458
- package/src/core/class/html.js +187 -129
- package/src/core/class/inline.js +1853 -0
- package/src/core/class/listFormat.js +582 -0
- package/src/core/class/menu.js +14 -3
- package/src/core/class/nodeTransform.js +9 -14
- package/src/core/class/offset.js +162 -197
- package/src/core/class/selection.js +137 -34
- package/src/core/class/toolbar.js +73 -52
- package/src/core/class/ui.js +11 -11
- package/src/core/class/viewer.js +56 -55
- package/src/core/config/context.js +122 -0
- package/src/core/config/frameContext.js +204 -0
- package/src/core/config/options.js +639 -0
- package/src/core/editor.js +181 -108
- package/src/core/event/actions/index.js +229 -0
- package/src/core/event/effects/common.registry.js +60 -0
- package/src/core/event/effects/keydown.registry.js +551 -0
- package/src/core/event/effects/ruleHelpers.js +145 -0
- package/src/core/{base → event}/eventManager.js +119 -201
- package/src/core/event/executor.js +21 -0
- package/src/core/{base/eventHandlers → event/handlers}/handler_toolbar.js +4 -4
- package/src/core/{base/eventHandlers → event/handlers}/handler_ww_dragDrop.js +2 -2
- package/src/core/event/handlers/handler_ww_input.js +77 -0
- package/src/core/event/handlers/handler_ww_key.js +228 -0
- package/src/core/{base/eventHandlers → event/handlers}/handler_ww_mouse.js +3 -3
- package/src/core/event/ports.js +211 -0
- package/src/core/event/reducers/keydown.reducer.js +89 -0
- package/src/core/event/rules/keydown.rule.arrow.js +54 -0
- package/src/core/event/rules/keydown.rule.backspace.js +202 -0
- package/src/core/event/rules/keydown.rule.delete.js +126 -0
- package/src/core/event/rules/keydown.rule.enter.js +144 -0
- package/src/core/event/rules/keydown.rule.tab.js +29 -0
- package/src/core/section/constructor.js +79 -388
- package/src/core/section/documentType.js +47 -26
- package/src/core/util/instanceCheck.js +59 -0
- package/src/editorInjector/_classes.js +4 -0
- package/src/editorInjector/_core.js +17 -7
- package/src/editorInjector/index.js +10 -2
- package/src/events.js +6 -0
- package/src/helper/clipboard.js +24 -10
- package/src/helper/converter.js +17 -12
- package/src/helper/dom/domCheck.js +22 -3
- package/src/helper/dom/domQuery.js +91 -45
- package/src/helper/dom/domUtils.js +93 -19
- package/src/helper/dom/index.js +4 -0
- package/src/helper/env.js +11 -7
- package/src/helper/keyCodeMap.js +4 -3
- package/src/langs/ckb.js +1 -1
- package/src/langs/cs.js +1 -1
- package/src/langs/da.js +1 -1
- package/src/langs/de.js +1 -1
- package/src/langs/en.js +1 -1
- package/src/langs/es.js +1 -1
- package/src/langs/fa.js +1 -1
- package/src/langs/fr.js +1 -1
- package/src/langs/he.js +1 -1
- package/src/langs/hu.js +1 -1
- package/src/langs/it.js +1 -1
- package/src/langs/ja.js +1 -1
- package/src/langs/km.js +1 -1
- package/src/langs/ko.js +1 -1
- package/src/langs/lv.js +1 -1
- package/src/langs/nl.js +1 -1
- package/src/langs/pl.js +1 -1
- package/src/langs/pt_br.js +10 -10
- package/src/langs/ro.js +1 -1
- package/src/langs/ru.js +1 -1
- package/src/langs/se.js +1 -1
- package/src/langs/tr.js +1 -1
- package/src/langs/uk.js +1 -1
- package/src/langs/ur.js +1 -1
- package/src/langs/zh_cn.js +1 -1
- package/src/modules/ApiManager.js +25 -18
- package/src/modules/Browser.js +52 -61
- package/src/modules/ColorPicker.js +37 -38
- package/src/modules/Controller.js +85 -79
- package/src/modules/Figure.js +275 -187
- package/src/modules/FileManager.js +86 -92
- package/src/modules/HueSlider.js +67 -35
- package/src/modules/Modal.js +84 -77
- package/src/modules/ModalAnchorEditor.js +62 -79
- package/src/modules/SelectMenu.js +89 -86
- package/src/plugins/browser/audioGallery.js +9 -5
- package/src/plugins/browser/fileBrowser.js +10 -6
- package/src/plugins/browser/fileGallery.js +9 -5
- package/src/plugins/browser/imageGallery.js +9 -5
- package/src/plugins/browser/videoGallery.js +11 -6
- package/src/plugins/command/blockquote.js +1 -0
- package/src/plugins/command/exportPDF.js +11 -8
- package/src/plugins/command/fileUpload.js +41 -29
- package/src/plugins/command/list_bulleted.js +2 -1
- package/src/plugins/command/list_numbered.js +2 -1
- package/src/plugins/dropdown/align.js +8 -2
- package/src/plugins/dropdown/backgroundColor.js +19 -11
- package/src/plugins/dropdown/font.js +15 -9
- package/src/plugins/dropdown/fontColor.js +19 -11
- package/src/plugins/dropdown/formatBlock.js +7 -2
- package/src/plugins/dropdown/hr.js +7 -3
- package/src/plugins/dropdown/layout.js +6 -2
- package/src/plugins/dropdown/lineHeight.js +8 -3
- package/src/plugins/dropdown/list.js +2 -1
- package/src/plugins/dropdown/paragraphStyle.js +15 -11
- package/src/plugins/dropdown/{table.js → table/index.js} +514 -362
- package/src/plugins/dropdown/template.js +6 -2
- package/src/plugins/dropdown/textStyle.js +7 -3
- package/src/plugins/field/mention.js +33 -27
- package/src/plugins/input/fontSize.js +44 -37
- package/src/plugins/input/pageNavigator.js +3 -2
- package/src/plugins/modal/audio.js +90 -85
- package/src/plugins/modal/drawing.js +58 -66
- package/src/plugins/modal/embed.js +193 -180
- package/src/plugins/modal/image.js +441 -439
- package/src/plugins/modal/link.js +31 -8
- package/src/plugins/modal/math.js +23 -22
- package/src/plugins/modal/video.js +233 -230
- package/src/plugins/popup/anchor.js +24 -18
- package/src/suneditor.js +69 -24
- package/src/typedef.js +42 -19
- package/types/assets/icons/defaultIcons.d.ts +8 -0
- package/types/core/class/char.d.ts +1 -1
- package/types/core/class/component.d.ts +29 -7
- package/types/core/class/format.d.ts +4 -354
- package/types/core/class/html.d.ts +13 -4
- package/types/core/class/inline.d.ts +263 -0
- package/types/core/class/listFormat.d.ts +135 -0
- package/types/core/class/menu.d.ts +10 -2
- package/types/core/class/offset.d.ts +24 -26
- package/types/core/class/selection.d.ts +2 -0
- package/types/core/class/toolbar.d.ts +24 -11
- package/types/core/class/ui.d.ts +1 -1
- package/types/core/class/viewer.d.ts +1 -1
- package/types/core/config/context.d.ts +157 -0
- package/types/core/config/frameContext.d.ts +367 -0
- package/types/core/config/options.d.ts +1119 -0
- package/types/core/editor.d.ts +101 -66
- package/types/core/event/actions/index.d.ts +47 -0
- package/types/core/event/effects/common.registry.d.ts +50 -0
- package/types/core/event/effects/keydown.registry.d.ts +73 -0
- package/types/core/event/effects/ruleHelpers.d.ts +31 -0
- package/types/core/{base → event}/eventManager.d.ts +15 -46
- package/types/core/event/executor.d.ts +6 -0
- package/types/core/event/handlers/handler_ww_input.d.ts +41 -0
- package/types/core/{base/eventHandlers/handler_ww_key_input.d.ts → event/handlers/handler_ww_key.d.ts} +4 -6
- package/types/core/event/ports.d.ts +255 -0
- package/types/core/event/reducers/keydown.reducer.d.ts +75 -0
- package/types/core/event/rules/keydown.rule.arrow.d.ts +8 -0
- package/types/core/event/rules/keydown.rule.backspace.d.ts +9 -0
- package/types/core/event/rules/keydown.rule.delete.d.ts +9 -0
- package/types/core/event/rules/keydown.rule.enter.d.ts +9 -0
- package/types/core/event/rules/keydown.rule.tab.d.ts +9 -0
- package/types/core/section/constructor.d.ts +101 -631
- package/types/core/section/documentType.d.ts +14 -4
- package/types/core/util/instanceCheck.d.ts +50 -0
- package/types/editorInjector/_classes.d.ts +4 -0
- package/types/editorInjector/_core.d.ts +17 -7
- package/types/editorInjector/index.d.ts +10 -2
- package/types/events.d.ts +1 -0
- package/types/helper/clipboard.d.ts +2 -2
- package/types/helper/converter.d.ts +6 -9
- package/types/helper/dom/domCheck.d.ts +7 -0
- package/types/helper/dom/domQuery.d.ts +19 -8
- package/types/helper/dom/domUtils.d.ts +24 -2
- package/types/helper/dom/index.d.ts +86 -1
- package/types/helper/env.d.ts +6 -1
- package/types/helper/index.d.ts +7 -1
- package/types/helper/keyCodeMap.d.ts +3 -3
- package/types/index.d.ts +23 -117
- package/types/langs/index.d.ts +2 -2
- package/types/modules/ApiManager.d.ts +1 -8
- package/types/modules/Browser.d.ts +4 -62
- package/types/modules/ColorPicker.d.ts +4 -21
- package/types/modules/Controller.d.ts +8 -64
- package/types/modules/Figure.d.ts +54 -50
- package/types/modules/FileManager.d.ts +1 -13
- package/types/modules/HueSlider.d.ts +13 -3
- package/types/modules/Modal.d.ts +0 -43
- package/types/modules/ModalAnchorEditor.d.ts +0 -73
- package/types/modules/SelectMenu.d.ts +0 -85
- package/types/modules/index.d.ts +3 -3
- package/types/plugins/browser/audioGallery.d.ts +29 -18
- package/types/plugins/browser/fileBrowser.d.ts +38 -27
- package/types/plugins/browser/fileGallery.d.ts +29 -18
- package/types/plugins/browser/imageGallery.d.ts +24 -16
- package/types/plugins/browser/videoGallery.d.ts +29 -18
- package/types/plugins/command/blockquote.d.ts +1 -0
- package/types/plugins/command/exportPDF.d.ts +18 -18
- package/types/plugins/command/fileUpload.d.ts +65 -45
- package/types/plugins/command/list_bulleted.d.ts +1 -0
- package/types/plugins/command/list_numbered.d.ts +1 -0
- package/types/plugins/dropdown/align.d.ts +13 -8
- package/types/plugins/dropdown/backgroundColor.d.ts +30 -19
- package/types/plugins/dropdown/font.d.ts +13 -12
- package/types/plugins/dropdown/fontColor.d.ts +30 -19
- package/types/plugins/dropdown/formatBlock.d.ts +13 -8
- package/types/plugins/dropdown/hr.d.ts +15 -11
- package/types/plugins/dropdown/layout.d.ts +15 -11
- package/types/plugins/dropdown/lineHeight.d.ts +16 -11
- package/types/plugins/dropdown/list.d.ts +1 -0
- package/types/plugins/dropdown/paragraphStyle.d.ts +31 -27
- package/types/plugins/dropdown/table/index.d.ts +582 -0
- package/types/plugins/dropdown/table.d.ts +41 -86
- package/types/plugins/dropdown/template.d.ts +15 -11
- package/types/plugins/dropdown/textStyle.d.ts +19 -11
- package/types/plugins/field/mention.d.ts +58 -56
- package/types/plugins/index.d.ts +38 -38
- package/types/plugins/input/fontSize.d.ts +46 -50
- package/types/plugins/modal/audio.d.ts +26 -56
- package/types/plugins/modal/drawing.d.ts +0 -85
- package/types/plugins/modal/embed.d.ts +15 -79
- package/types/plugins/modal/image.d.ts +24 -136
- package/types/plugins/modal/link.d.ts +34 -15
- package/types/plugins/modal/math.d.ts +0 -16
- package/types/plugins/modal/video.d.ts +17 -86
- package/types/plugins/popup/anchor.d.ts +1 -8
- package/types/suneditor.d.ts +70 -19
- package/types/typedef.d.ts +60 -46
- package/src/core/base/eventHandlers/handler_ww_key_input.js +0 -1200
- package/src/core/section/context.js +0 -102
- package/types/core/section/context.d.ts +0 -45
- package/types/langs/_Lang.d.ts +0 -194
- /package/src/core/{base/eventHandlers → event/handlers}/handler_ww_clipboard.js +0 -0
- /package/types/core/{section → base}/actives.d.ts +0 -0
- /package/types/core/{base/eventHandlers → event/handlers}/handler_toolbar.d.ts +0 -0
- /package/types/core/{base/eventHandlers → event/handlers}/handler_ww_clipboard.d.ts +0 -0
- /package/types/core/{base/eventHandlers → event/handlers}/handler_ww_dragDrop.d.ts +0 -0
- /package/types/core/{base/eventHandlers → event/handlers}/handler_ww_mouse.d.ts +0 -0
|
@@ -20,6 +20,11 @@ const { NO_EVENT, ON_OVER_COMPONENT } = env;
|
|
|
20
20
|
* @property {boolean} [allowMultiple] - Whether to allow multiple file uploads.
|
|
21
21
|
* @property {string} [acceptedFormats="audio/*"] - Accepted file formats (default is "audio/*").
|
|
22
22
|
* @property {Object<string, string>} [audioTagAttributes] - Additional attributes to set on the audio tag.
|
|
23
|
+
* @property {__se__ComponentInsertBehaviorType} [insertBehavior] - Component insertion behavior for selection and cursor placement. [default: options.get('componentInsertBehavior')]
|
|
24
|
+
* - `auto`: Move cursor to the next line if possible, otherwise select the component.
|
|
25
|
+
* - `select`: Always select the inserted component.
|
|
26
|
+
* - `line`: Move cursor to the next line if possible, or create a new line and move there.
|
|
27
|
+
* - `none`: Do nothing.
|
|
23
28
|
*/
|
|
24
29
|
|
|
25
30
|
/**
|
|
@@ -39,6 +44,11 @@ class Audio_ extends EditorInjector {
|
|
|
39
44
|
return /^AUDIO$/i.test(node?.nodeName) ? node : null;
|
|
40
45
|
}
|
|
41
46
|
|
|
47
|
+
#element;
|
|
48
|
+
#defaultWidth;
|
|
49
|
+
#defaultHeight;
|
|
50
|
+
#urlValue;
|
|
51
|
+
|
|
42
52
|
/**
|
|
43
53
|
* @constructor
|
|
44
54
|
* @param {__se__EditorCore} editor - The root editor instance
|
|
@@ -62,7 +72,8 @@ class Audio_ extends EditorInjector {
|
|
|
62
72
|
uploadSingleSizeLimit: numbers.get(pluginOptions.uploadSingleSizeLimit, 0),
|
|
63
73
|
allowMultiple: !!pluginOptions.allowMultiple,
|
|
64
74
|
acceptedFormats: typeof pluginOptions.acceptedFormats !== 'string' || pluginOptions.acceptedFormats.trim() === '*' ? 'audio/*' : pluginOptions.acceptedFormats.trim() || 'audio/*',
|
|
65
|
-
audioTagAttributes: pluginOptions.audioTagAttributes || null
|
|
75
|
+
audioTagAttributes: pluginOptions.audioTagAttributes || null,
|
|
76
|
+
insertBehavior: pluginOptions.insertBehavior
|
|
66
77
|
};
|
|
67
78
|
|
|
68
79
|
// create HTML
|
|
@@ -89,12 +100,12 @@ class Audio_ extends EditorInjector {
|
|
|
89
100
|
this.audioUrlFile = modalEl.querySelector('.se-input-url');
|
|
90
101
|
/** @type {HTMLElement} */
|
|
91
102
|
this.preview = modalEl.querySelector('.se-link-preview');
|
|
92
|
-
/** @type {HTMLAudioElement} */
|
|
93
|
-
this._element = null;
|
|
94
103
|
|
|
95
|
-
|
|
96
|
-
this
|
|
97
|
-
this
|
|
104
|
+
/** @type {HTMLAudioElement} */
|
|
105
|
+
this.#element = null;
|
|
106
|
+
this.#defaultWidth = this.pluginOptions.defaultWidth;
|
|
107
|
+
this.#defaultHeight = this.pluginOptions.defaultHeight;
|
|
108
|
+
this.#urlValue = '';
|
|
98
109
|
|
|
99
110
|
const galleryButton = modalEl.querySelector('.__se__gallery');
|
|
100
111
|
if (galleryButton) this.eventManager.addEvent(galleryButton, 'click', this.#OpenGallery.bind(this));
|
|
@@ -127,8 +138,8 @@ class Audio_ extends EditorInjector {
|
|
|
127
138
|
on(isUpdate) {
|
|
128
139
|
if (!isUpdate) {
|
|
129
140
|
if (this.audioInputFile && this.pluginOptions.allowMultiple) this.audioInputFile.setAttribute('multiple', 'multiple');
|
|
130
|
-
} else if (this
|
|
131
|
-
this
|
|
141
|
+
} else if (this.#element) {
|
|
142
|
+
this.#urlValue = this.preview.textContent = this.audioUrlFile.value = this.#element.src;
|
|
132
143
|
if (this.audioInputFile && this.pluginOptions.allowMultiple) this.audioInputFile.removeAttribute('multiple');
|
|
133
144
|
} else {
|
|
134
145
|
if (this.audioInputFile && this.pluginOptions.allowMultiple) this.audioInputFile.removeAttribute('multiple');
|
|
@@ -161,8 +172,8 @@ class Audio_ extends EditorInjector {
|
|
|
161
172
|
async modalAction() {
|
|
162
173
|
if (this.audioInputFile && this.audioInputFile?.files.length > 0) {
|
|
163
174
|
return await this.submitFile(this.audioInputFile.files);
|
|
164
|
-
} else if (this.audioUrlFile && this
|
|
165
|
-
return await this.submitURL(this
|
|
175
|
+
} else if (this.audioUrlFile && this.#urlValue.length > 0) {
|
|
176
|
+
return await this.submitURL(this.#urlValue);
|
|
166
177
|
}
|
|
167
178
|
return false;
|
|
168
179
|
}
|
|
@@ -174,7 +185,7 @@ class Audio_ extends EditorInjector {
|
|
|
174
185
|
init() {
|
|
175
186
|
Modal.OnChangeFile(this.fileModalWrapper, []);
|
|
176
187
|
if (this.audioInputFile) this.audioInputFile.value = '';
|
|
177
|
-
if (this.audioUrlFile) this
|
|
188
|
+
if (this.audioUrlFile) this.#urlValue = this.preview.textContent = this.audioUrlFile.value = '';
|
|
178
189
|
if (this.audioInputFile && this.audioUrlFile) {
|
|
179
190
|
this.audioUrlFile.disabled = false;
|
|
180
191
|
this.preview.style.textDecoration = '';
|
|
@@ -189,11 +200,11 @@ class Audio_ extends EditorInjector {
|
|
|
189
200
|
controllerAction(target) {
|
|
190
201
|
switch (target.getAttribute('data-command')) {
|
|
191
202
|
case 'update':
|
|
192
|
-
if (this.audioUrlFile) this
|
|
203
|
+
if (this.audioUrlFile) this.#urlValue = this.preview.textContent = this.audioUrlFile.value = this.#element.src;
|
|
193
204
|
this.open();
|
|
194
205
|
break;
|
|
195
206
|
case 'copy': {
|
|
196
|
-
const figure = Figure.GetContainer(this
|
|
207
|
+
const figure = Figure.GetContainer(this.#element);
|
|
197
208
|
this.component.copy(figure.container);
|
|
198
209
|
break;
|
|
199
210
|
}
|
|
@@ -221,7 +232,7 @@ class Audio_ extends EditorInjector {
|
|
|
221
232
|
const figureInfo = Figure.GetContainer(element);
|
|
222
233
|
if (figureInfo && figureInfo.container && figureInfo.cover) return;
|
|
223
234
|
|
|
224
|
-
this
|
|
235
|
+
this.#setTagAttrs(element);
|
|
225
236
|
const figure = Figure.CreateContainer(element.cloneNode(true), 'se-flex-component');
|
|
226
237
|
this.figure.retainFigureFormat(figure.container, element, null, this.fileManager);
|
|
227
238
|
}
|
|
@@ -234,21 +245,8 @@ class Audio_ extends EditorInjector {
|
|
|
234
245
|
* @param {HTMLElement} target Target component element
|
|
235
246
|
*/
|
|
236
247
|
select(target) {
|
|
237
|
-
this.figure.open(target, { nonResizing: true, nonSizeInfo: true, nonBorder: true, figureTarget: true,
|
|
238
|
-
this
|
|
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 });
|
|
248
|
+
this.figure.open(target, { nonResizing: true, nonSizeInfo: true, nonBorder: true, figureTarget: true, infoOnly: false });
|
|
249
|
+
this.#ready(target);
|
|
252
250
|
}
|
|
253
251
|
|
|
254
252
|
/**
|
|
@@ -258,7 +256,7 @@ class Audio_ extends EditorInjector {
|
|
|
258
256
|
* @returns {Promise<void>}
|
|
259
257
|
*/
|
|
260
258
|
async destroy(target) {
|
|
261
|
-
const element = target || this
|
|
259
|
+
const element = target || this.#element;
|
|
262
260
|
const figure = Figure.GetContainer(element);
|
|
263
261
|
const container = figure.container || element;
|
|
264
262
|
const focusEl = container.previousElementSibling || container.nextElementSibling;
|
|
@@ -271,7 +269,7 @@ class Audio_ extends EditorInjector {
|
|
|
271
269
|
this.init();
|
|
272
270
|
this.controller.close();
|
|
273
271
|
|
|
274
|
-
if (emptyDiv !== this.
|
|
272
|
+
if (emptyDiv !== this.frameContext.get('wysiwyg')) {
|
|
275
273
|
this.nodeTransform.removeAllParents(
|
|
276
274
|
emptyDiv,
|
|
277
275
|
function (current) {
|
|
@@ -286,25 +284,6 @@ class Audio_ extends EditorInjector {
|
|
|
286
284
|
this.history.push(false);
|
|
287
285
|
}
|
|
288
286
|
|
|
289
|
-
/**
|
|
290
|
-
* @private
|
|
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
287
|
/**
|
|
309
288
|
* @description Create an "audio" component using the provided files.
|
|
310
289
|
* @param {FileList|File[]} fileList File object list
|
|
@@ -321,7 +300,7 @@ class Audio_ extends EditorInjector {
|
|
|
321
300
|
if (!/audio/i.test(f.type)) continue;
|
|
322
301
|
|
|
323
302
|
s = f.size;
|
|
324
|
-
if (slngleSizeLimit &&
|
|
303
|
+
if (slngleSizeLimit > 0 && s > slngleSizeLimit) {
|
|
325
304
|
const err = '[SUNEDITOR.audioUpload.fail] Size of uploadable single file: ' + slngleSizeLimit / 1000 + 'KB';
|
|
326
305
|
const message = await this.triggerEvent('onAudioUploadError', {
|
|
327
306
|
error: err,
|
|
@@ -352,13 +331,13 @@ class Audio_ extends EditorInjector {
|
|
|
352
331
|
const audioInfo = {
|
|
353
332
|
files,
|
|
354
333
|
isUpdate: this.modal.isUpdate,
|
|
355
|
-
element: this
|
|
334
|
+
element: this.#element
|
|
356
335
|
};
|
|
357
336
|
|
|
358
|
-
const handler = function (newInfos, infos) {
|
|
337
|
+
const handler = function (uploadCallback, newInfos, infos) {
|
|
359
338
|
infos = newInfos || infos;
|
|
360
|
-
|
|
361
|
-
}.bind(this, audioInfo);
|
|
339
|
+
uploadCallback(infos, infos.files);
|
|
340
|
+
}.bind(this, this.#serverUpload.bind(this), audioInfo);
|
|
362
341
|
|
|
363
342
|
const result = await this.triggerEvent('onAudioUploadBefore', {
|
|
364
343
|
info: audioInfo,
|
|
@@ -387,13 +366,13 @@ class Audio_ extends EditorInjector {
|
|
|
387
366
|
url,
|
|
388
367
|
files: file,
|
|
389
368
|
isUpdate: this.modal.isUpdate,
|
|
390
|
-
element: this
|
|
369
|
+
element: this.#createAudioTag()
|
|
391
370
|
};
|
|
392
371
|
|
|
393
|
-
const handler = function (newInfos, infos) {
|
|
372
|
+
const handler = function (uploadCallback, newInfos, infos) {
|
|
394
373
|
infos = newInfos || infos;
|
|
395
|
-
|
|
396
|
-
}.bind(this, audioInfo);
|
|
374
|
+
uploadCallback(infos.element, infos.url, infos.files, infos.isUpdate, true);
|
|
375
|
+
}.bind(this, this.create.bind(this), audioInfo);
|
|
397
376
|
|
|
398
377
|
const result = await this.triggerEvent('onAudioUploadBefore', {
|
|
399
378
|
info: audioInfo,
|
|
@@ -410,7 +389,6 @@ class Audio_ extends EditorInjector {
|
|
|
410
389
|
}
|
|
411
390
|
|
|
412
391
|
/**
|
|
413
|
-
* @private
|
|
414
392
|
* @description Creates or updates an audio component within the editor.
|
|
415
393
|
* - If `isUpdate` is `true`, updates the existing element's `src`.
|
|
416
394
|
* - Otherwise, inserts a new audio component with the given file.
|
|
@@ -418,23 +396,24 @@ class Audio_ extends EditorInjector {
|
|
|
418
396
|
* @param {string} src - The source URL of the audio file.
|
|
419
397
|
* @param {{name: string, size: number}} file - The file metadata (name, size).
|
|
420
398
|
* @param {boolean} isUpdate - Whether to update an existing element.
|
|
399
|
+
* @param {boolean} isLast - Indicates whether this is the last file in the batch (used for scroll and insert actions).
|
|
421
400
|
*/
|
|
422
|
-
|
|
401
|
+
create(element, src, file, isUpdate, isLast) {
|
|
423
402
|
// create new tag
|
|
424
403
|
if (!isUpdate) {
|
|
425
404
|
this.fileManager.setFileData(element, file);
|
|
426
405
|
element.src = src;
|
|
427
406
|
const figure = Figure.CreateContainer(element, 'se-flex-component');
|
|
428
|
-
if (!this.component.insert(figure.container, {
|
|
429
|
-
this.editor.focus();
|
|
407
|
+
if (!this.component.insert(figure.container, { scrollTo: isLast ? true : false, insertBehavior: isLast ? this.pluginOptions.insertBehavior : 'line' })) {
|
|
408
|
+
if (isLast) this.editor.focus();
|
|
430
409
|
return;
|
|
431
410
|
}
|
|
432
|
-
if (!this.options.get('
|
|
411
|
+
if (!this.options.get('componentInsertBehavior')) {
|
|
433
412
|
const line = this.format.addLine(figure.container, null);
|
|
434
413
|
if (line) this.selection.setRange(line, 0, line, 0);
|
|
435
414
|
}
|
|
436
415
|
} else {
|
|
437
|
-
if (this
|
|
416
|
+
if (this.#element) element = this.#element;
|
|
438
417
|
this.fileManager.setFileData(element, file);
|
|
439
418
|
if (element && element.src !== src) {
|
|
440
419
|
element.src = src;
|
|
@@ -449,27 +428,55 @@ class Audio_ extends EditorInjector {
|
|
|
449
428
|
}
|
|
450
429
|
|
|
451
430
|
/**
|
|
452
|
-
* @
|
|
431
|
+
* @description Prepares the component for selection.
|
|
432
|
+
* - Ensures that the controller is properly positioned and initialized.
|
|
433
|
+
* - Prevents duplicate event handling if the component is already selected.
|
|
434
|
+
* @param {HTMLElement} target - The selected element.
|
|
435
|
+
*/
|
|
436
|
+
#ready(target) {
|
|
437
|
+
if (_DragHandle.get('__overInfo') === ON_OVER_COMPONENT) return;
|
|
438
|
+
this.#element = /** @type {HTMLAudioElement} */ (target);
|
|
439
|
+
this.controller.open(target, null, { isWWTarget: false, addOffset: null });
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
/**
|
|
443
|
+
* @description Registers uploaded audio files and creates the corresponding audio elements.
|
|
444
|
+
* - Iterates through the uploaded files and inserts them into the editor.
|
|
445
|
+
* @param {AudioInfo_audio} info - Upload metadata, including `isUpdate` flag and `element`.
|
|
446
|
+
* @param {Object<string, *>} response - Server response containing uploaded file details.
|
|
447
|
+
*/
|
|
448
|
+
#register(info, response) {
|
|
449
|
+
const fileList = response.result;
|
|
450
|
+
|
|
451
|
+
for (let i = 0, len = fileList.length, file, oAudio; i < len; i++) {
|
|
452
|
+
if (info.isUpdate) oAudio = info.element;
|
|
453
|
+
else oAudio = this.#createAudioTag();
|
|
454
|
+
|
|
455
|
+
file = { name: fileList[i].name, size: fileList[i].size };
|
|
456
|
+
this.create(oAudio, fileList[i].url, file, info.isUpdate, i === len - 1);
|
|
457
|
+
}
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
/**
|
|
453
461
|
* @description Creates a new `<audio>` element with default attributes.
|
|
454
462
|
* - Applies width, height, and additional attributes from plugin options.
|
|
455
463
|
* @returns {HTMLAudioElement} - The newly created `<audio>` element.
|
|
456
464
|
*/
|
|
457
|
-
|
|
458
|
-
const w = this
|
|
459
|
-
const h = this
|
|
465
|
+
#createAudioTag() {
|
|
466
|
+
const w = this.#defaultWidth;
|
|
467
|
+
const h = this.#defaultHeight;
|
|
460
468
|
/** @type {HTMLAudioElement} */
|
|
461
469
|
const oAudio = dom.utils.createElement('AUDIO', { style: (w ? 'width:' + w + '; ' : '') + (h ? 'height:' + h + ';' : '') });
|
|
462
|
-
this
|
|
470
|
+
this.#setTagAttrs(oAudio);
|
|
463
471
|
return oAudio;
|
|
464
472
|
}
|
|
465
473
|
|
|
466
474
|
/**
|
|
467
|
-
* @private
|
|
468
475
|
* @description Sets attributes on an audio element based on plugin options.
|
|
469
476
|
* - Adds the `controls` attribute and applies any custom attributes.
|
|
470
477
|
* @param {HTMLElement} element - The `<audio>` element to modify.
|
|
471
478
|
*/
|
|
472
|
-
|
|
479
|
+
#setTagAttrs(element) {
|
|
473
480
|
element.setAttribute('controls', 'true');
|
|
474
481
|
|
|
475
482
|
const attrs = this.pluginOptions.audioTagAttributes;
|
|
@@ -481,21 +488,19 @@ class Audio_ extends EditorInjector {
|
|
|
481
488
|
}
|
|
482
489
|
|
|
483
490
|
/**
|
|
484
|
-
* @private
|
|
485
491
|
* @description Uploads audio files to the server.
|
|
486
492
|
* - Sends a request to the configured upload URL and processes the response.
|
|
487
493
|
* @param {AudioInfo_audio} info - Upload metadata, including `files` and `isUpdate`.
|
|
488
494
|
* @param {FileList|File[]} files - The files to be uploaded.
|
|
489
495
|
*/
|
|
490
|
-
|
|
496
|
+
#serverUpload(info, files) {
|
|
491
497
|
if (!files) return;
|
|
492
498
|
|
|
493
499
|
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.
|
|
500
|
+
this.fileManager.upload(this.pluginOptions.uploadUrl, this.pluginOptions.uploadHeaders, uploadFiles, this.#UploadCallBack.bind(this, info), this.#error.bind(this));
|
|
495
501
|
}
|
|
496
502
|
|
|
497
503
|
/**
|
|
498
|
-
* @private
|
|
499
504
|
* @description Handles errors that occur during the audio upload process.
|
|
500
505
|
* - Triggers the `onAudioUploadError` event to allow custom handling of errors.
|
|
501
506
|
* - Displays an error message in the editor's UI.
|
|
@@ -503,7 +508,7 @@ class Audio_ extends EditorInjector {
|
|
|
503
508
|
* @param {Object<string, *>} response - The error response object from the server or upload process.
|
|
504
509
|
* @returns {Promise<void>}
|
|
505
510
|
*/
|
|
506
|
-
async
|
|
511
|
+
async #error(response) {
|
|
507
512
|
const message = await this.triggerEvent('onAudioUploadError', { error: response });
|
|
508
513
|
const err = message === NO_EVENT ? response.errorMessage : message || response.errorMessage;
|
|
509
514
|
this.ui.alertOpen(err, 'error');
|
|
@@ -521,9 +526,9 @@ class Audio_ extends EditorInjector {
|
|
|
521
526
|
if ((await this.triggerEvent('audioUploadHandler', { xmlHttp, info })) === NO_EVENT) {
|
|
522
527
|
const response = JSON.parse(xmlHttp.responseText);
|
|
523
528
|
if (response.errorMessage) {
|
|
524
|
-
this
|
|
529
|
+
this.#error(response);
|
|
525
530
|
} else {
|
|
526
|
-
this
|
|
531
|
+
this.#register(info, response);
|
|
527
532
|
}
|
|
528
533
|
}
|
|
529
534
|
}
|
|
@@ -537,13 +542,13 @@ class Audio_ extends EditorInjector {
|
|
|
537
542
|
/** @type {HTMLInputElement} */
|
|
538
543
|
const target = dom.query.getEventTarget(e);
|
|
539
544
|
const value = target.value.trim();
|
|
540
|
-
this
|
|
545
|
+
this.#urlValue = this.preview.textContent = !value
|
|
541
546
|
? ''
|
|
542
547
|
: this.options.get('defaultUrlProtocol') && !value.includes('://') && value.indexOf('#') !== 0
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
548
|
+
? this.options.get('defaultUrlProtocol') + value
|
|
549
|
+
: !value.includes('://')
|
|
550
|
+
? '/' + value
|
|
551
|
+
: value;
|
|
547
552
|
}
|
|
548
553
|
|
|
549
554
|
/**
|
|
@@ -558,7 +563,7 @@ class Audio_ extends EditorInjector {
|
|
|
558
563
|
* @param {HTMLInputElement} target - The target element.
|
|
559
564
|
*/
|
|
560
565
|
#SetUrlInput(target) {
|
|
561
|
-
this
|
|
566
|
+
this.#urlValue = this.preview.textContent = this.audioUrlFile.value = target.getAttribute('data-command') || target.src;
|
|
562
567
|
this.audioUrlFile.focus();
|
|
563
568
|
}
|
|
564
569
|
|