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
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import EditorInjector from '../../editorInjector';
|
|
2
2
|
import { Modal, Figure, FileManager } from '../../modules';
|
|
3
3
|
import { dom, numbers, env, converter, keyCodeMap } from '../../helper';
|
|
4
|
-
const { NO_EVENT } = env;
|
|
4
|
+
const { _w, NO_EVENT } = env;
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* @typedef {import('../../events').VideoInfo} VideoInfo_video
|
|
@@ -37,6 +37,11 @@ const { NO_EVENT } = env;
|
|
|
37
37
|
* @property {Array<RegExp>} [urlPatterns] - Additional URL patterns for video embedding.
|
|
38
38
|
* @property {Array<string>} [extensions] - Additional file extensions to be recognized for video uploads.
|
|
39
39
|
* @property {FigureControls_video} [controls] - Figure controls.
|
|
40
|
+
* @property {__se__ComponentInsertBehaviorType} [insertBehavior] - Component insertion behavior for selection and cursor placement. [default: options.get('componentInsertBehavior')]
|
|
41
|
+
* - `auto`: Move cursor to the next line if possible, otherwise select the component.
|
|
42
|
+
* - `select`: Always select the inserted component.
|
|
43
|
+
* - `line`: Move cursor to the next line if possible, or create a new line and move there.
|
|
44
|
+
* - `none`: Do nothing.
|
|
40
45
|
*/
|
|
41
46
|
|
|
42
47
|
/**
|
|
@@ -63,6 +68,22 @@ class Video extends EditorInjector {
|
|
|
63
68
|
return null;
|
|
64
69
|
}
|
|
65
70
|
|
|
71
|
+
#linkValue;
|
|
72
|
+
#align;
|
|
73
|
+
#frameRatio;
|
|
74
|
+
#defaultRatio;
|
|
75
|
+
#defaultSizeX;
|
|
76
|
+
#defaultSizeY;
|
|
77
|
+
#element;
|
|
78
|
+
#container;
|
|
79
|
+
#ratio;
|
|
80
|
+
#origin_w;
|
|
81
|
+
#origin_h;
|
|
82
|
+
#resizing;
|
|
83
|
+
#onlyPercentage;
|
|
84
|
+
#nonResizing;
|
|
85
|
+
#initRatioValue;
|
|
86
|
+
|
|
66
87
|
/**
|
|
67
88
|
* @constructor
|
|
68
89
|
* @param {__se__EditorCore} editor - The root editor instance
|
|
@@ -95,13 +116,14 @@ class Video extends EditorInjector {
|
|
|
95
116
|
videoTagAttributes: pluginOptions.videoTagAttributes || null,
|
|
96
117
|
iframeTagAttributes: pluginOptions.iframeTagAttributes || null,
|
|
97
118
|
query_youtube: pluginOptions.query_youtube || '',
|
|
98
|
-
query_vimeo: pluginOptions.query_vimeo || ''
|
|
119
|
+
query_vimeo: pluginOptions.query_vimeo || '',
|
|
120
|
+
insertBehavior: pluginOptions.insertBehavior
|
|
99
121
|
};
|
|
100
122
|
|
|
101
123
|
// create HTML
|
|
102
124
|
const sizeUnit = this.pluginOptions.percentageOnlySize ? '%' : 'px';
|
|
103
125
|
const modalEl = CreateHTML_modal(editor, this.pluginOptions);
|
|
104
|
-
const figureControls = pluginOptions.controls || !this.pluginOptions.canResize ? [['align', 'edit', 'copy', 'remove']] : [['resize_auto,75,50', 'align', 'edit', 'revert', 'copy', 'remove']];
|
|
126
|
+
const figureControls = pluginOptions.controls || (!this.pluginOptions.canResize ? [['align', 'edit', 'copy', 'remove']] : [['resize_auto,75,50', 'align', 'edit', 'revert', 'copy', 'remove']]);
|
|
105
127
|
|
|
106
128
|
// show align
|
|
107
129
|
if (!figureControls.some((subArray) => subArray.includes('align'))) modalEl.alignForm.style.display = 'none';
|
|
@@ -122,26 +144,27 @@ class Video extends EditorInjector {
|
|
|
122
144
|
this.videoUrlFile = modalEl.videoUrlFile;
|
|
123
145
|
this.focusElement = this.videoUrlFile || this.videoInputFile;
|
|
124
146
|
this.previewSrc = modalEl.previewSrc;
|
|
125
|
-
this._linkValue = '';
|
|
126
|
-
this._align = 'none';
|
|
127
|
-
this._frameRatio = defaultRatio;
|
|
128
|
-
this._defaultRatio = defaultRatio;
|
|
129
|
-
this._defaultSizeX = '100%';
|
|
130
|
-
this._defaultSizeY = this.pluginOptions.defaultRatio * 100 + '%';
|
|
131
147
|
this.sizeUnit = sizeUnit;
|
|
132
148
|
this.proportion = null;
|
|
133
149
|
this.frameRatioOption = null;
|
|
134
150
|
this.inputX = null;
|
|
135
151
|
this.inputY = null;
|
|
136
|
-
|
|
137
|
-
this
|
|
138
|
-
this
|
|
139
|
-
this
|
|
140
|
-
this
|
|
141
|
-
this
|
|
142
|
-
this
|
|
143
|
-
this
|
|
144
|
-
this
|
|
152
|
+
|
|
153
|
+
this.#linkValue = '';
|
|
154
|
+
this.#align = 'none';
|
|
155
|
+
this.#frameRatio = defaultRatio;
|
|
156
|
+
this.#defaultRatio = defaultRatio;
|
|
157
|
+
this.#defaultSizeX = '100%';
|
|
158
|
+
this.#defaultSizeY = this.pluginOptions.defaultRatio * 100 + '%';
|
|
159
|
+
this.#element = null;
|
|
160
|
+
this.#container = null;
|
|
161
|
+
this.#ratio = { w: 0, h: 0 };
|
|
162
|
+
this.#origin_w = this.pluginOptions.defaultWidth === '100%' ? '' : this.pluginOptions.defaultWidth;
|
|
163
|
+
this.#origin_h = this.pluginOptions.defaultHeight === defaultRatio ? '' : this.pluginOptions.defaultHeight;
|
|
164
|
+
this.#resizing = this.pluginOptions.canResize;
|
|
165
|
+
this.#onlyPercentage = this.pluginOptions.percentageOnlySize;
|
|
166
|
+
this.#nonResizing = !this.#resizing || !this.pluginOptions.showHeightInput || this.#onlyPercentage;
|
|
167
|
+
|
|
145
168
|
this.query = {
|
|
146
169
|
youtube: {
|
|
147
170
|
pattern: /youtu\.?be/i,
|
|
@@ -195,7 +218,8 @@ class Video extends EditorInjector {
|
|
|
195
218
|
if (this.videoUrlFile) this.eventManager.addEvent(this.videoUrlFile, 'input', this.#OnLinkPreview.bind(this));
|
|
196
219
|
if (this.videoInputFile && this.videoUrlFile) this.eventManager.addEvent(this.videoInputFile, 'change', this.#OnfileInputChange.bind(this));
|
|
197
220
|
|
|
198
|
-
if (this
|
|
221
|
+
if (this.#resizing) {
|
|
222
|
+
this.#initRatioValue = null;
|
|
199
223
|
this.proportion = modalEl.proportion;
|
|
200
224
|
this.frameRatioOption = modalEl.frameRatioOption;
|
|
201
225
|
this.inputX = modalEl.inputX;
|
|
@@ -237,9 +261,9 @@ class Video extends EditorInjector {
|
|
|
237
261
|
*/
|
|
238
262
|
on(isUpdate) {
|
|
239
263
|
if (!isUpdate) {
|
|
240
|
-
if (this
|
|
241
|
-
this.inputX.value = this
|
|
242
|
-
this.inputY.value = this
|
|
264
|
+
if (this.#resizing) {
|
|
265
|
+
this.inputX.value = this.#origin_w = this.pluginOptions.defaultWidth === this.#defaultSizeX ? '' : this.pluginOptions.defaultWidth;
|
|
266
|
+
this.inputY.value = this.#origin_h = this.pluginOptions.defaultHeight === this.#defaultSizeY ? '' : this.pluginOptions.defaultHeight;
|
|
243
267
|
this.proportion.disabled = true;
|
|
244
268
|
}
|
|
245
269
|
if (this.videoInputFile && this.pluginOptions.allowMultiple) this.videoInputFile.setAttribute('multiple', 'multiple');
|
|
@@ -247,8 +271,9 @@ class Video extends EditorInjector {
|
|
|
247
271
|
if (this.videoInputFile && this.pluginOptions.allowMultiple) this.videoInputFile.removeAttribute('multiple');
|
|
248
272
|
}
|
|
249
273
|
|
|
250
|
-
if (this
|
|
251
|
-
this
|
|
274
|
+
if (this.#resizing) {
|
|
275
|
+
this.#setRatioSelect(this.figure.isVertical ? '' : this.#origin_h || this.#defaultRatio);
|
|
276
|
+
this.#initRatioValue = this.frameRatioOption?.value;
|
|
252
277
|
}
|
|
253
278
|
}
|
|
254
279
|
|
|
@@ -276,16 +301,16 @@ class Video extends EditorInjector {
|
|
|
276
301
|
* @returns {Promise<boolean>} Success / failure
|
|
277
302
|
*/
|
|
278
303
|
async modalAction() {
|
|
279
|
-
this
|
|
304
|
+
this.#align = /** @type {HTMLInputElement} */ (this.modal.form.querySelector('input[name="suneditor_video_radio"]:checked')).value;
|
|
280
305
|
|
|
281
306
|
let result = false;
|
|
282
307
|
if (this.videoInputFile && this.videoInputFile.files.length > 0) {
|
|
283
308
|
result = await this.submitFile(this.videoInputFile.files);
|
|
284
|
-
} else if (this.videoUrlFile && this.
|
|
285
|
-
result = await this.submitURL(this
|
|
309
|
+
} else if (this.videoUrlFile && this.#linkValue.length > 0) {
|
|
310
|
+
result = await this.submitURL(this.#linkValue);
|
|
286
311
|
}
|
|
287
312
|
|
|
288
|
-
if (result)
|
|
313
|
+
if (result) _w.setTimeout(this.component.select.bind(this.component, this.#element, Video.key), 0);
|
|
289
314
|
|
|
290
315
|
return result;
|
|
291
316
|
}
|
|
@@ -312,11 +337,11 @@ class Video extends EditorInjector {
|
|
|
312
337
|
const figureInfo = Figure.GetContainer(element);
|
|
313
338
|
if (figureInfo && figureInfo.container && figureInfo.cover) return;
|
|
314
339
|
|
|
315
|
-
this
|
|
340
|
+
this.#ready(element, true);
|
|
316
341
|
const line = this.format.getLine(element);
|
|
317
|
-
if (line) this
|
|
342
|
+
if (line) this.#align = line.style.textAlign || line.style.float;
|
|
318
343
|
|
|
319
|
-
this
|
|
344
|
+
this.#fixTagStructure(element);
|
|
320
345
|
}
|
|
321
346
|
};
|
|
322
347
|
}
|
|
@@ -328,22 +353,22 @@ class Video extends EditorInjector {
|
|
|
328
353
|
init() {
|
|
329
354
|
Modal.OnChangeFile(this.fileModalWrapper, []);
|
|
330
355
|
if (this.videoInputFile) this.videoInputFile.value = '';
|
|
331
|
-
if (this.videoUrlFile) this
|
|
356
|
+
if (this.videoUrlFile) this.#linkValue = this.previewSrc.textContent = this.videoUrlFile.value = '';
|
|
332
357
|
if (this.videoInputFile && this.videoUrlFile) {
|
|
333
358
|
this.videoUrlFile.disabled = false;
|
|
334
359
|
this.previewSrc.style.textDecoration = '';
|
|
335
360
|
}
|
|
336
361
|
|
|
337
362
|
/** @type {HTMLInputElement} */ (this.modal.form.querySelector('input[name="suneditor_video_radio"][value="none"]')).checked = true;
|
|
338
|
-
this
|
|
339
|
-
this
|
|
363
|
+
this.#ratio = { w: 0, h: 0 };
|
|
364
|
+
this.#nonResizing = false;
|
|
340
365
|
|
|
341
|
-
if (this
|
|
342
|
-
this.inputX.value = this.pluginOptions.defaultWidth === this
|
|
343
|
-
this.inputY.value = this.pluginOptions.defaultHeight === this
|
|
366
|
+
if (this.#resizing) {
|
|
367
|
+
this.inputX.value = this.pluginOptions.defaultWidth === this.#defaultSizeX ? '' : this.pluginOptions.defaultWidth;
|
|
368
|
+
this.inputY.value = this.pluginOptions.defaultHeight === this.#defaultSizeY ? '' : this.pluginOptions.defaultHeight;
|
|
344
369
|
this.proportion.checked = false;
|
|
345
370
|
this.proportion.disabled = true;
|
|
346
|
-
this
|
|
371
|
+
this.#setRatioSelect(this.#defaultRatio);
|
|
347
372
|
}
|
|
348
373
|
}
|
|
349
374
|
|
|
@@ -353,60 +378,7 @@ class Video extends EditorInjector {
|
|
|
353
378
|
* @param {HTMLIFrameElement|HTMLVideoElement} target Target component element
|
|
354
379
|
*/
|
|
355
380
|
select(target) {
|
|
356
|
-
this
|
|
357
|
-
}
|
|
358
|
-
|
|
359
|
-
/**
|
|
360
|
-
* @private
|
|
361
|
-
* @description Prepares the component for selection.
|
|
362
|
-
* - Ensures that the controller is properly positioned and initialized.
|
|
363
|
-
* - Prevents duplicate event handling if the component is already selected.
|
|
364
|
-
* @param {HTMLIFrameElement|HTMLVideoElement} target - The selected element.
|
|
365
|
-
*/
|
|
366
|
-
_ready(target) {
|
|
367
|
-
if (!target) return;
|
|
368
|
-
const figureInfo = this.figure.open(target, { nonResizing: this._nonResizing, nonSizeInfo: false, nonBorder: false, figureTarget: false, __fileManagerInfo: false });
|
|
369
|
-
|
|
370
|
-
this._element = target;
|
|
371
|
-
this._cover = figureInfo.cover;
|
|
372
|
-
this._container = figureInfo.container;
|
|
373
|
-
this._align = figureInfo.align;
|
|
374
|
-
target.style.float = '';
|
|
375
|
-
|
|
376
|
-
this._origin_w = String(figureInfo.width || figureInfo.originWidth || figureInfo.w || '');
|
|
377
|
-
this._origin_h = String(figureInfo.height || figureInfo.originHeight || figureInfo.h || '');
|
|
378
|
-
|
|
379
|
-
let w = figureInfo.width || figureInfo.w || this._origin_w || '';
|
|
380
|
-
const h = figureInfo.height || figureInfo.h || this._origin_h || '';
|
|
381
|
-
|
|
382
|
-
if (this.videoUrlFile) this._linkValue = this.previewSrc.textContent = this.videoUrlFile.value = this._element.src || this._element.querySelector('source')?.src || '';
|
|
383
|
-
|
|
384
|
-
/** @type {HTMLInputElement} */
|
|
385
|
-
const activeAlgin = this.modal.form.querySelector('input[name="suneditor_video_radio"][value="' + this._align + '"]') || this.modal.form.querySelector('input[name="suneditor_video_radio"][value="none"]');
|
|
386
|
-
activeAlgin.checked = true;
|
|
387
|
-
|
|
388
|
-
if (!this._resizing) return;
|
|
389
|
-
|
|
390
|
-
const percentageRotation = this._onlyPercentage && this.figure.isVertical;
|
|
391
|
-
if (this._onlyPercentage) {
|
|
392
|
-
w = numbers.get(w, 2);
|
|
393
|
-
if (w > 100) w = 100;
|
|
394
|
-
}
|
|
395
|
-
this.inputX.value = String(w === 'auto' ? '' : w);
|
|
396
|
-
|
|
397
|
-
if (!this._onlyPercentage) {
|
|
398
|
-
const infoH = percentageRotation ? '' : figureInfo.height;
|
|
399
|
-
this.inputY.value = String(infoH === 'auto' ? '' : infoH);
|
|
400
|
-
}
|
|
401
|
-
|
|
402
|
-
if (!this._setRatioSelect(h)) this.inputY.value = String(this._onlyPercentage ? numbers.get(h, 2) : h);
|
|
403
|
-
|
|
404
|
-
this.proportion.checked = true;
|
|
405
|
-
this.inputX.disabled = percentageRotation ? true : false;
|
|
406
|
-
this.inputY.disabled = percentageRotation ? true : false;
|
|
407
|
-
this.proportion.disabled = percentageRotation ? true : false;
|
|
408
|
-
|
|
409
|
-
this._ratio = this.proportion.checked ? figureInfo.ratio : { w: 1, h: 1 };
|
|
381
|
+
this.#ready(target);
|
|
410
382
|
}
|
|
411
383
|
|
|
412
384
|
/**
|
|
@@ -416,18 +388,18 @@ class Video extends EditorInjector {
|
|
|
416
388
|
* @returns {Promise<void>}
|
|
417
389
|
*/
|
|
418
390
|
async destroy(target) {
|
|
419
|
-
const targetEl = target || this
|
|
391
|
+
const targetEl = target || this.#element;
|
|
420
392
|
const container = dom.query.getParentElement(targetEl, Figure.is) || targetEl;
|
|
421
393
|
const focusEl = container.previousElementSibling || container.nextElementSibling;
|
|
422
394
|
const emptyDiv = container.parentNode;
|
|
423
395
|
|
|
424
|
-
const message = await this.triggerEvent('onVideoDeleteBefore', { element: targetEl, container, align: this
|
|
396
|
+
const message = await this.triggerEvent('onVideoDeleteBefore', { element: targetEl, container, align: this.#align, url: this.#linkValue });
|
|
425
397
|
if (message === false) return;
|
|
426
398
|
|
|
427
399
|
dom.utils.removeItem(container);
|
|
428
400
|
this.init();
|
|
429
401
|
|
|
430
|
-
if (emptyDiv !== this.
|
|
402
|
+
if (emptyDiv !== this.frameContext.get('wysiwyg')) {
|
|
431
403
|
this.nodeTransform.removeAllParents(
|
|
432
404
|
emptyDiv,
|
|
433
405
|
function (current) {
|
|
@@ -537,56 +509,55 @@ class Video extends EditorInjector {
|
|
|
537
509
|
* @param {string} align - The alignment to apply to the video element (e.g., 'left', 'center', 'right').
|
|
538
510
|
* @param {boolean} isUpdate - Indicates whether this is an update to an existing component (true) or a new creation (false).
|
|
539
511
|
* @param {{name: string, size: number}} file - File metadata associated with the video
|
|
512
|
+
* @param {boolean} isLast - Indicates whether this is the last file in the batch (used for scroll and insert actions).
|
|
540
513
|
*/
|
|
541
|
-
create(oFrame, src, width, height, align, isUpdate, file) {
|
|
542
|
-
let cover = null;
|
|
514
|
+
create(oFrame, src, width, height, align, isUpdate, file, isLast) {
|
|
543
515
|
let container = null;
|
|
544
516
|
|
|
545
517
|
/** update */
|
|
546
518
|
if (isUpdate) {
|
|
547
|
-
oFrame = this
|
|
519
|
+
oFrame = this.#element;
|
|
548
520
|
if (oFrame.src !== src) {
|
|
549
521
|
const processUrl = this.findProcessUrl(src);
|
|
550
522
|
if (/^iframe$/i.test(processUrl?.tag) && !/^iframe$/i.test(oFrame.nodeName)) {
|
|
551
523
|
const newTag = this.createIframeTag();
|
|
552
524
|
newTag.src = src;
|
|
553
525
|
oFrame.replaceWith(newTag);
|
|
554
|
-
this
|
|
526
|
+
this.#element = oFrame = newTag;
|
|
555
527
|
} else if (/^video$/i.test(processUrl?.tag) && !/^video$/i.test(oFrame.nodeName)) {
|
|
556
528
|
const newTag = this.createVideoTag();
|
|
557
529
|
newTag.src = src;
|
|
558
530
|
oFrame.replaceWith(newTag);
|
|
559
|
-
this
|
|
531
|
+
this.#element = oFrame = newTag;
|
|
560
532
|
} else {
|
|
561
533
|
oFrame.src = src;
|
|
562
534
|
}
|
|
563
535
|
}
|
|
564
|
-
container = this
|
|
565
|
-
cover = dom.query.getParentElement(oFrame, 'FIGURE');
|
|
536
|
+
container = this.#container;
|
|
566
537
|
} else {
|
|
567
538
|
/** create */
|
|
568
539
|
oFrame.src = src;
|
|
569
|
-
this
|
|
540
|
+
this.#element = oFrame;
|
|
570
541
|
const figure = Figure.CreateContainer(oFrame, 'se-video-container');
|
|
571
|
-
cover = figure.cover;
|
|
572
542
|
container = figure.container;
|
|
573
543
|
}
|
|
574
544
|
|
|
575
545
|
/** rendering */
|
|
576
|
-
this
|
|
577
|
-
this
|
|
578
|
-
this.
|
|
579
|
-
|
|
546
|
+
this.#element = oFrame;
|
|
547
|
+
this.#container = container;
|
|
548
|
+
this.figure.open(oFrame, { nonResizing: this.#nonResizing, nonSizeInfo: false, nonBorder: false, figureTarget: false, infoOnly: true });
|
|
549
|
+
|
|
550
|
+
width ||= this.#defaultSizeX;
|
|
551
|
+
height ||= this.#frameRatio;
|
|
580
552
|
|
|
581
|
-
width = width || this._defaultSizeX;
|
|
582
|
-
height = height || this._frameRatio;
|
|
583
553
|
const size = this.figure.getSize(oFrame);
|
|
584
554
|
const inputUpdate = size.w !== width || size.h !== height;
|
|
585
555
|
const changeSize = !isUpdate || inputUpdate;
|
|
586
556
|
|
|
587
557
|
// set size
|
|
588
558
|
if (changeSize) {
|
|
589
|
-
this.
|
|
559
|
+
if (this.#initRatioValue !== this.frameRatioOption?.value) this.figure.deleteTransform();
|
|
560
|
+
this.#applySize(width, height);
|
|
590
561
|
}
|
|
591
562
|
|
|
592
563
|
// align
|
|
@@ -597,15 +568,11 @@ class Video extends EditorInjector {
|
|
|
597
568
|
this.fileManager.setFileData(oFrame, file);
|
|
598
569
|
|
|
599
570
|
if (!isUpdate) {
|
|
600
|
-
this.component.insert(container, {
|
|
601
|
-
if (!this.options.get('componentAutoSelect')) {
|
|
602
|
-
const line = this.format.addLine(container, null);
|
|
603
|
-
if (line) this.selection.setRange(line, 0, line, 0);
|
|
604
|
-
}
|
|
571
|
+
this.component.insert(container, { scrollTo: isLast ? true : false, insertBehavior: isLast ? this.pluginOptions.insertBehavior : 'line' });
|
|
605
572
|
return;
|
|
606
573
|
}
|
|
607
574
|
|
|
608
|
-
if (this
|
|
575
|
+
if (!this.#resizing || !changeSize || !this.figure.isVertical) this.figure.setTransform(oFrame, width, height, 0);
|
|
609
576
|
this.history.push(false);
|
|
610
577
|
}
|
|
611
578
|
|
|
@@ -623,7 +590,7 @@ class Video extends EditorInjector {
|
|
|
623
590
|
iframeTag[key] = props[key];
|
|
624
591
|
}
|
|
625
592
|
}
|
|
626
|
-
this
|
|
593
|
+
this.#setIframeAttrs(iframeTag);
|
|
627
594
|
return iframeTag;
|
|
628
595
|
}
|
|
629
596
|
|
|
@@ -641,41 +608,10 @@ class Video extends EditorInjector {
|
|
|
641
608
|
videoTag[key] = props[key];
|
|
642
609
|
}
|
|
643
610
|
}
|
|
644
|
-
this
|
|
611
|
+
this.#setTagAttrs(videoTag);
|
|
645
612
|
return videoTag;
|
|
646
613
|
}
|
|
647
614
|
|
|
648
|
-
/**
|
|
649
|
-
* @private
|
|
650
|
-
* @description Sets the size of the video element.
|
|
651
|
-
* @param {string|number} w - The width of the video.
|
|
652
|
-
* @param {string|number} h - The height of the video.
|
|
653
|
-
*/
|
|
654
|
-
_applySize(w, h) {
|
|
655
|
-
if (!w) w = this.inputX?.value || this.pluginOptions.defaultWidth;
|
|
656
|
-
if (!h) h = this.inputY?.value || this.pluginOptions.defaultHeight;
|
|
657
|
-
if (this._onlyPercentage) {
|
|
658
|
-
if (!w) w = '100%';
|
|
659
|
-
else if (/%$/.test(w + '')) w += '%';
|
|
660
|
-
}
|
|
661
|
-
this.figure.setSize(w, h);
|
|
662
|
-
}
|
|
663
|
-
|
|
664
|
-
/**
|
|
665
|
-
* @private
|
|
666
|
-
* @description Retrieves video information including size and alignment.
|
|
667
|
-
* @returns {*} Video information object.
|
|
668
|
-
*/
|
|
669
|
-
_getInfo() {
|
|
670
|
-
return {
|
|
671
|
-
inputWidth: this.inputX?.value || '',
|
|
672
|
-
inputHeight: this.inputY?.value || '',
|
|
673
|
-
align: this._align,
|
|
674
|
-
isUpdate: this.modal.isUpdate,
|
|
675
|
-
element: this._element
|
|
676
|
-
};
|
|
677
|
-
}
|
|
678
|
-
|
|
679
615
|
/**
|
|
680
616
|
* @description Create an "video" component using the provided files.
|
|
681
617
|
* @param {FileList|File[]} fileList File object list
|
|
@@ -692,7 +628,7 @@ class Video extends EditorInjector {
|
|
|
692
628
|
if (!/video/i.test(f.type)) continue;
|
|
693
629
|
|
|
694
630
|
s = f.size;
|
|
695
|
-
if (slngleSizeLimit &&
|
|
631
|
+
if (slngleSizeLimit > 0 && s > slngleSizeLimit) {
|
|
696
632
|
const err = '[SUNEDITOR.videoUpload.fail] Size of uploadable single file: ' + slngleSizeLimit / 1000 + 'KB';
|
|
697
633
|
const message = await this.triggerEvent('onVideoUploadError', {
|
|
698
634
|
error: err,
|
|
@@ -724,15 +660,13 @@ class Video extends EditorInjector {
|
|
|
724
660
|
const videoInfo = {
|
|
725
661
|
url: null,
|
|
726
662
|
files,
|
|
727
|
-
...this
|
|
663
|
+
...this.#getInfo()
|
|
728
664
|
};
|
|
729
665
|
|
|
730
|
-
const handler = function (infos, newInfos) {
|
|
666
|
+
const handler = function (uploadCallback, infos, newInfos) {
|
|
731
667
|
infos = newInfos || infos;
|
|
732
|
-
|
|
733
|
-
}.bind(this, videoInfo);
|
|
734
|
-
// se-ts-ignore
|
|
735
|
-
this._serverUpload;
|
|
668
|
+
uploadCallback(infos, infos.files);
|
|
669
|
+
}.bind(this, this.#serverUpload.bind(this), videoInfo);
|
|
736
670
|
|
|
737
671
|
const result = await this.triggerEvent('onVideoUploadBefore', {
|
|
738
672
|
info: videoInfo,
|
|
@@ -752,8 +686,7 @@ class Video extends EditorInjector {
|
|
|
752
686
|
* @returns {Promise<boolean>} If return false, the file upload will be canceled
|
|
753
687
|
*/
|
|
754
688
|
async submitURL(url) {
|
|
755
|
-
if (!url
|
|
756
|
-
if (!url) return false;
|
|
689
|
+
if (!(url = this.#linkValue)) return false;
|
|
757
690
|
|
|
758
691
|
/** iframe source */
|
|
759
692
|
if (/^<iframe.*\/iframe>$/.test(url)) {
|
|
@@ -768,11 +701,11 @@ class Video extends EditorInjector {
|
|
|
768
701
|
}
|
|
769
702
|
|
|
770
703
|
const file = { name: url.split('/').pop(), size: 0 };
|
|
771
|
-
const videoInfo = { url, files: file, ...this
|
|
704
|
+
const videoInfo = { url, files: file, ...this.#getInfo(), process: processUrl };
|
|
772
705
|
|
|
773
706
|
const handler = function (infos, newInfos) {
|
|
774
707
|
infos = newInfos || infos;
|
|
775
|
-
this.create(this[/^iframe$/i.test(infos.process?.tag) ? 'createIframeTag' : 'createVideoTag'](), infos.url, infos.inputWidth, infos.inputHeight, infos.align, infos.isUpdate, infos.files);
|
|
708
|
+
this.create(this[/^iframe$/i.test(infos.process?.tag) ? 'createIframeTag' : 'createVideoTag'](), infos.url, infos.inputWidth, infos.inputHeight, infos.align, infos.isUpdate, infos.files, true);
|
|
776
709
|
}.bind(this, videoInfo);
|
|
777
710
|
|
|
778
711
|
const result = await this.triggerEvent('onVideoUploadBefore', {
|
|
@@ -790,106 +723,175 @@ class Video extends EditorInjector {
|
|
|
790
723
|
}
|
|
791
724
|
|
|
792
725
|
/**
|
|
793
|
-
* @
|
|
726
|
+
* @description Prepares the component for selection.
|
|
727
|
+
* - Ensures that the controller is properly positioned and initialized.
|
|
728
|
+
* - Prevents duplicate event handling if the component is already selected.
|
|
729
|
+
* @param {HTMLIFrameElement|HTMLVideoElement} target - The selected element.
|
|
730
|
+
* @param {boolean} [infoOnly=false] - If true, only retrieves information without opening the controller.
|
|
731
|
+
*/
|
|
732
|
+
#ready(target, infoOnly = false) {
|
|
733
|
+
if (!target) return;
|
|
734
|
+
const figureInfo = this.figure.open(target, { nonResizing: this.#nonResizing, nonSizeInfo: false, nonBorder: false, figureTarget: false, infoOnly });
|
|
735
|
+
|
|
736
|
+
this.#element = target;
|
|
737
|
+
this.#container = figureInfo.container;
|
|
738
|
+
this.#align = figureInfo.align;
|
|
739
|
+
target.style.float = '';
|
|
740
|
+
|
|
741
|
+
this.#origin_w = String(figureInfo.width || figureInfo.originWidth || figureInfo.w || '');
|
|
742
|
+
this.#origin_h = String(figureInfo.height || figureInfo.originHeight || figureInfo.h || '');
|
|
743
|
+
|
|
744
|
+
const h = figureInfo.height || figureInfo.h || this.#origin_h || '';
|
|
745
|
+
|
|
746
|
+
if (this.videoUrlFile) this.#linkValue = this.previewSrc.textContent = this.videoUrlFile.value = this.#element.src || this.#element.querySelector('source')?.src || '';
|
|
747
|
+
|
|
748
|
+
/** @type {HTMLInputElement} */
|
|
749
|
+
const activeAlgin = this.modal.form.querySelector('input[name="suneditor_video_radio"][value="' + this.#align + '"]') || this.modal.form.querySelector('input[name="suneditor_video_radio"][value="none"]');
|
|
750
|
+
activeAlgin.checked = true;
|
|
751
|
+
|
|
752
|
+
if (!this.#resizing) return;
|
|
753
|
+
|
|
754
|
+
const percentageRotation = this.#onlyPercentage && this.figure.isVertical;
|
|
755
|
+
const { dw, dh } = this.figure.getSize(target);
|
|
756
|
+
this.inputX.value = dw === 'auto' ? '' : dw;
|
|
757
|
+
this.inputY.value = dh === 'auto' ? '' : dh;
|
|
758
|
+
|
|
759
|
+
if (!this.#setRatioSelect(h)) this.inputY.value = String(this.#onlyPercentage ? numbers.get(h, 2) : h);
|
|
760
|
+
|
|
761
|
+
this.proportion.checked = true;
|
|
762
|
+
this.inputX.disabled = percentageRotation ? true : false;
|
|
763
|
+
this.inputY.disabled = percentageRotation ? true : false;
|
|
764
|
+
this.proportion.disabled = percentageRotation ? true : false;
|
|
765
|
+
|
|
766
|
+
if (figureInfo.isVertical) {
|
|
767
|
+
this.proportion.checked = false;
|
|
768
|
+
}
|
|
769
|
+
|
|
770
|
+
this.#ratio = this.proportion.checked ? figureInfo.ratio : { w: 0, h: 0 };
|
|
771
|
+
}
|
|
772
|
+
|
|
773
|
+
/**
|
|
774
|
+
* @description Sets the size of the video element.
|
|
775
|
+
* @param {string|number} w - The width of the video.
|
|
776
|
+
* @param {string|number} h - The height of the video.
|
|
777
|
+
*/
|
|
778
|
+
#applySize(w, h) {
|
|
779
|
+
w ||= this.inputX?.value || this.pluginOptions.defaultWidth;
|
|
780
|
+
h ||= this.inputY?.value || this.pluginOptions.defaultHeight;
|
|
781
|
+
|
|
782
|
+
if (this.#onlyPercentage) {
|
|
783
|
+
if (!w) w = '100%';
|
|
784
|
+
else if (/%$/.test(w + '')) w += '%';
|
|
785
|
+
}
|
|
786
|
+
this.figure.setSize(w, h);
|
|
787
|
+
}
|
|
788
|
+
|
|
789
|
+
/**
|
|
790
|
+
* @description Retrieves video information including size and alignment.
|
|
791
|
+
* @returns {*} Video information object.
|
|
792
|
+
*/
|
|
793
|
+
#getInfo() {
|
|
794
|
+
return {
|
|
795
|
+
inputWidth: this.inputX?.value || '',
|
|
796
|
+
inputHeight: this.inputY?.value || '',
|
|
797
|
+
align: this.#align,
|
|
798
|
+
isUpdate: this.modal.isUpdate,
|
|
799
|
+
element: this.#element
|
|
800
|
+
};
|
|
801
|
+
}
|
|
802
|
+
|
|
803
|
+
/**
|
|
794
804
|
* @description Updates the video component within the editor.
|
|
795
805
|
* @param {HTMLIFrameElement|HTMLVideoElement} oFrame - The video element to update.
|
|
796
806
|
*/
|
|
797
|
-
|
|
807
|
+
#fixTagStructure(oFrame) {
|
|
798
808
|
if (!oFrame) return;
|
|
799
809
|
|
|
800
|
-
|
|
801
|
-
|
|
810
|
+
const isVideoTag = /^video$/i.test(oFrame.nodeName);
|
|
811
|
+
if (isVideoTag) {
|
|
812
|
+
this.#setTagAttrs(/** @type {HTMLVideoElement} */ (oFrame));
|
|
802
813
|
} else if (/^iframe$/i.test(oFrame.nodeName)) {
|
|
803
|
-
this
|
|
814
|
+
this.#setIframeAttrs(/** @type {HTMLIFrameElement} */ (oFrame));
|
|
804
815
|
}
|
|
805
816
|
|
|
806
|
-
let existElement = this.format.isBlock(oFrame.parentNode) || dom.check.isWysiwygFrame(oFrame.parentNode) ? oFrame : this.format.getLine(oFrame) || oFrame;
|
|
807
|
-
|
|
808
817
|
const prevFrame = oFrame;
|
|
809
818
|
const cloneFrame = /** @type {HTMLIFrameElement|HTMLVideoElement} */ (oFrame.cloneNode(true));
|
|
810
819
|
const figure = Figure.CreateContainer(cloneFrame, 'se-video-container');
|
|
811
820
|
const container = figure.container;
|
|
812
821
|
|
|
813
|
-
const figcaption =
|
|
822
|
+
const figcaption = Figure.GetContainer(prevFrame)?.container?.querySelector('figcaption');
|
|
814
823
|
let caption = null;
|
|
815
824
|
if (figcaption) {
|
|
816
|
-
caption = dom.utils.createElement('
|
|
825
|
+
caption = dom.utils.createElement('figcaption');
|
|
817
826
|
caption.innerHTML = figcaption.innerHTML;
|
|
818
827
|
dom.utils.removeItem(figcaption);
|
|
828
|
+
figure.cover.appendChild(caption);
|
|
819
829
|
}
|
|
820
830
|
|
|
821
831
|
// size
|
|
822
|
-
this.figure.open(cloneFrame, { nonResizing: this
|
|
832
|
+
this.figure.open(cloneFrame, { nonResizing: this.#nonResizing, nonSizeInfo: false, nonBorder: false, figureTarget: false, infoOnly: true });
|
|
823
833
|
const size = (cloneFrame.getAttribute('data-se-size') || ',').split(',');
|
|
824
|
-
|
|
834
|
+
|
|
835
|
+
const width = size[0] || prevFrame.width || '';
|
|
836
|
+
const height = size[1] || prevFrame.height || this.#defaultRatio || '';
|
|
837
|
+
this.#applySize(width, height);
|
|
825
838
|
|
|
826
839
|
// align
|
|
827
840
|
const format = this.format.getLine(prevFrame);
|
|
828
|
-
if (format) this
|
|
829
|
-
this.figure.setAlign(cloneFrame, this
|
|
830
|
-
|
|
831
|
-
if (dom.query.getParentElement(prevFrame, dom.check.isExcludeFormat)) {
|
|
832
|
-
prevFrame.replaceWith(container);
|
|
833
|
-
} else if (dom.check.isListCell(existElement)) {
|
|
834
|
-
const refer = dom.query.getParentElement(prevFrame, (current) => current.parentNode === existElement);
|
|
835
|
-
existElement.insertBefore(container, refer);
|
|
836
|
-
dom.utils.removeItem(prevFrame);
|
|
837
|
-
this.nodeTransform.removeEmptyNode(refer, null, true);
|
|
838
|
-
} else if (this.format.isLine(existElement)) {
|
|
839
|
-
const refer = dom.query.getParentElement(prevFrame, (current) => current.parentNode === existElement);
|
|
840
|
-
existElement = this.nodeTransform.split(existElement, refer);
|
|
841
|
-
existElement.parentNode.insertBefore(container, existElement);
|
|
842
|
-
dom.utils.removeItem(prevFrame);
|
|
843
|
-
this.nodeTransform.removeEmptyNode(existElement, null, true);
|
|
844
|
-
} else {
|
|
845
|
-
/** @type {Element} */ (existElement).replaceWith(container);
|
|
846
|
-
}
|
|
841
|
+
if (format) this.#align = format.style.textAlign || format.style.float;
|
|
842
|
+
this.figure.setAlign(cloneFrame, this.#align);
|
|
847
843
|
|
|
848
|
-
|
|
844
|
+
this.figure.retainFigureFormat(container, this.#element, null, this.fileManager);
|
|
849
845
|
|
|
850
846
|
return cloneFrame;
|
|
851
847
|
}
|
|
852
848
|
|
|
853
849
|
/**
|
|
854
|
-
* @private
|
|
855
850
|
* @description Registers the uploaded video in the editor.
|
|
856
851
|
* @param {VideoInfo_video} info - Video information object.
|
|
857
852
|
* @param {Object<string, *>} response - Server response containing video data.
|
|
858
853
|
*/
|
|
859
|
-
|
|
854
|
+
#register(info, response) {
|
|
860
855
|
const fileList = response.result;
|
|
861
856
|
const videoTag = this.createVideoTag();
|
|
862
857
|
|
|
863
858
|
for (let i = 0, len = fileList.length; i < len; i++) {
|
|
864
859
|
const ctag = info.isUpdate ? info.element : /** @type {HTMLIFrameElement|HTMLVideoElement} */ (videoTag.cloneNode(false));
|
|
865
|
-
this.create(
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
860
|
+
this.create(
|
|
861
|
+
ctag,
|
|
862
|
+
fileList[i].url,
|
|
863
|
+
info.inputWidth,
|
|
864
|
+
info.inputHeight,
|
|
865
|
+
info.align,
|
|
866
|
+
info.isUpdate,
|
|
867
|
+
{
|
|
868
|
+
name: fileList[i].name,
|
|
869
|
+
size: fileList[i].size
|
|
870
|
+
},
|
|
871
|
+
i === len - 1
|
|
872
|
+
);
|
|
869
873
|
}
|
|
870
874
|
}
|
|
871
875
|
|
|
872
876
|
/**
|
|
873
|
-
* @private
|
|
874
877
|
* @description Uploads a video to the server using an external upload handler.
|
|
875
878
|
* @param {VideoInfo_video} info - Video information object.
|
|
876
879
|
* @param {FileList} files - The video files to upload.
|
|
877
880
|
*/
|
|
878
|
-
|
|
881
|
+
#serverUpload(info, files) {
|
|
879
882
|
if (!files) return;
|
|
880
883
|
|
|
881
884
|
const videoUploadUrl = this.pluginOptions.uploadUrl;
|
|
882
885
|
if (typeof videoUploadUrl === 'string' && videoUploadUrl.length > 0) {
|
|
883
|
-
this.fileManager.upload(videoUploadUrl, this.pluginOptions.uploadHeaders, files, this.#UploadCallBack.bind(this, info), this.
|
|
886
|
+
this.fileManager.upload(videoUploadUrl, this.pluginOptions.uploadHeaders, files, this.#UploadCallBack.bind(this, info), this.#error.bind(this));
|
|
884
887
|
}
|
|
885
888
|
}
|
|
886
889
|
|
|
887
890
|
/**
|
|
888
|
-
* @private
|
|
889
891
|
* @description Sets attributes for the video tag.
|
|
890
892
|
* @param {HTMLVideoElement} element - The video element.
|
|
891
893
|
*/
|
|
892
|
-
|
|
894
|
+
#setTagAttrs(element) {
|
|
893
895
|
element.setAttribute('controls', 'true');
|
|
894
896
|
|
|
895
897
|
const attrs = this.pluginOptions.videoTagAttributes;
|
|
@@ -901,11 +903,10 @@ class Video extends EditorInjector {
|
|
|
901
903
|
}
|
|
902
904
|
|
|
903
905
|
/**
|
|
904
|
-
* @private
|
|
905
906
|
* @description Sets attributes for the iframe tag.
|
|
906
907
|
* @param {HTMLIFrameElement} element - The iframe element.
|
|
907
908
|
*/
|
|
908
|
-
|
|
909
|
+
#setIframeAttrs(element) {
|
|
909
910
|
element.frameBorder = '0';
|
|
910
911
|
element.allowFullscreen = true;
|
|
911
912
|
|
|
@@ -918,16 +919,17 @@ class Video extends EditorInjector {
|
|
|
918
919
|
}
|
|
919
920
|
|
|
920
921
|
/**
|
|
921
|
-
* @private
|
|
922
922
|
* @description Selects a ratio option in the ratio dropdown.
|
|
923
923
|
* @param {string|number} value - The selected ratio value.
|
|
924
924
|
* @returns {boolean} Returns true if a ratio was selected.
|
|
925
925
|
*/
|
|
926
|
-
|
|
926
|
+
#setRatioSelect(value) {
|
|
927
|
+
if (!this.frameRatioOption) return;
|
|
928
|
+
|
|
927
929
|
let ratioSelected = false;
|
|
928
930
|
const ratioOption = this.frameRatioOption.options;
|
|
929
931
|
|
|
930
|
-
if (/%$/.test(value + '') || this
|
|
932
|
+
if (/%$/.test(value + '') || this.#onlyPercentage) value = numbers.get(value, 2) / 100 + '';
|
|
931
933
|
else if (!numbers.is(value) || Number(value) >= 1) value = '';
|
|
932
934
|
|
|
933
935
|
this.inputY.placeholder = '';
|
|
@@ -935,19 +937,20 @@ class Video extends EditorInjector {
|
|
|
935
937
|
if (ratioOption[i].value === value) {
|
|
936
938
|
ratioSelected = ratioOption[i].selected = true;
|
|
937
939
|
this.inputY.placeholder = !value ? '' : Number(value) * 100 + '%';
|
|
938
|
-
} else
|
|
940
|
+
} else {
|
|
941
|
+
ratioOption[i].selected = false;
|
|
942
|
+
}
|
|
939
943
|
}
|
|
940
944
|
|
|
941
945
|
return ratioSelected;
|
|
942
946
|
}
|
|
943
947
|
|
|
944
948
|
/**
|
|
945
|
-
* @private
|
|
946
949
|
* @description Handles video upload errors.
|
|
947
950
|
* @param {Object<string, *>} response - The error response object.
|
|
948
951
|
* @returns {Promise<void>}
|
|
949
952
|
*/
|
|
950
|
-
async
|
|
953
|
+
async #error(response) {
|
|
951
954
|
const message = await this.triggerEvent('onVideoUploadError', { error: response });
|
|
952
955
|
const err = message === NO_EVENT ? response.errorMessage : message || response.errorMessage;
|
|
953
956
|
this.ui.alertOpen(err, 'error');
|
|
@@ -963,9 +966,9 @@ class Video extends EditorInjector {
|
|
|
963
966
|
if ((await this.triggerEvent('videoUploadHandler', { xmlHttp, info })) === NO_EVENT) {
|
|
964
967
|
const response = JSON.parse(xmlHttp.responseText);
|
|
965
968
|
if (response.errorMessage) {
|
|
966
|
-
this
|
|
969
|
+
this.#error(response);
|
|
967
970
|
} else {
|
|
968
|
-
this
|
|
971
|
+
this.#register(info, response);
|
|
969
972
|
}
|
|
970
973
|
}
|
|
971
974
|
}
|
|
@@ -993,16 +996,16 @@ class Video extends EditorInjector {
|
|
|
993
996
|
const eventTarget = dom.query.getEventTarget(e);
|
|
994
997
|
const value = eventTarget.value.trim();
|
|
995
998
|
if (/^<iframe.*\/iframe>$/.test(value)) {
|
|
996
|
-
this
|
|
999
|
+
this.#linkValue = value;
|
|
997
1000
|
this.previewSrc.textContent = '<IFrame :src=".."></IFrame>';
|
|
998
1001
|
} else {
|
|
999
|
-
this
|
|
1002
|
+
this.#linkValue = this.previewSrc.textContent = !value
|
|
1000
1003
|
? ''
|
|
1001
1004
|
: this.options.get('defaultUrlProtocol') && !value.includes('://') && value.indexOf('#') !== 0
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1005
|
+
? this.options.get('defaultUrlProtocol') + value
|
|
1006
|
+
: !value.includes('://')
|
|
1007
|
+
? '/' + value
|
|
1008
|
+
: value;
|
|
1006
1009
|
}
|
|
1007
1010
|
}
|
|
1008
1011
|
|
|
@@ -1018,7 +1021,7 @@ class Video extends EditorInjector {
|
|
|
1018
1021
|
* @param {HTMLInputElement} target - The selected video element.
|
|
1019
1022
|
*/
|
|
1020
1023
|
#SetUrlInput(target) {
|
|
1021
|
-
this
|
|
1024
|
+
this.#linkValue = this.previewSrc.textContent = this.videoUrlFile.value = target.getAttribute('data-command') || target.src;
|
|
1022
1025
|
this.videoUrlFile.focus();
|
|
1023
1026
|
}
|
|
1024
1027
|
|
|
@@ -1041,11 +1044,11 @@ class Video extends EditorInjector {
|
|
|
1041
1044
|
}
|
|
1042
1045
|
|
|
1043
1046
|
#OnClickRevert() {
|
|
1044
|
-
if (this
|
|
1045
|
-
this.inputX.value = Number(this
|
|
1047
|
+
if (this.#onlyPercentage) {
|
|
1048
|
+
this.inputX.value = Number(this.#origin_w) > 100 ? '100' : this.#origin_w;
|
|
1046
1049
|
} else {
|
|
1047
|
-
this.inputX.value = this
|
|
1048
|
-
this.inputY.value = this
|
|
1050
|
+
this.inputX.value = this.#origin_w;
|
|
1051
|
+
this.inputY.value = this.#origin_h;
|
|
1049
1052
|
}
|
|
1050
1053
|
}
|
|
1051
1054
|
|
|
@@ -1056,13 +1059,13 @@ class Video extends EditorInjector {
|
|
|
1056
1059
|
/** @type {HTMLSelectElement} */
|
|
1057
1060
|
const eventTarget = dom.query.getEventTarget(e);
|
|
1058
1061
|
const value = eventTarget.options[eventTarget.selectedIndex].value;
|
|
1059
|
-
this
|
|
1062
|
+
this.#defaultSizeY = this.figure.autoRatio.current = this.#frameRatio = !value ? this.#defaultSizeY : Number(value) * 100 + '%';
|
|
1060
1063
|
this.inputY.placeholder = !value ? '' : Number(value) * 100 + '%';
|
|
1061
1064
|
this.inputY.value = '';
|
|
1062
1065
|
}
|
|
1063
1066
|
|
|
1064
1067
|
#OnChangeRatio() {
|
|
1065
|
-
this
|
|
1068
|
+
this.#ratio = this.proportion.checked ? Figure.GetRatio(this.inputX.value, this.inputY.value, this.sizeUnit) : { w: 0, h: 0 };
|
|
1066
1069
|
}
|
|
1067
1070
|
|
|
1068
1071
|
/**
|
|
@@ -1077,10 +1080,10 @@ class Video extends EditorInjector {
|
|
|
1077
1080
|
|
|
1078
1081
|
/** @type {HTMLInputElement} */
|
|
1079
1082
|
const eventTarget = dom.query.getEventTarget(e);
|
|
1080
|
-
if (xy === 'x' && this
|
|
1083
|
+
if (xy === 'x' && this.#onlyPercentage && Number(eventTarget.value) > 100) {
|
|
1081
1084
|
eventTarget.value = '100';
|
|
1082
|
-
} else if (this.proportion.checked) {
|
|
1083
|
-
const ratioSize = Figure.CalcRatio(this.inputX.value, this.inputY.value, this.sizeUnit, this
|
|
1085
|
+
} else if (this.proportion.checked && !this.frameRatioOption?.value) {
|
|
1086
|
+
const ratioSize = Figure.CalcRatio(this.inputX.value, this.inputY.value, this.sizeUnit, this.#ratio);
|
|
1084
1087
|
if (xy === 'x') {
|
|
1085
1088
|
this.inputY.value = String(ratioSize.h);
|
|
1086
1089
|
} else {
|
|
@@ -1089,7 +1092,7 @@ class Video extends EditorInjector {
|
|
|
1089
1092
|
}
|
|
1090
1093
|
|
|
1091
1094
|
if (xy === 'y') {
|
|
1092
|
-
this
|
|
1095
|
+
this.#setRatioSelect(eventTarget.value || this.#defaultRatio);
|
|
1093
1096
|
}
|
|
1094
1097
|
}
|
|
1095
1098
|
}
|