suneditor 2.47.5 → 2.47.7

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.
Files changed (141) hide show
  1. package/LICENSE.txt +20 -20
  2. package/README.md +1625 -1613
  3. package/dist/css/suneditor.min.css +1 -1
  4. package/dist/suneditor.min.js +2 -2
  5. package/example.md +586 -586
  6. package/package.json +71 -71
  7. package/src/assets/css/suneditor-contents.css +561 -561
  8. package/src/assets/css/suneditor.css +2 -2
  9. package/src/assets/defaultIcons.js +103 -103
  10. package/src/lang/Lang.d.ts +143 -143
  11. package/src/lang/ckb.d.ts +4 -4
  12. package/src/lang/ckb.js +187 -187
  13. package/src/lang/cs.d.ts +4 -4
  14. package/src/lang/cs.js +187 -187
  15. package/src/lang/da.d.ts +4 -4
  16. package/src/lang/da.js +191 -191
  17. package/src/lang/de.d.ts +4 -4
  18. package/src/lang/de.js +188 -188
  19. package/src/lang/en.d.ts +4 -4
  20. package/src/lang/en.js +187 -187
  21. package/src/lang/es.d.ts +4 -4
  22. package/src/lang/es.js +187 -187
  23. package/src/lang/fa.d.ts +4 -4
  24. package/src/lang/fa.js +187 -187
  25. package/src/lang/fr.d.ts +4 -4
  26. package/src/lang/fr.js +188 -188
  27. package/src/lang/he.d.ts +4 -4
  28. package/src/lang/he.js +188 -188
  29. package/src/lang/hu.d.ts +5 -5
  30. package/src/lang/hu.js +188 -188
  31. package/src/lang/index.d.ts +25 -24
  32. package/src/lang/index.js +30 -27
  33. package/src/lang/it.d.ts +4 -4
  34. package/src/lang/it.js +188 -188
  35. package/src/lang/ja.d.ts +4 -4
  36. package/src/lang/ja.js +187 -187
  37. package/src/lang/km.d.ts +5 -0
  38. package/src/lang/km.js +188 -0
  39. package/src/lang/ko.d.ts +4 -4
  40. package/src/lang/ko.js +187 -187
  41. package/src/lang/lv.d.ts +4 -4
  42. package/src/lang/lv.js +187 -187
  43. package/src/lang/nl.d.ts +4 -4
  44. package/src/lang/nl.js +187 -187
  45. package/src/lang/pl.d.ts +4 -4
  46. package/src/lang/pl.js +187 -187
  47. package/src/lang/pt_br.d.ts +4 -4
  48. package/src/lang/pt_br.js +189 -189
  49. package/src/lang/ro.d.ts +4 -4
  50. package/src/lang/ro.js +187 -187
  51. package/src/lang/ru.d.ts +4 -4
  52. package/src/lang/ru.js +187 -187
  53. package/src/lang/se.d.ts +4 -4
  54. package/src/lang/se.js +191 -191
  55. package/src/lang/tr.d.ts +5 -5
  56. package/src/lang/tr.js +191 -191
  57. package/src/lang/ua.d.ts +5 -5
  58. package/src/lang/ua.js +188 -188
  59. package/src/lang/ur.d.ts +4 -4
  60. package/src/lang/ur.js +187 -187
  61. package/src/lang/zh_cn.d.ts +4 -4
  62. package/src/lang/zh_cn.js +187 -187
  63. package/src/lib/constructor.js +0 -0
  64. package/src/lib/context.d.ts +42 -42
  65. package/src/lib/context.js +0 -0
  66. package/src/lib/core.d.ts +1135 -1135
  67. package/src/lib/core.js +9 -3
  68. package/src/lib/history.d.ts +48 -48
  69. package/src/lib/history.js +218 -218
  70. package/src/lib/util.d.ts +677 -677
  71. package/src/lib/util.js +1 -1
  72. package/src/options.d.ts +621 -620
  73. package/src/plugins/CommandPlugin.d.ts +7 -7
  74. package/src/plugins/DialogPlugin.d.ts +19 -19
  75. package/src/plugins/FileBrowserPlugin.d.ts +29 -29
  76. package/src/plugins/Module.d.ts +14 -14
  77. package/src/plugins/Plugin.d.ts +41 -41
  78. package/src/plugins/SubmenuPlugin.d.ts +7 -7
  79. package/src/plugins/command/blockquote.d.ts +4 -4
  80. package/src/plugins/command/blockquote.js +46 -46
  81. package/src/plugins/dialog/audio.d.ts +4 -4
  82. package/src/plugins/dialog/audio.js +557 -558
  83. package/src/plugins/dialog/image.d.ts +4 -4
  84. package/src/plugins/dialog/image.js +1126 -1127
  85. package/src/plugins/dialog/link.d.ts +4 -4
  86. package/src/plugins/dialog/link.js +223 -223
  87. package/src/plugins/dialog/math.d.ts +4 -4
  88. package/src/plugins/dialog/math.js +300 -300
  89. package/src/plugins/dialog/video.d.ts +4 -4
  90. package/src/plugins/dialog/video.js +989 -989
  91. package/src/plugins/fileBrowser/imageGallery.d.ts +4 -4
  92. package/src/plugins/fileBrowser/imageGallery.js +64 -64
  93. package/src/plugins/index.d.ts +79 -79
  94. package/src/plugins/index.js +32 -32
  95. package/src/plugins/modules/_anchor.js +461 -461
  96. package/src/plugins/modules/_colorPicker.d.ts +59 -59
  97. package/src/plugins/modules/_colorPicker.js +0 -0
  98. package/src/plugins/modules/_notice.d.ts +20 -20
  99. package/src/plugins/modules/_notice.js +72 -72
  100. package/src/plugins/modules/_selectMenu.js +118 -118
  101. package/src/plugins/modules/component.d.ts +24 -24
  102. package/src/plugins/modules/component.js +80 -80
  103. package/src/plugins/modules/dialog.d.ts +27 -27
  104. package/src/plugins/modules/dialog.js +174 -174
  105. package/src/plugins/modules/fileBrowser.d.ts +41 -41
  106. package/src/plugins/modules/fileBrowser.js +377 -377
  107. package/src/plugins/modules/fileManager.d.ts +66 -66
  108. package/src/plugins/modules/fileManager.js +325 -325
  109. package/src/plugins/modules/index.d.ts +10 -10
  110. package/src/plugins/modules/index.js +8 -8
  111. package/src/plugins/modules/resizing.d.ts +153 -153
  112. package/src/plugins/modules/resizing.js +902 -902
  113. package/src/plugins/submenu/align.d.ts +4 -4
  114. package/src/plugins/submenu/align.js +160 -160
  115. package/src/plugins/submenu/font.d.ts +4 -4
  116. package/src/plugins/submenu/font.js +123 -123
  117. package/src/plugins/submenu/fontColor.d.ts +4 -4
  118. package/src/plugins/submenu/fontColor.js +0 -0
  119. package/src/plugins/submenu/fontSize.d.ts +4 -4
  120. package/src/plugins/submenu/fontSize.js +112 -112
  121. package/src/plugins/submenu/formatBlock.d.ts +4 -4
  122. package/src/plugins/submenu/formatBlock.js +273 -273
  123. package/src/plugins/submenu/hiliteColor.d.ts +4 -4
  124. package/src/plugins/submenu/hiliteColor.js +0 -0
  125. package/src/plugins/submenu/horizontalRule.d.ts +4 -4
  126. package/src/plugins/submenu/horizontalRule.js +98 -98
  127. package/src/plugins/submenu/lineHeight.d.ts +4 -4
  128. package/src/plugins/submenu/lineHeight.js +104 -104
  129. package/src/plugins/submenu/list.d.ts +4 -4
  130. package/src/plugins/submenu/list.js +456 -456
  131. package/src/plugins/submenu/paragraphStyle.d.ts +4 -4
  132. package/src/plugins/submenu/paragraphStyle.js +135 -135
  133. package/src/plugins/submenu/table.d.ts +4 -4
  134. package/src/plugins/submenu/template.d.ts +4 -4
  135. package/src/plugins/submenu/template.js +71 -71
  136. package/src/plugins/submenu/textStyle.d.ts +4 -4
  137. package/src/plugins/submenu/textStyle.js +167 -167
  138. package/src/suneditor.d.ts +9 -9
  139. package/src/suneditor.js +75 -75
  140. package/src/suneditor_build.js +20 -17
  141. package/README_V3_TEMP.md +0 -630
@@ -1,989 +1,989 @@
1
- /*
2
- * wysiwyg web editor
3
- *
4
- * suneditor.js
5
- * Copyright 2017 JiHong Lee.
6
- * MIT license.
7
- */
8
- 'use strict';
9
-
10
- import dialog from '../modules/dialog';
11
- import component from '../modules/component';
12
- import resizing from '../modules/resizing';
13
- import fileManager from '../modules/fileManager';
14
-
15
- export default {
16
- name: 'video',
17
- display: 'dialog',
18
- add: function (core) {
19
- core.addModule([dialog, component, resizing, fileManager]);
20
-
21
- const options = core.options;
22
- const context = core.context;
23
- const contextVideo = context.video = {
24
- _infoList: [], // @Override fileManager
25
- _infoIndex: 0, // @Override fileManager
26
- _uploadFileLength: 0, // @Override fileManager
27
- focusElement: null, // @Override dialog // This element has focus when the dialog is opened.
28
- sizeUnit: options._videoSizeUnit,
29
- _align: 'none',
30
- _floatClassRegExp: '__se__float\\-[a-z]+',
31
- _youtubeQuery: options.youtubeQuery,
32
- _vimeoQuery: options.vimeoQuery,
33
- _videoRatio: (options.videoRatio * 100) + '%',
34
- _defaultRatio: (options.videoRatio * 100) + '%',
35
- _linkValue: '',
36
- // @require @Override component
37
- _element: null,
38
- _cover: null,
39
- _container: null,
40
- // @Override resizing properties
41
- inputX: null,
42
- inputY: null,
43
- _element_w: 1,
44
- _element_h: 1,
45
- _element_l: 0,
46
- _element_t: 0,
47
- _defaultSizeX: '100%',
48
- _defaultSizeY: (options.videoRatio * 100) + '%',
49
- _origin_w: options.videoWidth === '100%' ? '' : options.videoWidth,
50
- _origin_h: options.videoHeight === '56.25%' ? '' : options.videoHeight,
51
- _proportionChecked: true,
52
- _resizing: options.videoResizing,
53
- _resizeDotHide: !options.videoHeightShow,
54
- _rotation: options.videoRotation,
55
- _alignHide: !options.videoAlignShow,
56
- _onlyPercentage: options.videoSizeOnlyPercentage,
57
- _ratio: false,
58
- _ratioX: 1,
59
- _ratioY: 1,
60
- _captionShow: false
61
- };
62
-
63
- /** video dialog */
64
- let video_dialog = this.setDialog(core);
65
- contextVideo.modal = video_dialog;
66
- contextVideo.videoInputFile = video_dialog.querySelector('._se_video_file');
67
- contextVideo.videoUrlFile = video_dialog.querySelector('.se-input-url');
68
- contextVideo.focusElement = contextVideo.videoUrlFile || contextVideo.videoInputFile;
69
- contextVideo.preview = video_dialog.querySelector('.se-link-preview');
70
-
71
- /** add event listeners */
72
- video_dialog.querySelector('form').addEventListener('submit', this.submit.bind(core));
73
- if (contextVideo.videoInputFile) video_dialog.querySelector('.se-dialog-files-edge-button').addEventListener('click', this._removeSelectedFiles.bind(contextVideo.videoInputFile, contextVideo.videoUrlFile, contextVideo.preview));
74
- if (contextVideo.videoInputFile && contextVideo.videoUrlFile) contextVideo.videoInputFile.addEventListener('change', this._fileInputChange.bind(contextVideo));
75
- if (contextVideo.videoUrlFile) contextVideo.videoUrlFile.addEventListener('input', this._onLinkPreview.bind(contextVideo.preview, contextVideo, options.linkProtocol));
76
-
77
- contextVideo.proportion = {};
78
- contextVideo.videoRatioOption = {};
79
- contextVideo.inputX = {};
80
- contextVideo.inputY = {};
81
- if (options.videoResizing) {
82
- contextVideo.proportion = video_dialog.querySelector('._se_video_check_proportion');
83
- contextVideo.videoRatioOption = video_dialog.querySelector('.se-video-ratio');
84
- contextVideo.inputX = video_dialog.querySelector('._se_video_size_x');
85
- contextVideo.inputY = video_dialog.querySelector('._se_video_size_y');
86
- contextVideo.inputX.value = options.videoWidth;
87
- contextVideo.inputY.value = options.videoHeight;
88
-
89
- contextVideo.inputX.addEventListener('keyup', this.setInputSize.bind(core, 'x'));
90
- contextVideo.inputY.addEventListener('keyup', this.setInputSize.bind(core, 'y'));
91
-
92
- contextVideo.inputX.addEventListener('change', this.setRatio.bind(core));
93
- contextVideo.inputY.addEventListener('change', this.setRatio.bind(core));
94
- contextVideo.proportion.addEventListener('change', this.setRatio.bind(core));
95
- contextVideo.videoRatioOption.addEventListener('change', this.setVideoRatio.bind(core));
96
-
97
- video_dialog.querySelector('.se-dialog-btn-revert').addEventListener('click', this.sizeRevert.bind(core));
98
- }
99
-
100
- /** append html */
101
- context.dialog.modal.appendChild(video_dialog);
102
-
103
- /** empty memory */
104
- video_dialog = null;
105
- },
106
-
107
- /** dialog */
108
- setDialog: function (core) {
109
- const option = core.options;
110
- const lang = core.lang;
111
- const dialog = core.util.createElement('DIV');
112
-
113
- dialog.className = 'se-dialog-content';
114
- dialog.style.display = 'none';
115
- let html = '' +
116
- '<form method="post" enctype="multipart/form-data">' +
117
- '<div class="se-dialog-header">' +
118
- '<button type="button" data-command="close" class="se-btn se-dialog-close" title="' + lang.dialogBox.close + '" aria-label="' + lang.dialogBox.close + '">' +
119
- core.icons.cancel +
120
- '</button>' +
121
- '<span class="se-modal-title">' + lang.dialogBox.videoBox.title + '</span>' +
122
- '</div>' +
123
- '<div class="se-dialog-body">';
124
-
125
- if (option.videoFileInput) {
126
- html += '' +
127
- '<div class="se-dialog-form">' +
128
- '<label>' + lang.dialogBox.videoBox.file + '</label>' +
129
- '<div class="se-dialog-form-files">' +
130
- '<input class="se-input-form _se_video_file" type="file" accept="' + option.videoAccept + '"' + (option.videoMultipleFile ? ' multiple="multiple"' : '') + '/>' +
131
- '<button type="button" data-command="filesRemove" class="se-btn se-dialog-files-edge-button se-file-remove" title="' + lang.controller.remove + '" aria-label="' + lang.controller.remove + '">' + core.icons.cancel + '</button>' +
132
- '</div>' +
133
- '</div>' ;
134
- }
135
-
136
- if (option.videoUrlInput) {
137
- html += '' +
138
- '<div class="se-dialog-form">' +
139
- '<label>' + lang.dialogBox.videoBox.url + '</label>' +
140
- '<input class="se-input-form se-input-url" type="text" />' +
141
- '<pre class="se-link-preview"></pre>' +
142
- '</div>';
143
- }
144
-
145
- if (option.videoResizing) {
146
- const ratioList = option.videoRatioList || [{name: '16:9', value: 0.5625}, {name: '4:3', value: 0.75}, {name: '21:9', value: 0.4285}];
147
- const ratio = option.videoRatio;
148
- const onlyPercentage = option.videoSizeOnlyPercentage;
149
- const onlyPercentDisplay = onlyPercentage ? ' style="display: none !important;"' : '';
150
- const heightDisplay = !option.videoHeightShow ? ' style="display: none !important;"' : '';
151
- const ratioDisplay = !option.videoRatioShow ? ' style="display: none !important;"' : '';
152
- const onlyWidthDisplay = !onlyPercentage && !option.videoHeightShow && !option.videoRatioShow ? ' style="display: none !important;"' : '';
153
- html += '' +
154
- '<div class="se-dialog-form">' +
155
- '<div class="se-dialog-size-text">' +
156
- '<label class="size-w">' + lang.dialogBox.width + '</label>' +
157
- '<label class="se-dialog-size-x">&nbsp;</label>' +
158
- '<label class="size-h"' + heightDisplay + '>' + lang.dialogBox.height + '</label>' +
159
- '<label class="size-h"' + ratioDisplay + '>(' + lang.dialogBox.ratio + ')</label>' +
160
- '</div>' +
161
- '<input class="se-input-control _se_video_size_x" placeholder="100%"' + (onlyPercentage ? ' type="number" min="1"' : 'type="text"') + (onlyPercentage ? ' max="100"' : '') + '/>' +
162
- '<label class="se-dialog-size-x"' + onlyWidthDisplay + '>' + (onlyPercentage ? '%' : 'x') + '</label>' +
163
- '<input class="se-input-control _se_video_size_y" placeholder="' + (option.videoRatio * 100) + '%"' + (onlyPercentage ? ' type="number" min="1"' : 'type="text"') + (onlyPercentage ? ' max="100"' : '') + heightDisplay + '/>' +
164
- '<select class="se-input-select se-video-ratio" title="' + lang.dialogBox.ratio + '" aria-label="' + lang.dialogBox.ratio + '"' + ratioDisplay + '>';
165
- if (!heightDisplay) html += '<option value=""> - </option>';
166
- for (let i = 0, len = ratioList.length; i < len; i++) {
167
- html += '<option value="' + ratioList[i].value + '"' + (ratio.toString() === ratioList[i].value.toString() ? ' selected' : '') + '>' + ratioList[i].name + '</option>';
168
- }
169
- html += '</select>' +
170
- '<button type="button" title="' + lang.dialogBox.revertButton + '" aria-label="' + lang.dialogBox.revertButton + '" class="se-btn se-dialog-btn-revert" style="float: right;">' + core.icons.revert + '</button>' +
171
- '</div>' +
172
- '<div class="se-dialog-form se-dialog-form-footer"' + onlyPercentDisplay + onlyWidthDisplay + '>' +
173
- '<label><input type="checkbox" class="se-dialog-btn-check _se_video_check_proportion" checked/>&nbsp;' + lang.dialogBox.proportion + '</label>' +
174
- '</div>';
175
- }
176
-
177
- html += '' +
178
- '</div>' +
179
- '<div class="se-dialog-footer">' +
180
- '<div' + (option.videoAlignShow ? '' : ' style="display: none"') + '>' +
181
- '<label><input type="radio" name="suneditor_video_radio" class="se-dialog-btn-radio" value="none" checked>' + lang.dialogBox.basic + '</label>' +
182
- '<label><input type="radio" name="suneditor_video_radio" class="se-dialog-btn-radio" value="left">' + lang.dialogBox.left + '</label>' +
183
- '<label><input type="radio" name="suneditor_video_radio" class="se-dialog-btn-radio" value="center">' + lang.dialogBox.center + '</label>' +
184
- '<label><input type="radio" name="suneditor_video_radio" class="se-dialog-btn-radio" value="right">' + lang.dialogBox.right + '</label>' +
185
- '</div>' +
186
- '<button type="submit" class="se-btn-primary" title="' + lang.dialogBox.submitButton + '" aria-label="' + lang.dialogBox.submitButton + '"><span>' + lang.dialogBox.submitButton + '</span></button>' +
187
- '</div>' +
188
- '</form>';
189
-
190
- dialog.innerHTML = html;
191
-
192
- return dialog;
193
- },
194
-
195
- _fileInputChange: function () {
196
- if (!this.videoInputFile.value) {
197
- this.videoUrlFile.removeAttribute('disabled');
198
- this.preview.style.textDecoration = '';
199
- } else {
200
- this.videoUrlFile.setAttribute('disabled', true);
201
- this.preview.style.textDecoration = 'line-through';
202
- }
203
- },
204
-
205
- _removeSelectedFiles: function (urlInput, preview) {
206
- this.value = '';
207
- if (urlInput) {
208
- urlInput.removeAttribute('disabled');
209
- preview.style.textDecoration = '';
210
- }
211
- },
212
-
213
- _onLinkPreview: function (context, protocol, e) {
214
- const value = e.target.value.trim();
215
- if (/^<iframe.*\/iframe>$/.test(value)) {
216
- context._linkValue = value;
217
- this.textContent = '<IFrame :src=".."></IFrame>';
218
- } else {
219
- context._linkValue = this.textContent = !value ? '' : (protocol && value.indexOf('://') === -1 && value.indexOf('#') !== 0) ? protocol + value : value.indexOf('://') === -1 ? '/' + value : value;
220
- }
221
- },
222
-
223
- _setTagAttrs: function (element) {
224
- element.setAttribute('controls', true);
225
-
226
- const attrs = this.options.videoTagAttrs;
227
- if (!attrs) return;
228
-
229
- for (let key in attrs) {
230
- if (!this.util.hasOwn(attrs, key)) continue;
231
- element.setAttribute(key, attrs[key]);
232
- }
233
- },
234
-
235
- createVideoTag: function () {
236
- const videoTag = this.util.createElement('VIDEO');
237
- this.plugins.video._setTagAttrs.call(this, videoTag);
238
- return videoTag;
239
- },
240
-
241
- _setIframeAttrs: function (element) {
242
- element.frameBorder = '0';
243
- element.allowFullscreen = true;
244
-
245
- const attrs = this.options.videoIframeAttrs;
246
- if (!attrs) return;
247
-
248
- for (let key in attrs) {
249
- if (!this.util.hasOwn(attrs, key)) continue;
250
- element.setAttribute(key, attrs[key]);
251
- }
252
- },
253
-
254
- createIframeTag: function () {
255
- const iframeTag = this.util.createElement('IFRAME');
256
- this.plugins.video._setIframeAttrs.call(this, iframeTag);
257
- return iframeTag;
258
- },
259
-
260
- /**
261
- * @Override @Required fileManager
262
- */
263
- fileTags: ['iframe', 'video'],
264
-
265
- /**
266
- * @Override core, resizing, fileManager
267
- * @description It is called from core.selectComponent.
268
- * @param {Element} element Target element
269
- */
270
- select: function (element) {
271
- this.plugins.video.onModifyMode.call(this, element, this.plugins.resizing.call_controller_resize.call(this, element, 'video'));
272
- },
273
-
274
- /**
275
- * @Override fileManager, resizing
276
- */
277
- destroy: function (element) {
278
- const frame = element || this.context.video._element;
279
- const container = this.context.video._container;
280
- const dataIndex = frame.getAttribute('data-index') * 1;
281
-
282
- if (typeof this.functions.onVideoDeleteBefore === 'function' && (this.functions.onVideoDeleteBefore(frame, container, dataIndex, this) === false)) return;
283
-
284
- let focusEl = (container.previousElementSibling || container.nextElementSibling);
285
- const emptyDiv = container.parentNode;
286
- this.util.removeItem(container);
287
- this.plugins.video.init.call(this);
288
- this.controllersOff();
289
-
290
- if (emptyDiv !== this.context.element.wysiwyg) this.util.removeItemAllParents(emptyDiv, function (current) { return current.childNodes.length === 0; }, null);
291
-
292
- // focus
293
- this.focusEdge(focusEl);
294
-
295
- // event
296
- this.plugins.fileManager.deleteInfo.call(this, 'video', dataIndex, this.functions.onVideoUpload);
297
-
298
- // history stack
299
- this.history.push(false);
300
- },
301
-
302
- /**
303
- * @Required @Override dialog
304
- */
305
- on: function (update) {
306
- const contextVideo = this.context.video;
307
-
308
- if (!update) {
309
- contextVideo.inputX.value = contextVideo._origin_w = this.options.videoWidth === contextVideo._defaultSizeX ? '' : this.options.videoWidth;
310
- contextVideo.inputY.value = contextVideo._origin_h = this.options.videoHeight === contextVideo._defaultSizeY ? '' : this.options.videoHeight;
311
- contextVideo.proportion.disabled = true;
312
- if (contextVideo.videoInputFile && this.options.videoMultipleFile) contextVideo.videoInputFile.setAttribute('multiple', 'multiple');
313
- } else {
314
- if (contextVideo.videoInputFile && this.options.videoMultipleFile) contextVideo.videoInputFile.removeAttribute('multiple');
315
- }
316
-
317
- if (contextVideo._resizing) {
318
- this.plugins.video.setVideoRatioSelect.call(this, contextVideo._origin_h || contextVideo._defaultRatio);
319
- }
320
- },
321
-
322
- /**
323
- * @Required @Override dialog
324
- */
325
- open: function () {
326
- this.plugins.dialog.open.call(this, 'video', 'video' === this.currentControllerName);
327
- },
328
-
329
- setVideoRatio: function (e) {
330
- const contextVideo = this.context.video;
331
- const value = e.target.options[e.target.selectedIndex].value;
332
-
333
- contextVideo._defaultSizeY = contextVideo._videoRatio = !value ? contextVideo._defaultSizeY : (value * 100) + '%';
334
- contextVideo.inputY.placeholder = !value ? '' : (value * 100) + '%';
335
- contextVideo.inputY.value = '';
336
- },
337
-
338
- /**
339
- * @Override resizing
340
- * @param {String} xy 'x': width, 'y': height
341
- * @param {KeyboardEvent} e Event object
342
- */
343
- setInputSize: function (xy, e) {
344
- if (e && e.keyCode === 32) {
345
- e.preventDefault();
346
- return;
347
- }
348
-
349
- const contextVideo = this.context.video;
350
- this.plugins.resizing._module_setInputSize.call(this, contextVideo, xy);
351
-
352
- if (xy === 'y') {
353
- this.plugins.video.setVideoRatioSelect.call(this, e.target.value || contextVideo._defaultRatio);
354
- }
355
- },
356
-
357
- /**
358
- * @Override resizing
359
- */
360
- setRatio: function () {
361
- this.plugins.resizing._module_setRatio.call(this, this.context.video);
362
- },
363
-
364
- submit: function (e) {
365
- const contextVideo = this.context.video;
366
- const videoPlugin = this.plugins.video;
367
-
368
- e.preventDefault();
369
- e.stopPropagation();
370
-
371
- contextVideo._align = contextVideo.modal.querySelector('input[name="suneditor_video_radio"]:checked').value;
372
-
373
- try {
374
- if (contextVideo.videoInputFile && contextVideo.videoInputFile.files.length > 0) {
375
- this.showLoading();
376
- videoPlugin.submitAction.call(this, this.context.video.videoInputFile.files);
377
- } else if (contextVideo.videoUrlFile && contextVideo._linkValue.length > 0) {
378
- this.showLoading();
379
- videoPlugin.setup_url.call(this, contextVideo._linkValue);
380
- }
381
- } catch (error) {
382
- this.closeLoading();
383
- throw Error('[SUNEDITOR.video.submit.fail] cause : "' + error.message + '"');
384
- } finally {
385
- this.plugins.dialog.close.call(this);
386
- }
387
-
388
- return false;
389
- },
390
-
391
- submitAction: function (fileList) {
392
- if (fileList.length === 0) return;
393
-
394
- let fileSize = 0;
395
- let files = [];
396
- for (let i = 0, len = fileList.length; i < len; i++) {
397
- if (/video/i.test(fileList[i].type)) {
398
- files.push(fileList[i]);
399
- fileSize += fileList[i].size;
400
- }
401
- }
402
-
403
- const limitSize = this.options.videoUploadSizeLimit;
404
- if (limitSize > 0) {
405
- let infoSize = 0;
406
- const videosInfo = this.context.video._infoList;
407
- for (let i = 0, len = videosInfo.length; i < len; i++) {
408
- infoSize += videosInfo[i].size * 1;
409
- }
410
-
411
- if ((fileSize + infoSize) > limitSize) {
412
- this.closeLoading();
413
- const err = '[SUNEDITOR.videoUpload.fail] Size of uploadable total videos: ' + (limitSize/1000) + 'KB';
414
- if (typeof this.functions.onVideoUploadError !== 'function' || this.functions.onVideoUploadError(err, { 'limitSize': limitSize, 'currentSize': infoSize, 'uploadSize': fileSize }, this)) {
415
- this.functions.noticeOpen(err);
416
- }
417
- return;
418
- }
419
- }
420
-
421
- const contextVideo = this.context.video;
422
- contextVideo._uploadFileLength = files.length;
423
-
424
- const info = {
425
- inputWidth: contextVideo.inputX.value,
426
- inputHeight: contextVideo.inputY.value,
427
- align: contextVideo._align,
428
- isUpdate: this.context.dialog.updateModal,
429
- element: contextVideo._element
430
- };
431
-
432
- if (typeof this.functions.onVideoUploadBefore === 'function') {
433
- const result = this.functions.onVideoUploadBefore(files, info, this, function (data) {
434
- if (data && this._w.Array.isArray(data.result)) {
435
- this.plugins.video.register.call(this, info, data);
436
- } else {
437
- this.plugins.video.upload.call(this, info, data);
438
- }
439
- }.bind(this));
440
-
441
- if (typeof result === 'undefined') return;
442
- if (!result) {
443
- this.closeLoading();
444
- return;
445
- }
446
- if (typeof result === 'object' && result.length > 0) files = result;
447
- }
448
-
449
- this.plugins.video.upload.call(this, info, files);
450
- },
451
-
452
- error: function (message, response) {
453
- this.closeLoading();
454
- if (typeof this.functions.onVideoUploadError !== 'function' || this.functions.onVideoUploadError(message, response, this)) {
455
- this.functions.noticeOpen(message);
456
- throw Error('[SUNEDITOR.plugin.video.error] response: ' + message);
457
- }
458
- },
459
-
460
- upload: function (info, files) {
461
- if (!files) {
462
- this.closeLoading();
463
- return;
464
- }
465
- if (typeof files === 'string') {
466
- this.plugins.video.error.call(this, files, null);
467
- return;
468
- }
469
-
470
- const videoUploadUrl = this.options.videoUploadUrl;
471
- const filesLen = this.context.dialog.updateModal ? 1 : files.length;
472
-
473
- // server upload
474
- if (typeof videoUploadUrl === 'string' && videoUploadUrl.length > 0) {
475
- const formData = new FormData();
476
- for (let i = 0; i < filesLen; i++) {
477
- formData.append('file-' + i, files[i]);
478
- }
479
- this.plugins.fileManager.upload.call(this, videoUploadUrl, this.options.videoUploadHeader, formData, this.plugins.video.callBack_videoUpload.bind(this, info), this.functions.onVideoUploadError);
480
- } else {
481
- throw Error('[SUNEDITOR.videoUpload.fail] cause : There is no "videoUploadUrl" option.');
482
- }
483
- },
484
-
485
- callBack_videoUpload: function (info, xmlHttp) {
486
- if (typeof this.functions.videoUploadHandler === 'function') {
487
- this.functions.videoUploadHandler(xmlHttp, info, this);
488
- } else {
489
- const response = JSON.parse(xmlHttp.responseText);
490
- if (response.errorMessage) {
491
- this.plugins.video.error.call(this, response.errorMessage, response);
492
- } else {
493
- this.plugins.video.register.call(this, info, response);
494
- }
495
- }
496
- },
497
-
498
- register: function (info, response) {
499
- const fileList = response.result;
500
- const videoTag = this.plugins.video.createVideoTag.call(this);
501
-
502
- for (let i = 0, len = fileList.length, file; i < len; i++) {
503
- file = { name: fileList[i].name, size: fileList[i].size };
504
- this.plugins.video.create_video.call(this, (info.isUpdate ? info.element : videoTag.cloneNode(false)), fileList[i].url, info.inputWidth, info.inputHeight, info.align, file, info.isUpdate);
505
- }
506
-
507
- this.closeLoading();
508
- },
509
-
510
- setup_url: function (url) {
511
- try {
512
- const contextVideo = this.context.video;
513
- if (!url) url = contextVideo._linkValue;
514
- if (!url) return false;
515
-
516
- /** iframe source */
517
- if (/^<iframe.*\/iframe>$/.test(url)) {
518
- const oIframe = (new this._w.DOMParser()).parseFromString(url, 'text/html').querySelector('iframe');
519
- url = oIframe.src;
520
- if (url.length === 0) return false;
521
- }
522
-
523
- /** youtube */
524
- if (/youtu\.?be/.test(url)) {
525
- if (!/^http/.test(url)) url = 'https://' + url;
526
- url = url.replace('watch?v=', '');
527
- if (!/^\/\/.+\/embed\//.test(url)) {
528
- url = url.replace(url.match(/\/\/.+\//)[0], '//www.youtube.com/embed/').replace('&', '?&');
529
- }
530
-
531
- if (contextVideo._youtubeQuery.length > 0) {
532
- if (/\?/.test(url)) {
533
- const splitUrl = url.split('?');
534
- url = splitUrl[0] + '?' + contextVideo._youtubeQuery + '&' + splitUrl[1];
535
- } else {
536
- url += '?' + contextVideo._youtubeQuery;
537
- }
538
- }
539
- } else if (/vimeo\.com/.test(url)) {
540
- if (url.endsWith('/')) {
541
- url = url.slice(0, -1);
542
- }
543
- url = 'https://player.vimeo.com/video/' + url.slice(url.lastIndexOf('/') + 1);
544
-
545
- if (contextVideo._vimeoQuery.length > 0) {
546
- if (/\?/.test(url)) {
547
- const splitUrl = url.split('?');
548
- url = splitUrl[0] + '?' + contextVideo._vimeoQuery + '&' + splitUrl[1];
549
- } else {
550
- url += '?' + contextVideo._vimeoQuery;
551
- }
552
- }
553
- }
554
-
555
- this.plugins.video.create_video.call(this, this.plugins.video[(!/embed|iframe|player|\/e\/|\.php|\.html?/.test(url) && !/vimeo\.com/.test(url) ? "createVideoTag" : "createIframeTag")].call(this), url, contextVideo.inputX.value, contextVideo.inputY.value, contextVideo._align, null, this.context.dialog.updateModal);
556
- } catch (error) {
557
- throw Error('[SUNEDITOR.video.upload.fail] cause : "' + error.message + '"');
558
- } finally {
559
- this.closeLoading();
560
- }
561
- },
562
-
563
- create_video: function (oFrame, src, width, height, align, file, isUpdate) {
564
- this.context.resizing._resize_plugin = 'video';
565
- const contextVideo = this.context.video;
566
-
567
- let cover = null;
568
- let container = null;
569
- let init = false;
570
-
571
- /** update */
572
- if (isUpdate) {
573
- oFrame = contextVideo._element;
574
- if (oFrame.src !== src) {
575
- init = true;
576
- const isYoutube = /youtu\.?be/.test(src);
577
- const isVimeo = /vimeo\.com/.test(src);
578
- if ((isYoutube || isVimeo) && !/^iframe$/i.test(oFrame.nodeName)) {
579
- const newTag = this.plugins.video.createIframeTag.call(this);
580
- newTag.src = src;
581
- oFrame.parentNode.replaceChild(newTag, oFrame);
582
- contextVideo._element = oFrame = newTag;
583
- } else if (!isYoutube && !isVimeo && !/^video$/i.test(oFrame.nodeName)) {
584
- const newTag = this.plugins.video.createVideoTag.call(this);
585
- newTag.src = src;
586
- oFrame.parentNode.replaceChild(newTag, oFrame);
587
- contextVideo._element = oFrame = newTag;
588
- } else {
589
- oFrame.src = src;
590
- }
591
- }
592
- container = contextVideo._container;
593
- cover = this.util.getParentElement(oFrame, 'FIGURE');
594
- }
595
- /** create */
596
- else {
597
- init = true;
598
- oFrame.src = src;
599
- contextVideo._element = oFrame;
600
- cover = this.plugins.component.set_cover.call(this, oFrame);
601
- container = this.plugins.component.set_container.call(this, cover, 'se-video-container');
602
- }
603
-
604
- /** rendering */
605
- contextVideo._cover = cover;
606
- contextVideo._container = container;
607
-
608
- const inputUpdate = (this.plugins.resizing._module_getSizeX.call(this, contextVideo) !== (width || contextVideo._defaultSizeX)) || (this.plugins.resizing._module_getSizeY.call(this, contextVideo) !== (height || contextVideo._videoRatio));
609
- const changeSize = !isUpdate || inputUpdate;
610
-
611
- if (contextVideo._resizing) {
612
- this.context.video._proportionChecked = contextVideo.proportion.checked;
613
- oFrame.setAttribute('data-proportion', contextVideo._proportionChecked);
614
- }
615
-
616
- // size
617
- let isPercent = false;
618
- if (changeSize) {
619
- isPercent = this.plugins.video.applySize.call(this);
620
- }
621
-
622
- // align
623
- if (!(isPercent && align === 'center')) {
624
- this.plugins.video.setAlign.call(this, null, oFrame, cover, container);
625
- }
626
-
627
- let changed = true;
628
- if (!isUpdate) {
629
- changed = this.insertComponent(container, false, true, !this.options.mediaAutoSelect);
630
- if (!this.options.mediaAutoSelect) {
631
- const line = this.appendFormatTag(container, null);
632
- if (line) this.setRange(line, 0, line, 0);
633
- }
634
- } else if (contextVideo._resizing && this.context.resizing._rotateVertical && changeSize) {
635
- this.plugins.resizing.setTransformSize.call(this, oFrame, null, null);
636
- }
637
-
638
- if (changed) {
639
- if (init) {
640
- this.plugins.fileManager.setInfo.call(this, 'video', oFrame, this.functions.onVideoUpload, file, true);
641
- }
642
- if (isUpdate) {
643
- this.selectComponent(oFrame, 'video');
644
- // history stack
645
- this.history.push(false);
646
- }
647
- }
648
-
649
- this.context.resizing._resize_plugin = '';
650
- },
651
-
652
- _update_videoCover: function (oFrame) {
653
- if (!oFrame) return;
654
-
655
- const contextVideo = this.context.video;
656
-
657
- if (/^video$/i.test(oFrame.nodeName)) this.plugins.video._setTagAttrs.call(this, oFrame);
658
- else this.plugins.video._setIframeAttrs.call(this, oFrame);
659
-
660
- let existElement = (this.util.isRangeFormatElement(oFrame.parentNode) || this.util.isWysiwygDiv(oFrame.parentNode)) ?
661
- oFrame : this.util.getFormatElement(oFrame) || oFrame;
662
-
663
- const prevFrame = oFrame;
664
- contextVideo._element = oFrame = oFrame.cloneNode(true);
665
- const cover = contextVideo._cover = this.plugins.component.set_cover.call(this, oFrame);
666
- const container = contextVideo._container = this.plugins.component.set_container.call(this, cover, 'se-video-container');
667
-
668
- try {
669
- const figcaption = existElement.querySelector('figcaption');
670
- let caption = null;
671
- if (!!figcaption) {
672
- caption = this.util.createElement('DIV');
673
- caption.innerHTML = figcaption.innerHTML;
674
- this.util.removeItem(figcaption);
675
- }
676
-
677
- // size
678
- const size = (oFrame.getAttribute('data-size') || oFrame.getAttribute('data-origin') || '').split(',');
679
- this.plugins.video.applySize.call(this, (size[0] || prevFrame.style.width || prevFrame.width || ''), (size[1] || prevFrame.style.height || prevFrame.height || ''));
680
-
681
- // align
682
- const format = this.util.getFormatElement(prevFrame);
683
- if (format) contextVideo._align = format.style.textAlign || format.style.float;
684
- this.plugins.video.setAlign.call(this, null, oFrame, cover, container);
685
-
686
- if (this.util.getParentElement(prevFrame, this.util.isNotCheckingNode)) {
687
- prevFrame.parentNode.replaceChild(container, prevFrame);
688
- } else if (this.util.isListCell(existElement)) {
689
- const refer = this.util.getParentElement(prevFrame, function (current) { return current.parentNode === existElement; });
690
- existElement.insertBefore(container, refer);
691
- this.util.removeItem(prevFrame);
692
- this.util.removeEmptyNode(refer, null, true);
693
- } else if (this.util.isFormatElement(existElement)) {
694
- const refer = this.util.getParentElement(prevFrame, function (current) { return current.parentNode === existElement; });
695
- existElement = this.util.splitElement(existElement, refer);
696
- existElement.parentNode.insertBefore(container, existElement);
697
- this.util.removeItem(prevFrame);
698
- this.util.removeEmptyNode(existElement, null, true);
699
- if (existElement.children.length === 0) existElement.innerHTML = this.util.htmlRemoveWhiteSpace(existElement.innerHTML);
700
- } else {
701
- existElement.parentNode.replaceChild(container, existElement);
702
- }
703
-
704
- if (!!caption) existElement.parentNode.insertBefore(caption, container.nextElementSibling);
705
- } catch (error) {
706
- console.warn('[SUNEDITOR.video.error] Maybe the video tag is nested.', error);
707
- }
708
-
709
- this.plugins.fileManager.setInfo.call(this, 'video', oFrame, this.functions.onVideoUpload, null, true);
710
- this.plugins.video.init.call(this);
711
- },
712
-
713
- /**
714
- * @Required @Override fileManager, resizing
715
- */
716
- onModifyMode: function (element, size) {
717
- const contextVideo = this.context.video;
718
- contextVideo._element = element;
719
- contextVideo._cover = this.util.getParentElement(element, 'FIGURE');
720
- contextVideo._container = this.util.getParentElement(element, this.util.isMediaComponent);
721
- contextVideo._align = element.style.float || element.getAttribute('data-align') || 'none';
722
- element.style.float = '';
723
-
724
- if (size) {
725
- contextVideo._element_w = size.w;
726
- contextVideo._element_h = size.h;
727
- contextVideo._element_t = size.t;
728
- contextVideo._element_l = size.l;
729
- }
730
-
731
- let origin = contextVideo._element.getAttribute('data-size') || contextVideo._element.getAttribute('data-origin');
732
- let w, h;
733
- if (origin) {
734
- origin = origin.split(',');
735
- w = origin[0];
736
- h = origin[1];
737
- } else if (size) {
738
- w = size.w;
739
- h = size.h;
740
- }
741
-
742
- contextVideo._origin_w = w || element.style.width || element.width || '';
743
- contextVideo._origin_h = h || element.style.height || element.height || '';
744
- },
745
-
746
- /**
747
- * @Required @Override fileManager, resizing
748
- */
749
- openModify: function (notOpen) {
750
- const contextVideo = this.context.video;
751
-
752
- if (contextVideo.videoUrlFile) contextVideo._linkValue = contextVideo.preview.textContent = contextVideo.videoUrlFile.value = (contextVideo._element.src || (contextVideo._element.querySelector('source') || '').src || '');
753
- (contextVideo.modal.querySelector('input[name="suneditor_video_radio"][value="' + contextVideo._align + '"]') || contextVideo.modal.querySelector('input[name="suneditor_video_radio"][value="none"]')).checked = true;
754
-
755
- if (contextVideo._resizing) {
756
- this.plugins.resizing._module_setModifyInputSize.call(this, contextVideo, this.plugins.video);
757
-
758
- const y = contextVideo._videoRatio = this.plugins.resizing._module_getSizeY.call(this, contextVideo);
759
- const ratioSelected = this.plugins.video.setVideoRatioSelect.call(this, y);
760
- if (!ratioSelected) contextVideo.inputY.value = contextVideo._onlyPercentage ? this.util.getNumber(y, 2) : y;
761
- }
762
-
763
- if (!notOpen) this.plugins.dialog.open.call(this, 'video', true);
764
- },
765
-
766
- setVideoRatioSelect: function (value) {
767
- let ratioSelected = false;
768
- const contextVideo = this.context.video;
769
- const ratioOptions = contextVideo.videoRatioOption.options;
770
-
771
- if (/%$/.test(value) || contextVideo._onlyPercentage) value = (this.util.getNumber(value, 2) / 100) + '';
772
- else if (!this.util.isNumber(value) || (value * 1) >= 1) value = '';
773
-
774
- contextVideo.inputY.placeholder = '';
775
- for (let i = 0, len = ratioOptions.length; i < len; i++) {
776
- if (ratioOptions[i].value === value) {
777
- ratioSelected = ratioOptions[i].selected = true;
778
- contextVideo.inputY.placeholder = !value ? '' : (value * 100) + '%';
779
- }
780
- else ratioOptions[i].selected = false;
781
- }
782
-
783
- return ratioSelected;
784
- },
785
-
786
- /**
787
- * @Override fileManager
788
- */
789
- checkFileInfo: function () {
790
- this.plugins.fileManager.checkInfo.call(this, 'video', ['iframe', 'video'], this.functions.onVideoUpload, this.plugins.video._update_videoCover.bind(this), true);
791
- },
792
-
793
- /**
794
- * @Override fileManager
795
- */
796
- resetFileInfo: function () {
797
- this.plugins.fileManager.resetInfo.call(this, 'video', this.functions.onVideoUpload);
798
- },
799
-
800
- /**
801
- * @Override fileManager
802
- */
803
- applySize: function (w, h) {
804
- const contextVideo = this.context.video;
805
-
806
- if (!w) w = contextVideo.inputX.value || this.options.videoWidth;
807
- if (!h) h = contextVideo.inputY.value || this.options.videoHeight;
808
-
809
- if (contextVideo._onlyPercentage || /%$/.test(w) || !w) {
810
- this.plugins.video.setPercentSize.call(this, (w || '100%'), (h || (/%$/.test(contextVideo._videoRatio) ? contextVideo._videoRatio : contextVideo._defaultRatio)));
811
- return true;
812
- } else if ((!w || w === 'auto') && (!h || h === 'auto')) {
813
- this.plugins.video.setAutoSize.call(this);
814
- } else {
815
- this.plugins.video.setSize.call(this, w, (h || contextVideo._videoRatio || contextVideo._defaultRatio), false);
816
- }
817
-
818
- return false;
819
- },
820
-
821
- /**
822
- * @Override resizing
823
- */
824
- sizeRevert: function () {
825
- this.plugins.resizing._module_sizeRevert.call(this, this.context.video);
826
- },
827
-
828
- /**
829
- * @Override resizing
830
- */
831
- setSize: function (w, h, notResetPercentage, direction) {
832
- const contextVideo = this.context.video;
833
- const onlyW = /^(rw|lw)$/.test(direction);
834
- const onlyH = /^(th|bh)$/.test(direction);
835
-
836
- if (!onlyH) w = this.util.getNumber(w, 0);
837
- if (!onlyW) h = this.util.isNumber(h) ? h + contextVideo.sizeUnit : !h ? '' : h;
838
- w = w ? w + contextVideo.sizeUnit : '';
839
-
840
- if (!onlyH) contextVideo._element.style.width = w;
841
- if (!onlyW) contextVideo._cover.style.paddingBottom = contextVideo._cover.style.height = h;
842
-
843
- if (!onlyH && !/%$/.test(w)) {
844
- contextVideo._cover.style.width = w;
845
- contextVideo._container.style.width = '';
846
- }
847
-
848
- if (!onlyW && !/%$/.test(h)) {
849
- contextVideo._element.style.height = h;
850
- } else {
851
- contextVideo._element.style.height = '';
852
- }
853
-
854
- if (!notResetPercentage) contextVideo._element.removeAttribute('data-percentage');
855
-
856
- // save current size
857
- this.plugins.resizing._module_saveCurrentSize.call(this, contextVideo);
858
- },
859
-
860
- /**
861
- * @Override resizing
862
- */
863
- setAutoSize: function () {
864
- this.plugins.video.setPercentSize.call(this, 100, this.context.video._defaultRatio);
865
- },
866
-
867
- /**
868
- * @Override resizing
869
- */
870
- setOriginSize: function (dataSize) {
871
- const contextVideo = this.context.video;
872
- contextVideo._element.removeAttribute('data-percentage');
873
-
874
- this.plugins.resizing.resetTransform.call(this, contextVideo._element);
875
- this.plugins.video.cancelPercentAttr.call(this);
876
-
877
- const originSize = ((dataSize ? contextVideo._element.getAttribute('data-size') : '') || contextVideo._element.getAttribute('data-origin') || '').split(',');
878
-
879
- if (originSize) {
880
- const w = originSize[0];
881
- const h = originSize[1];
882
-
883
- if (contextVideo._onlyPercentage || (/%$/.test(w) && (/%$/.test(h) || !/\d/.test(h)))) {
884
- this.plugins.video.setPercentSize.call(this, w, h);
885
- } else {
886
- this.plugins.video.setSize.call(this, w, h);
887
- }
888
-
889
- // save current size
890
- this.plugins.resizing._module_saveCurrentSize.call(this, contextVideo);
891
- }
892
- },
893
-
894
- /**
895
- * @Override resizing
896
- */
897
- setPercentSize: function (w, h) {
898
- const contextVideo = this.context.video;
899
- h = !!h && !/%$/.test(h) && !this.util.getNumber(h, 0) ? this.util.isNumber(h) ? h + '%' : h : this.util.isNumber(h) ? h + contextVideo.sizeUnit : (h || contextVideo._defaultRatio);
900
-
901
- contextVideo._container.style.width = this.util.isNumber(w) ? w + '%' : w;
902
- contextVideo._container.style.height = '';
903
- contextVideo._cover.style.width = '100%';
904
- contextVideo._cover.style.height = h;
905
- contextVideo._cover.style.paddingBottom = h;
906
- contextVideo._element.style.width = '100%';
907
- contextVideo._element.style.height = '100%';
908
- contextVideo._element.style.maxWidth = '';
909
-
910
- if (contextVideo._align === 'center') this.plugins.video.setAlign.call(this, null, null, null, null);
911
- contextVideo._element.setAttribute('data-percentage', w + ',' + h);
912
-
913
- // save current size
914
- this.plugins.resizing._module_saveCurrentSize.call(this, contextVideo);
915
- },
916
-
917
- /**
918
- * @Override resizing
919
- */
920
- cancelPercentAttr: function () {
921
- const contextVideo = this.context.video;
922
-
923
- contextVideo._cover.style.width = '';
924
- contextVideo._cover.style.height = '';
925
- contextVideo._cover.style.paddingBottom = '';
926
- contextVideo._container.style.width = '';
927
- contextVideo._container.style.height = '';
928
-
929
- this.util.removeClass(contextVideo._container, this.context.video._floatClassRegExp);
930
- this.util.addClass(contextVideo._container, '__se__float-' + contextVideo._align);
931
-
932
- if (contextVideo._align === 'center') this.plugins.video.setAlign.call(this, null, null, null, null);
933
- },
934
-
935
- /**
936
- * @Override resizing
937
- */
938
- setAlign: function (align, element, cover, container) {
939
- const contextVideo = this.context.video;
940
-
941
- if (!align) align = contextVideo._align;
942
- if (!element) element = contextVideo._element;
943
- if (!cover) cover = contextVideo._cover;
944
- if (!container) container = contextVideo._container;
945
-
946
- if (/%$/.test(element.style.width) && align === 'center') {
947
- container.style.minWidth = '100%';
948
- cover.style.width = container.style.width;
949
- cover.style.height = cover.style.height;
950
- cover.style.paddingBottom = !/%$/.test(cover.style.height) ? cover.style.height : this.util.getNumber((this.util.getNumber(cover.style.height, 2) / 100) * this.util.getNumber(cover.style.width, 2), 2) + '%';
951
- } else {
952
- container.style.minWidth = '';
953
- cover.style.width = this.context.resizing._rotateVertical ? (element.style.height || element.offsetHeight) : (element.style.width || '100%');
954
- cover.style.paddingBottom = cover.style.height;
955
- }
956
-
957
- if (!this.util.hasClass(container, '__se__float-' + align)) {
958
- this.util.removeClass(container, contextVideo._floatClassRegExp);
959
- this.util.addClass(container, '__se__float-' + align);
960
- }
961
-
962
- element.setAttribute('data-align', align);
963
- },
964
-
965
- /**
966
- * @Override dialog
967
- */
968
- init: function () {
969
- const contextVideo = this.context.video;
970
- if (contextVideo.videoInputFile) contextVideo.videoInputFile.value = '';
971
- if (contextVideo.videoUrlFile) contextVideo._linkValue = contextVideo.preview.textContent = contextVideo.videoUrlFile.value = '';
972
- if (contextVideo.videoInputFile && contextVideo.videoUrlFile) {
973
- contextVideo.videoUrlFile.removeAttribute('disabled');
974
- contextVideo.preview.style.textDecoration = '';
975
- }
976
-
977
- contextVideo._origin_w = this.options.videoWidth;
978
- contextVideo._origin_h = this.options.videoHeight;
979
- contextVideo.modal.querySelector('input[name="suneditor_video_radio"][value="none"]').checked = true;
980
-
981
- if (contextVideo._resizing) {
982
- contextVideo.inputX.value = this.options.videoWidth === contextVideo._defaultSizeX ? '' : this.options.videoWidth;
983
- contextVideo.inputY.value = this.options.videoHeight === contextVideo._defaultSizeY ? '' : this.options.videoHeight;
984
- contextVideo.proportion.checked = true;
985
- contextVideo.proportion.disabled = true;
986
- this.plugins.video.setVideoRatioSelect.call(this, contextVideo._defaultRatio);
987
- }
988
- }
989
- };
1
+ /*
2
+ * wysiwyg web editor
3
+ *
4
+ * suneditor.js
5
+ * Copyright 2017 JiHong Lee.
6
+ * MIT license.
7
+ */
8
+ 'use strict';
9
+
10
+ import dialog from '../modules/dialog';
11
+ import component from '../modules/component';
12
+ import resizing from '../modules/resizing';
13
+ import fileManager from '../modules/fileManager';
14
+
15
+ export default {
16
+ name: 'video',
17
+ display: 'dialog',
18
+ add: function (core) {
19
+ core.addModule([dialog, component, resizing, fileManager]);
20
+
21
+ const options = core.options;
22
+ const context = core.context;
23
+ const contextVideo = context.video = {
24
+ _infoList: [], // @Override fileManager
25
+ _infoIndex: 0, // @Override fileManager
26
+ _uploadFileLength: 0, // @Override fileManager
27
+ focusElement: null, // @Override dialog // This element has focus when the dialog is opened.
28
+ sizeUnit: options._videoSizeUnit,
29
+ _align: 'none',
30
+ _floatClassRegExp: '__se__float\\-[a-z]+',
31
+ _youtubeQuery: options.youtubeQuery,
32
+ _vimeoQuery: options.vimeoQuery,
33
+ _videoRatio: (options.videoRatio * 100) + '%',
34
+ _defaultRatio: (options.videoRatio * 100) + '%',
35
+ _linkValue: '',
36
+ // @require @Override component
37
+ _element: null,
38
+ _cover: null,
39
+ _container: null,
40
+ // @Override resizing properties
41
+ inputX: null,
42
+ inputY: null,
43
+ _element_w: 1,
44
+ _element_h: 1,
45
+ _element_l: 0,
46
+ _element_t: 0,
47
+ _defaultSizeX: '100%',
48
+ _defaultSizeY: (options.videoRatio * 100) + '%',
49
+ _origin_w: options.videoWidth === '100%' ? '' : options.videoWidth,
50
+ _origin_h: options.videoHeight === '56.25%' ? '' : options.videoHeight,
51
+ _proportionChecked: true,
52
+ _resizing: options.videoResizing,
53
+ _resizeDotHide: !options.videoHeightShow,
54
+ _rotation: options.videoRotation,
55
+ _alignHide: !options.videoAlignShow,
56
+ _onlyPercentage: options.videoSizeOnlyPercentage,
57
+ _ratio: false,
58
+ _ratioX: 1,
59
+ _ratioY: 1,
60
+ _captionShow: false
61
+ };
62
+
63
+ /** video dialog */
64
+ let video_dialog = this.setDialog(core);
65
+ contextVideo.modal = video_dialog;
66
+ contextVideo.videoInputFile = video_dialog.querySelector('._se_video_file');
67
+ contextVideo.videoUrlFile = video_dialog.querySelector('.se-input-url');
68
+ contextVideo.focusElement = contextVideo.videoUrlFile || contextVideo.videoInputFile;
69
+ contextVideo.preview = video_dialog.querySelector('.se-link-preview');
70
+
71
+ /** add event listeners */
72
+ video_dialog.querySelector('form').addEventListener('submit', this.submit.bind(core));
73
+ if (contextVideo.videoInputFile) video_dialog.querySelector('.se-dialog-files-edge-button').addEventListener('click', this._removeSelectedFiles.bind(contextVideo.videoInputFile, contextVideo.videoUrlFile, contextVideo.preview));
74
+ if (contextVideo.videoInputFile && contextVideo.videoUrlFile) contextVideo.videoInputFile.addEventListener('change', this._fileInputChange.bind(contextVideo));
75
+ if (contextVideo.videoUrlFile) contextVideo.videoUrlFile.addEventListener('input', this._onLinkPreview.bind(contextVideo.preview, contextVideo, options.linkProtocol));
76
+
77
+ contextVideo.proportion = {};
78
+ contextVideo.videoRatioOption = {};
79
+ contextVideo.inputX = {};
80
+ contextVideo.inputY = {};
81
+ if (options.videoResizing) {
82
+ contextVideo.proportion = video_dialog.querySelector('._se_video_check_proportion');
83
+ contextVideo.videoRatioOption = video_dialog.querySelector('.se-video-ratio');
84
+ contextVideo.inputX = video_dialog.querySelector('._se_video_size_x');
85
+ contextVideo.inputY = video_dialog.querySelector('._se_video_size_y');
86
+ contextVideo.inputX.value = options.videoWidth;
87
+ contextVideo.inputY.value = options.videoHeight;
88
+
89
+ contextVideo.inputX.addEventListener('keyup', this.setInputSize.bind(core, 'x'));
90
+ contextVideo.inputY.addEventListener('keyup', this.setInputSize.bind(core, 'y'));
91
+
92
+ contextVideo.inputX.addEventListener('change', this.setRatio.bind(core));
93
+ contextVideo.inputY.addEventListener('change', this.setRatio.bind(core));
94
+ contextVideo.proportion.addEventListener('change', this.setRatio.bind(core));
95
+ contextVideo.videoRatioOption.addEventListener('change', this.setVideoRatio.bind(core));
96
+
97
+ video_dialog.querySelector('.se-dialog-btn-revert').addEventListener('click', this.sizeRevert.bind(core));
98
+ }
99
+
100
+ /** append html */
101
+ context.dialog.modal.appendChild(video_dialog);
102
+
103
+ /** empty memory */
104
+ video_dialog = null;
105
+ },
106
+
107
+ /** dialog */
108
+ setDialog: function (core) {
109
+ const option = core.options;
110
+ const lang = core.lang;
111
+ const dialog = core.util.createElement('DIV');
112
+
113
+ dialog.className = 'se-dialog-content';
114
+ dialog.style.display = 'none';
115
+ let html = '' +
116
+ '<form method="post" enctype="multipart/form-data">' +
117
+ '<div class="se-dialog-header">' +
118
+ '<button type="button" data-command="close" class="se-btn se-dialog-close" title="' + lang.dialogBox.close + '" aria-label="' + lang.dialogBox.close + '">' +
119
+ core.icons.cancel +
120
+ '</button>' +
121
+ '<span class="se-modal-title">' + lang.dialogBox.videoBox.title + '</span>' +
122
+ '</div>' +
123
+ '<div class="se-dialog-body">';
124
+
125
+ if (option.videoFileInput) {
126
+ html += '' +
127
+ '<div class="se-dialog-form">' +
128
+ '<label>' + lang.dialogBox.videoBox.file + '</label>' +
129
+ '<div class="se-dialog-form-files">' +
130
+ '<input class="se-input-form _se_video_file" type="file" accept="' + option.videoAccept + '"' + (option.videoMultipleFile ? ' multiple="multiple"' : '') + '/>' +
131
+ '<button type="button" data-command="filesRemove" class="se-btn se-dialog-files-edge-button se-file-remove" title="' + lang.controller.remove + '" aria-label="' + lang.controller.remove + '">' + core.icons.cancel + '</button>' +
132
+ '</div>' +
133
+ '</div>' ;
134
+ }
135
+
136
+ if (option.videoUrlInput) {
137
+ html += '' +
138
+ '<div class="se-dialog-form">' +
139
+ '<label>' + lang.dialogBox.videoBox.url + '</label>' +
140
+ '<input class="se-input-form se-input-url" type="text" />' +
141
+ '<pre class="se-link-preview"></pre>' +
142
+ '</div>';
143
+ }
144
+
145
+ if (option.videoResizing) {
146
+ const ratioList = option.videoRatioList || [{name: '16:9', value: 0.5625}, {name: '4:3', value: 0.75}, {name: '21:9', value: 0.4285}];
147
+ const ratio = option.videoRatio;
148
+ const onlyPercentage = option.videoSizeOnlyPercentage;
149
+ const onlyPercentDisplay = onlyPercentage ? ' style="display: none !important;"' : '';
150
+ const heightDisplay = !option.videoHeightShow ? ' style="display: none !important;"' : '';
151
+ const ratioDisplay = !option.videoRatioShow ? ' style="display: none !important;"' : '';
152
+ const onlyWidthDisplay = !onlyPercentage && !option.videoHeightShow && !option.videoRatioShow ? ' style="display: none !important;"' : '';
153
+ html += '' +
154
+ '<div class="se-dialog-form">' +
155
+ '<div class="se-dialog-size-text">' +
156
+ '<label class="size-w">' + lang.dialogBox.width + '</label>' +
157
+ '<label class="se-dialog-size-x">&nbsp;</label>' +
158
+ '<label class="size-h"' + heightDisplay + '>' + lang.dialogBox.height + '</label>' +
159
+ '<label class="size-h"' + ratioDisplay + '>(' + lang.dialogBox.ratio + ')</label>' +
160
+ '</div>' +
161
+ '<input class="se-input-control _se_video_size_x" placeholder="100%"' + (onlyPercentage ? ' type="number" min="1"' : 'type="text"') + (onlyPercentage ? ' max="100"' : '') + '/>' +
162
+ '<label class="se-dialog-size-x"' + onlyWidthDisplay + '>' + (onlyPercentage ? '%' : 'x') + '</label>' +
163
+ '<input class="se-input-control _se_video_size_y" placeholder="' + (option.videoRatio * 100) + '%"' + (onlyPercentage ? ' type="number" min="1"' : 'type="text"') + (onlyPercentage ? ' max="100"' : '') + heightDisplay + '/>' +
164
+ '<select class="se-input-select se-video-ratio" title="' + lang.dialogBox.ratio + '" aria-label="' + lang.dialogBox.ratio + '"' + ratioDisplay + '>';
165
+ if (!heightDisplay) html += '<option value=""> - </option>';
166
+ for (let i = 0, len = ratioList.length; i < len; i++) {
167
+ html += '<option value="' + ratioList[i].value + '"' + (ratio.toString() === ratioList[i].value.toString() ? ' selected' : '') + '>' + ratioList[i].name + '</option>';
168
+ }
169
+ html += '</select>' +
170
+ '<button type="button" title="' + lang.dialogBox.revertButton + '" aria-label="' + lang.dialogBox.revertButton + '" class="se-btn se-dialog-btn-revert" style="float: right;">' + core.icons.revert + '</button>' +
171
+ '</div>' +
172
+ '<div class="se-dialog-form se-dialog-form-footer"' + onlyPercentDisplay + onlyWidthDisplay + '>' +
173
+ '<label><input type="checkbox" class="se-dialog-btn-check _se_video_check_proportion" checked/>&nbsp;' + lang.dialogBox.proportion + '</label>' +
174
+ '</div>';
175
+ }
176
+
177
+ html += '' +
178
+ '</div>' +
179
+ '<div class="se-dialog-footer">' +
180
+ '<div' + (option.videoAlignShow ? '' : ' style="display: none"') + '>' +
181
+ '<label><input type="radio" name="suneditor_video_radio" class="se-dialog-btn-radio" value="none" checked>' + lang.dialogBox.basic + '</label>' +
182
+ '<label><input type="radio" name="suneditor_video_radio" class="se-dialog-btn-radio" value="left">' + lang.dialogBox.left + '</label>' +
183
+ '<label><input type="radio" name="suneditor_video_radio" class="se-dialog-btn-radio" value="center">' + lang.dialogBox.center + '</label>' +
184
+ '<label><input type="radio" name="suneditor_video_radio" class="se-dialog-btn-radio" value="right">' + lang.dialogBox.right + '</label>' +
185
+ '</div>' +
186
+ '<button type="submit" class="se-btn-primary" title="' + lang.dialogBox.submitButton + '" aria-label="' + lang.dialogBox.submitButton + '"><span>' + lang.dialogBox.submitButton + '</span></button>' +
187
+ '</div>' +
188
+ '</form>';
189
+
190
+ dialog.innerHTML = html;
191
+
192
+ return dialog;
193
+ },
194
+
195
+ _fileInputChange: function () {
196
+ if (!this.videoInputFile.value) {
197
+ this.videoUrlFile.removeAttribute('disabled');
198
+ this.preview.style.textDecoration = '';
199
+ } else {
200
+ this.videoUrlFile.setAttribute('disabled', true);
201
+ this.preview.style.textDecoration = 'line-through';
202
+ }
203
+ },
204
+
205
+ _removeSelectedFiles: function (urlInput, preview) {
206
+ this.value = '';
207
+ if (urlInput) {
208
+ urlInput.removeAttribute('disabled');
209
+ preview.style.textDecoration = '';
210
+ }
211
+ },
212
+
213
+ _onLinkPreview: function (context, protocol, e) {
214
+ const value = e.target.value.trim();
215
+ if (/^<iframe.*\/iframe>$/.test(value)) {
216
+ context._linkValue = value;
217
+ this.textContent = '<IFrame :src=".."></IFrame>';
218
+ } else {
219
+ context._linkValue = this.textContent = !value ? '' : (protocol && value.indexOf('://') === -1 && value.indexOf('#') !== 0) ? protocol + value : value.indexOf('://') === -1 ? '/' + value : value;
220
+ }
221
+ },
222
+
223
+ _setTagAttrs: function (element) {
224
+ element.setAttribute('controls', true);
225
+
226
+ const attrs = this.options.videoTagAttrs;
227
+ if (!attrs) return;
228
+
229
+ for (let key in attrs) {
230
+ if (!this.util.hasOwn(attrs, key)) continue;
231
+ element.setAttribute(key, attrs[key]);
232
+ }
233
+ },
234
+
235
+ createVideoTag: function () {
236
+ const videoTag = this.util.createElement('VIDEO');
237
+ this.plugins.video._setTagAttrs.call(this, videoTag);
238
+ return videoTag;
239
+ },
240
+
241
+ _setIframeAttrs: function (element) {
242
+ element.frameBorder = '0';
243
+ element.allowFullscreen = true;
244
+
245
+ const attrs = this.options.videoIframeAttrs;
246
+ if (!attrs) return;
247
+
248
+ for (let key in attrs) {
249
+ if (!this.util.hasOwn(attrs, key)) continue;
250
+ element.setAttribute(key, attrs[key]);
251
+ }
252
+ },
253
+
254
+ createIframeTag: function () {
255
+ const iframeTag = this.util.createElement('IFRAME');
256
+ this.plugins.video._setIframeAttrs.call(this, iframeTag);
257
+ return iframeTag;
258
+ },
259
+
260
+ /**
261
+ * @Override @Required fileManager
262
+ */
263
+ fileTags: ['iframe', 'video'],
264
+
265
+ /**
266
+ * @Override core, resizing, fileManager
267
+ * @description It is called from core.selectComponent.
268
+ * @param {Element} element Target element
269
+ */
270
+ select: function (element) {
271
+ this.plugins.video.onModifyMode.call(this, element, this.plugins.resizing.call_controller_resize.call(this, element, 'video'));
272
+ },
273
+
274
+ /**
275
+ * @Override fileManager, resizing
276
+ */
277
+ destroy: function (element) {
278
+ const frame = element || this.context.video._element;
279
+ const container = this.context.video._container;
280
+ const dataIndex = frame.getAttribute('data-index') * 1;
281
+
282
+ if (typeof this.functions.onVideoDeleteBefore === 'function' && (this.functions.onVideoDeleteBefore(frame, container, dataIndex, this) === false)) return;
283
+
284
+ let focusEl = (container.previousElementSibling || container.nextElementSibling);
285
+ const emptyDiv = container.parentNode;
286
+ this.util.removeItem(container);
287
+ this.plugins.video.init.call(this);
288
+ this.controllersOff();
289
+
290
+ if (emptyDiv !== this.context.element.wysiwyg) this.util.removeItemAllParents(emptyDiv, function (current) { return current.childNodes.length === 0; }, null);
291
+
292
+ // focus
293
+ this.focusEdge(focusEl);
294
+
295
+ // event
296
+ this.plugins.fileManager.deleteInfo.call(this, 'video', dataIndex, this.functions.onVideoUpload);
297
+
298
+ // history stack
299
+ this.history.push(false);
300
+ },
301
+
302
+ /**
303
+ * @Required @Override dialog
304
+ */
305
+ on: function (update) {
306
+ const contextVideo = this.context.video;
307
+
308
+ if (!update) {
309
+ contextVideo.inputX.value = contextVideo._origin_w = this.options.videoWidth === contextVideo._defaultSizeX ? '' : this.options.videoWidth;
310
+ contextVideo.inputY.value = contextVideo._origin_h = this.options.videoHeight === contextVideo._defaultSizeY ? '' : this.options.videoHeight;
311
+ contextVideo.proportion.disabled = true;
312
+ if (contextVideo.videoInputFile && this.options.videoMultipleFile) contextVideo.videoInputFile.setAttribute('multiple', 'multiple');
313
+ } else {
314
+ if (contextVideo.videoInputFile && this.options.videoMultipleFile) contextVideo.videoInputFile.removeAttribute('multiple');
315
+ }
316
+
317
+ if (contextVideo._resizing) {
318
+ this.plugins.video.setVideoRatioSelect.call(this, contextVideo._origin_h || contextVideo._defaultRatio);
319
+ }
320
+ },
321
+
322
+ /**
323
+ * @Required @Override dialog
324
+ */
325
+ open: function () {
326
+ this.plugins.dialog.open.call(this, 'video', 'video' === this.currentControllerName);
327
+ },
328
+
329
+ setVideoRatio: function (e) {
330
+ const contextVideo = this.context.video;
331
+ const value = e.target.options[e.target.selectedIndex].value;
332
+
333
+ contextVideo._defaultSizeY = contextVideo._videoRatio = !value ? contextVideo._defaultSizeY : (value * 100) + '%';
334
+ contextVideo.inputY.placeholder = !value ? '' : (value * 100) + '%';
335
+ contextVideo.inputY.value = '';
336
+ },
337
+
338
+ /**
339
+ * @Override resizing
340
+ * @param {String} xy 'x': width, 'y': height
341
+ * @param {KeyboardEvent} e Event object
342
+ */
343
+ setInputSize: function (xy, e) {
344
+ if (e && e.keyCode === 32) {
345
+ e.preventDefault();
346
+ return;
347
+ }
348
+
349
+ const contextVideo = this.context.video;
350
+ this.plugins.resizing._module_setInputSize.call(this, contextVideo, xy);
351
+
352
+ if (xy === 'y') {
353
+ this.plugins.video.setVideoRatioSelect.call(this, e.target.value || contextVideo._defaultRatio);
354
+ }
355
+ },
356
+
357
+ /**
358
+ * @Override resizing
359
+ */
360
+ setRatio: function () {
361
+ this.plugins.resizing._module_setRatio.call(this, this.context.video);
362
+ },
363
+
364
+ submit: function (e) {
365
+ const contextVideo = this.context.video;
366
+ const videoPlugin = this.plugins.video;
367
+
368
+ e.preventDefault();
369
+ e.stopPropagation();
370
+
371
+ contextVideo._align = contextVideo.modal.querySelector('input[name="suneditor_video_radio"]:checked').value;
372
+
373
+ try {
374
+ if (contextVideo.videoInputFile && contextVideo.videoInputFile.files.length > 0) {
375
+ this.showLoading();
376
+ videoPlugin.submitAction.call(this, this.context.video.videoInputFile.files);
377
+ } else if (contextVideo.videoUrlFile && contextVideo._linkValue.length > 0) {
378
+ this.showLoading();
379
+ videoPlugin.setup_url.call(this, contextVideo._linkValue);
380
+ }
381
+ } catch (error) {
382
+ this.closeLoading();
383
+ throw Error('[SUNEDITOR.video.submit.fail] cause : "' + error.message + '"');
384
+ } finally {
385
+ this.plugins.dialog.close.call(this);
386
+ }
387
+
388
+ return false;
389
+ },
390
+
391
+ submitAction: function (fileList) {
392
+ if (fileList.length === 0) return;
393
+
394
+ let fileSize = 0;
395
+ let files = [];
396
+ for (let i = 0, len = fileList.length; i < len; i++) {
397
+ if (/video/i.test(fileList[i].type)) {
398
+ files.push(fileList[i]);
399
+ fileSize += fileList[i].size;
400
+ }
401
+ }
402
+
403
+ const limitSize = this.options.videoUploadSizeLimit;
404
+ if (limitSize > 0) {
405
+ let infoSize = 0;
406
+ const videosInfo = this.context.video._infoList;
407
+ for (let i = 0, len = videosInfo.length; i < len; i++) {
408
+ infoSize += videosInfo[i].size * 1;
409
+ }
410
+
411
+ if ((fileSize + infoSize) > limitSize) {
412
+ this.closeLoading();
413
+ const err = '[SUNEDITOR.videoUpload.fail] Size of uploadable total videos: ' + (limitSize/1000) + 'KB';
414
+ if (typeof this.functions.onVideoUploadError !== 'function' || this.functions.onVideoUploadError(err, { 'limitSize': limitSize, 'currentSize': infoSize, 'uploadSize': fileSize }, this)) {
415
+ this.functions.noticeOpen(err);
416
+ }
417
+ return;
418
+ }
419
+ }
420
+
421
+ const contextVideo = this.context.video;
422
+ contextVideo._uploadFileLength = files.length;
423
+
424
+ const info = {
425
+ inputWidth: contextVideo.inputX.value,
426
+ inputHeight: contextVideo.inputY.value,
427
+ align: contextVideo._align,
428
+ isUpdate: this.context.dialog.updateModal,
429
+ element: contextVideo._element
430
+ };
431
+
432
+ if (typeof this.functions.onVideoUploadBefore === 'function') {
433
+ const result = this.functions.onVideoUploadBefore(files, info, this, function (data) {
434
+ if (data && this._w.Array.isArray(data.result)) {
435
+ this.plugins.video.register.call(this, info, data);
436
+ } else {
437
+ this.plugins.video.upload.call(this, info, data);
438
+ }
439
+ }.bind(this));
440
+
441
+ if (typeof result === 'undefined') return;
442
+ if (!result) {
443
+ this.closeLoading();
444
+ return;
445
+ }
446
+ if (typeof result === 'object' && result.length > 0) files = result;
447
+ }
448
+
449
+ this.plugins.video.upload.call(this, info, files);
450
+ },
451
+
452
+ error: function (message, response) {
453
+ this.closeLoading();
454
+ if (typeof this.functions.onVideoUploadError !== 'function' || this.functions.onVideoUploadError(message, response, this)) {
455
+ this.functions.noticeOpen(message);
456
+ throw Error('[SUNEDITOR.plugin.video.error] response: ' + message);
457
+ }
458
+ },
459
+
460
+ upload: function (info, files) {
461
+ if (!files) {
462
+ this.closeLoading();
463
+ return;
464
+ }
465
+ if (typeof files === 'string') {
466
+ this.plugins.video.error.call(this, files, null);
467
+ return;
468
+ }
469
+
470
+ const videoUploadUrl = this.options.videoUploadUrl;
471
+ const filesLen = this.context.dialog.updateModal ? 1 : files.length;
472
+
473
+ // server upload
474
+ if (typeof videoUploadUrl === 'string' && videoUploadUrl.length > 0) {
475
+ const formData = new FormData();
476
+ for (let i = 0; i < filesLen; i++) {
477
+ formData.append('file-' + i, files[i]);
478
+ }
479
+ this.plugins.fileManager.upload.call(this, videoUploadUrl, this.options.videoUploadHeader, formData, this.plugins.video.callBack_videoUpload.bind(this, info), this.functions.onVideoUploadError);
480
+ } else {
481
+ throw Error('[SUNEDITOR.videoUpload.fail] cause : There is no "videoUploadUrl" option.');
482
+ }
483
+ },
484
+
485
+ callBack_videoUpload: function (info, xmlHttp) {
486
+ if (typeof this.functions.videoUploadHandler === 'function') {
487
+ this.functions.videoUploadHandler(xmlHttp, info, this);
488
+ } else {
489
+ const response = JSON.parse(xmlHttp.responseText);
490
+ if (response.errorMessage) {
491
+ this.plugins.video.error.call(this, response.errorMessage, response);
492
+ } else {
493
+ this.plugins.video.register.call(this, info, response);
494
+ }
495
+ }
496
+ },
497
+
498
+ register: function (info, response) {
499
+ const fileList = response.result;
500
+ const videoTag = this.plugins.video.createVideoTag.call(this);
501
+
502
+ for (let i = 0, len = fileList.length, file; i < len; i++) {
503
+ file = { name: fileList[i].name, size: fileList[i].size };
504
+ this.plugins.video.create_video.call(this, (info.isUpdate ? info.element : videoTag.cloneNode(false)), fileList[i].url, info.inputWidth, info.inputHeight, info.align, file, info.isUpdate);
505
+ }
506
+
507
+ this.closeLoading();
508
+ },
509
+
510
+ setup_url: function (url) {
511
+ try {
512
+ const contextVideo = this.context.video;
513
+ if (!url) url = contextVideo._linkValue;
514
+ if (!url) return false;
515
+
516
+ /** iframe source */
517
+ if (/^<iframe.*\/iframe>$/.test(url)) {
518
+ const oIframe = (new this._w.DOMParser()).parseFromString(url, 'text/html').querySelector('iframe');
519
+ url = oIframe.src;
520
+ if (url.length === 0) return false;
521
+ }
522
+
523
+ /** youtube */
524
+ if (/youtu\.?be/.test(url)) {
525
+ if (!/^http/.test(url)) url = 'https://' + url;
526
+ url = url.replace('watch?v=', '');
527
+ if (!/^\/\/.+\/embed\//.test(url)) {
528
+ url = url.replace(url.match(/\/\/.+\//)[0], '//www.youtube.com/embed/').replace('&', '?&');
529
+ }
530
+
531
+ if (contextVideo._youtubeQuery.length > 0) {
532
+ if (/\?/.test(url)) {
533
+ const splitUrl = url.split('?');
534
+ url = splitUrl[0] + '?' + contextVideo._youtubeQuery + '&' + splitUrl[1];
535
+ } else {
536
+ url += '?' + contextVideo._youtubeQuery;
537
+ }
538
+ }
539
+ } else if (/vimeo\.com/.test(url)) {
540
+ if (url.endsWith('/')) {
541
+ url = url.slice(0, -1);
542
+ }
543
+ url = 'https://player.vimeo.com/video/' + url.slice(url.lastIndexOf('/') + 1);
544
+
545
+ if (contextVideo._vimeoQuery.length > 0) {
546
+ if (/\?/.test(url)) {
547
+ const splitUrl = url.split('?');
548
+ url = splitUrl[0] + '?' + contextVideo._vimeoQuery + '&' + splitUrl[1];
549
+ } else {
550
+ url += '?' + contextVideo._vimeoQuery;
551
+ }
552
+ }
553
+ }
554
+
555
+ this.plugins.video.create_video.call(this, this.plugins.video[(!/embed|iframe|player|\/e\/|\.php|\.html?/.test(url) && !/vimeo\.com/.test(url) ? "createVideoTag" : "createIframeTag")].call(this), url, contextVideo.inputX.value, contextVideo.inputY.value, contextVideo._align, null, this.context.dialog.updateModal);
556
+ } catch (error) {
557
+ throw Error('[SUNEDITOR.video.upload.fail] cause : "' + error.message + '"');
558
+ } finally {
559
+ this.closeLoading();
560
+ }
561
+ },
562
+
563
+ create_video: function (oFrame, src, width, height, align, file, isUpdate) {
564
+ this.context.resizing._resize_plugin = 'video';
565
+ const contextVideo = this.context.video;
566
+
567
+ let cover = null;
568
+ let container = null;
569
+ let init = false;
570
+
571
+ /** update */
572
+ if (isUpdate) {
573
+ oFrame = contextVideo._element;
574
+ if (oFrame.src !== src) {
575
+ init = true;
576
+ const isYoutube = /youtu\.?be/.test(src);
577
+ const isVimeo = /vimeo\.com/.test(src);
578
+ if ((isYoutube || isVimeo) && !/^iframe$/i.test(oFrame.nodeName)) {
579
+ const newTag = this.plugins.video.createIframeTag.call(this);
580
+ newTag.src = src;
581
+ oFrame.parentNode.replaceChild(newTag, oFrame);
582
+ contextVideo._element = oFrame = newTag;
583
+ } else if (!isYoutube && !isVimeo && !/^video$/i.test(oFrame.nodeName)) {
584
+ const newTag = this.plugins.video.createVideoTag.call(this);
585
+ newTag.src = src;
586
+ oFrame.parentNode.replaceChild(newTag, oFrame);
587
+ contextVideo._element = oFrame = newTag;
588
+ } else {
589
+ oFrame.src = src;
590
+ }
591
+ }
592
+ container = contextVideo._container;
593
+ cover = this.util.getParentElement(oFrame, 'FIGURE');
594
+ }
595
+ /** create */
596
+ else {
597
+ init = true;
598
+ oFrame.src = src;
599
+ contextVideo._element = oFrame;
600
+ cover = this.plugins.component.set_cover.call(this, oFrame);
601
+ container = this.plugins.component.set_container.call(this, cover, 'se-video-container');
602
+ }
603
+
604
+ /** rendering */
605
+ contextVideo._cover = cover;
606
+ contextVideo._container = container;
607
+
608
+ const inputUpdate = (this.plugins.resizing._module_getSizeX.call(this, contextVideo) !== (width || contextVideo._defaultSizeX)) || (this.plugins.resizing._module_getSizeY.call(this, contextVideo) !== (height || contextVideo._videoRatio));
609
+ const changeSize = !isUpdate || inputUpdate;
610
+
611
+ if (contextVideo._resizing) {
612
+ this.context.video._proportionChecked = contextVideo.proportion.checked;
613
+ oFrame.setAttribute('data-proportion', contextVideo._proportionChecked);
614
+ }
615
+
616
+ // size
617
+ let isPercent = false;
618
+ if (changeSize) {
619
+ isPercent = this.plugins.video.applySize.call(this);
620
+ }
621
+
622
+ // align
623
+ if (!(isPercent && align === 'center')) {
624
+ this.plugins.video.setAlign.call(this, null, oFrame, cover, container);
625
+ }
626
+
627
+ let changed = true;
628
+ if (!isUpdate) {
629
+ changed = this.insertComponent(container, false, true, !this.options.mediaAutoSelect);
630
+ if (!this.options.mediaAutoSelect) {
631
+ const line = this.appendFormatTag(container, null);
632
+ if (line) this.setRange(line, 0, line, 0);
633
+ }
634
+ } else if (contextVideo._resizing && this.context.resizing._rotateVertical && changeSize) {
635
+ this.plugins.resizing.setTransformSize.call(this, oFrame, null, null);
636
+ }
637
+
638
+ if (changed) {
639
+ if (init) {
640
+ this.plugins.fileManager.setInfo.call(this, 'video', oFrame, this.functions.onVideoUpload, file, true);
641
+ }
642
+ if (isUpdate) {
643
+ this.selectComponent(oFrame, 'video');
644
+ // history stack
645
+ this.history.push(false);
646
+ }
647
+ }
648
+
649
+ this.context.resizing._resize_plugin = '';
650
+ },
651
+
652
+ _update_videoCover: function (oFrame) {
653
+ if (!oFrame) return;
654
+
655
+ const contextVideo = this.context.video;
656
+
657
+ if (/^video$/i.test(oFrame.nodeName)) this.plugins.video._setTagAttrs.call(this, oFrame);
658
+ else this.plugins.video._setIframeAttrs.call(this, oFrame);
659
+
660
+ const frameParent = oFrame.parentNode;
661
+ let existElement = (this.util.isRangeFormatElement(frameParent) || this.util.isWysiwygDiv(frameParent)) ? oFrame : frameParent || oFrame;
662
+
663
+ const prevFrame = oFrame;
664
+ contextVideo._element = oFrame = oFrame.cloneNode(true);
665
+ const cover = contextVideo._cover = this.plugins.component.set_cover.call(this, oFrame);
666
+ const container = contextVideo._container = this.plugins.component.set_container.call(this, cover, 'se-video-container');
667
+
668
+ try {
669
+ const figcaption = existElement.querySelector('figcaption');
670
+ let caption = null;
671
+ if (!!figcaption) {
672
+ caption = this.util.createElement('DIV');
673
+ caption.innerHTML = figcaption.innerHTML;
674
+ this.util.removeItem(figcaption);
675
+ }
676
+
677
+ // size
678
+ const size = (oFrame.getAttribute('data-size') || oFrame.getAttribute('data-origin') || '').split(',');
679
+ this.plugins.video.applySize.call(this, (size[0] || prevFrame.style.width || prevFrame.width || ''), (size[1] || prevFrame.style.height || prevFrame.height || ''));
680
+
681
+ // align
682
+ const format = this.util.getFormatElement(prevFrame);
683
+ if (format) contextVideo._align = format.style.textAlign || format.style.float;
684
+ this.plugins.video.setAlign.call(this, null, oFrame, cover, container);
685
+
686
+ if (this.util.getParentElement(prevFrame, this.util.isNotCheckingNode)) {
687
+ prevFrame.parentNode.replaceChild(container, prevFrame);
688
+ } else if (this.util.isListCell(existElement)) {
689
+ const refer = this.util.getParentElement(prevFrame, function (current) { return current.parentNode === existElement; });
690
+ existElement.insertBefore(container, refer);
691
+ this.util.removeItem(prevFrame);
692
+ this.util.removeEmptyNode(refer, null, true);
693
+ } else if (this.util.isFormatElement(existElement)) {
694
+ const refer = this.util.getParentElement(prevFrame, function (current) { return current.parentNode === existElement; });
695
+ existElement = this.util.splitElement(existElement, refer);
696
+ existElement.parentNode.insertBefore(container, existElement);
697
+ this.util.removeItem(prevFrame);
698
+ this.util.removeEmptyNode(existElement, null, true);
699
+ if (existElement.children.length === 0) existElement.innerHTML = this.util.htmlRemoveWhiteSpace(existElement.innerHTML);
700
+ } else {
701
+ existElement.parentNode.replaceChild(container, existElement);
702
+ }
703
+
704
+ if (!!caption) existElement.parentNode.insertBefore(caption, container.nextElementSibling);
705
+ } catch (error) {
706
+ console.warn('[SUNEDITOR.video.error] Maybe the video tag is nested.', error);
707
+ }
708
+
709
+ this.plugins.fileManager.setInfo.call(this, 'video', oFrame, this.functions.onVideoUpload, null, true);
710
+ this.plugins.video.init.call(this);
711
+ },
712
+
713
+ /**
714
+ * @Required @Override fileManager, resizing
715
+ */
716
+ onModifyMode: function (element, size) {
717
+ const contextVideo = this.context.video;
718
+ contextVideo._element = element;
719
+ contextVideo._cover = this.util.getParentElement(element, 'FIGURE');
720
+ contextVideo._container = this.util.getParentElement(element, this.util.isMediaComponent);
721
+ contextVideo._align = element.style.float || element.getAttribute('data-align') || 'none';
722
+ element.style.float = '';
723
+
724
+ if (size) {
725
+ contextVideo._element_w = size.w;
726
+ contextVideo._element_h = size.h;
727
+ contextVideo._element_t = size.t;
728
+ contextVideo._element_l = size.l;
729
+ }
730
+
731
+ let origin = contextVideo._element.getAttribute('data-size') || contextVideo._element.getAttribute('data-origin');
732
+ let w, h;
733
+ if (origin) {
734
+ origin = origin.split(',');
735
+ w = origin[0];
736
+ h = origin[1];
737
+ } else if (size) {
738
+ w = size.w;
739
+ h = size.h;
740
+ }
741
+
742
+ contextVideo._origin_w = w || element.style.width || element.width || '';
743
+ contextVideo._origin_h = h || element.style.height || element.height || '';
744
+ },
745
+
746
+ /**
747
+ * @Required @Override fileManager, resizing
748
+ */
749
+ openModify: function (notOpen) {
750
+ const contextVideo = this.context.video;
751
+
752
+ if (contextVideo.videoUrlFile) contextVideo._linkValue = contextVideo.preview.textContent = contextVideo.videoUrlFile.value = (contextVideo._element.src || (contextVideo._element.querySelector('source') || '').src || '');
753
+ (contextVideo.modal.querySelector('input[name="suneditor_video_radio"][value="' + contextVideo._align + '"]') || contextVideo.modal.querySelector('input[name="suneditor_video_radio"][value="none"]')).checked = true;
754
+
755
+ if (contextVideo._resizing) {
756
+ this.plugins.resizing._module_setModifyInputSize.call(this, contextVideo, this.plugins.video);
757
+
758
+ const y = contextVideo._videoRatio = this.plugins.resizing._module_getSizeY.call(this, contextVideo);
759
+ const ratioSelected = this.plugins.video.setVideoRatioSelect.call(this, y);
760
+ if (!ratioSelected) contextVideo.inputY.value = contextVideo._onlyPercentage ? this.util.getNumber(y, 2) : y;
761
+ }
762
+
763
+ if (!notOpen) this.plugins.dialog.open.call(this, 'video', true);
764
+ },
765
+
766
+ setVideoRatioSelect: function (value) {
767
+ let ratioSelected = false;
768
+ const contextVideo = this.context.video;
769
+ const ratioOptions = contextVideo.videoRatioOption.options;
770
+
771
+ if (/%$/.test(value) || contextVideo._onlyPercentage) value = (this.util.getNumber(value, 2) / 100) + '';
772
+ else if (!this.util.isNumber(value) || (value * 1) >= 1) value = '';
773
+
774
+ contextVideo.inputY.placeholder = '';
775
+ for (let i = 0, len = ratioOptions.length; i < len; i++) {
776
+ if (ratioOptions[i].value === value) {
777
+ ratioSelected = ratioOptions[i].selected = true;
778
+ contextVideo.inputY.placeholder = !value ? '' : (value * 100) + '%';
779
+ }
780
+ else ratioOptions[i].selected = false;
781
+ }
782
+
783
+ return ratioSelected;
784
+ },
785
+
786
+ /**
787
+ * @Override fileManager
788
+ */
789
+ checkFileInfo: function () {
790
+ this.plugins.fileManager.checkInfo.call(this, 'video', ['iframe', 'video'], this.functions.onVideoUpload, this.plugins.video._update_videoCover.bind(this), true);
791
+ },
792
+
793
+ /**
794
+ * @Override fileManager
795
+ */
796
+ resetFileInfo: function () {
797
+ this.plugins.fileManager.resetInfo.call(this, 'video', this.functions.onVideoUpload);
798
+ },
799
+
800
+ /**
801
+ * @Override fileManager
802
+ */
803
+ applySize: function (w, h) {
804
+ const contextVideo = this.context.video;
805
+
806
+ if (!w) w = contextVideo.inputX.value || this.options.videoWidth;
807
+ if (!h) h = contextVideo.inputY.value || this.options.videoHeight;
808
+
809
+ if (contextVideo._onlyPercentage || /%$/.test(w) || !w) {
810
+ this.plugins.video.setPercentSize.call(this, (w || '100%'), (h || (/%$/.test(contextVideo._videoRatio) ? contextVideo._videoRatio : contextVideo._defaultRatio)));
811
+ return true;
812
+ } else if ((!w || w === 'auto') && (!h || h === 'auto')) {
813
+ this.plugins.video.setAutoSize.call(this);
814
+ } else {
815
+ this.plugins.video.setSize.call(this, w, (h || contextVideo._videoRatio || contextVideo._defaultRatio), false);
816
+ }
817
+
818
+ return false;
819
+ },
820
+
821
+ /**
822
+ * @Override resizing
823
+ */
824
+ sizeRevert: function () {
825
+ this.plugins.resizing._module_sizeRevert.call(this, this.context.video);
826
+ },
827
+
828
+ /**
829
+ * @Override resizing
830
+ */
831
+ setSize: function (w, h, notResetPercentage, direction) {
832
+ const contextVideo = this.context.video;
833
+ const onlyW = /^(rw|lw)$/.test(direction);
834
+ const onlyH = /^(th|bh)$/.test(direction);
835
+
836
+ if (!onlyH) w = this.util.getNumber(w, 0);
837
+ if (!onlyW) h = this.util.isNumber(h) ? h + contextVideo.sizeUnit : !h ? '' : h;
838
+ w = w ? w + contextVideo.sizeUnit : '';
839
+
840
+ if (!onlyH) contextVideo._element.style.width = w;
841
+ if (!onlyW) contextVideo._cover.style.paddingBottom = contextVideo._cover.style.height = h;
842
+
843
+ if (!onlyH && !/%$/.test(w)) {
844
+ contextVideo._cover.style.width = w;
845
+ contextVideo._container.style.width = '';
846
+ }
847
+
848
+ if (!onlyW && !/%$/.test(h)) {
849
+ contextVideo._element.style.height = h;
850
+ } else {
851
+ contextVideo._element.style.height = '';
852
+ }
853
+
854
+ if (!notResetPercentage) contextVideo._element.removeAttribute('data-percentage');
855
+
856
+ // save current size
857
+ this.plugins.resizing._module_saveCurrentSize.call(this, contextVideo);
858
+ },
859
+
860
+ /**
861
+ * @Override resizing
862
+ */
863
+ setAutoSize: function () {
864
+ this.plugins.video.setPercentSize.call(this, 100, this.context.video._defaultRatio);
865
+ },
866
+
867
+ /**
868
+ * @Override resizing
869
+ */
870
+ setOriginSize: function (dataSize) {
871
+ const contextVideo = this.context.video;
872
+ contextVideo._element.removeAttribute('data-percentage');
873
+
874
+ this.plugins.resizing.resetTransform.call(this, contextVideo._element);
875
+ this.plugins.video.cancelPercentAttr.call(this);
876
+
877
+ const originSize = ((dataSize ? contextVideo._element.getAttribute('data-size') : '') || contextVideo._element.getAttribute('data-origin') || '').split(',');
878
+
879
+ if (originSize) {
880
+ const w = originSize[0];
881
+ const h = originSize[1];
882
+
883
+ if (contextVideo._onlyPercentage || (/%$/.test(w) && (/%$/.test(h) || !/\d/.test(h)))) {
884
+ this.plugins.video.setPercentSize.call(this, w, h);
885
+ } else {
886
+ this.plugins.video.setSize.call(this, w, h);
887
+ }
888
+
889
+ // save current size
890
+ this.plugins.resizing._module_saveCurrentSize.call(this, contextVideo);
891
+ }
892
+ },
893
+
894
+ /**
895
+ * @Override resizing
896
+ */
897
+ setPercentSize: function (w, h) {
898
+ const contextVideo = this.context.video;
899
+ h = !!h && !/%$/.test(h) && !this.util.getNumber(h, 0) ? this.util.isNumber(h) ? h + '%' : h : this.util.isNumber(h) ? h + contextVideo.sizeUnit : (h || contextVideo._defaultRatio);
900
+
901
+ contextVideo._container.style.width = this.util.isNumber(w) ? w + '%' : w;
902
+ contextVideo._container.style.height = '';
903
+ contextVideo._cover.style.width = '100%';
904
+ contextVideo._cover.style.height = h;
905
+ contextVideo._cover.style.paddingBottom = h;
906
+ contextVideo._element.style.width = '100%';
907
+ contextVideo._element.style.height = '100%';
908
+ contextVideo._element.style.maxWidth = '';
909
+
910
+ if (contextVideo._align === 'center') this.plugins.video.setAlign.call(this, null, null, null, null);
911
+ contextVideo._element.setAttribute('data-percentage', w + ',' + h);
912
+
913
+ // save current size
914
+ this.plugins.resizing._module_saveCurrentSize.call(this, contextVideo);
915
+ },
916
+
917
+ /**
918
+ * @Override resizing
919
+ */
920
+ cancelPercentAttr: function () {
921
+ const contextVideo = this.context.video;
922
+
923
+ contextVideo._cover.style.width = '';
924
+ contextVideo._cover.style.height = '';
925
+ contextVideo._cover.style.paddingBottom = '';
926
+ contextVideo._container.style.width = '';
927
+ contextVideo._container.style.height = '';
928
+
929
+ this.util.removeClass(contextVideo._container, this.context.video._floatClassRegExp);
930
+ this.util.addClass(contextVideo._container, '__se__float-' + contextVideo._align);
931
+
932
+ if (contextVideo._align === 'center') this.plugins.video.setAlign.call(this, null, null, null, null);
933
+ },
934
+
935
+ /**
936
+ * @Override resizing
937
+ */
938
+ setAlign: function (align, element, cover, container) {
939
+ const contextVideo = this.context.video;
940
+
941
+ if (!align) align = contextVideo._align;
942
+ if (!element) element = contextVideo._element;
943
+ if (!cover) cover = contextVideo._cover;
944
+ if (!container) container = contextVideo._container;
945
+
946
+ if (/%$/.test(element.style.width) && align === 'center') {
947
+ container.style.minWidth = '100%';
948
+ cover.style.width = container.style.width;
949
+ cover.style.height = cover.style.height;
950
+ cover.style.paddingBottom = !/%$/.test(cover.style.height) ? cover.style.height : this.util.getNumber((this.util.getNumber(cover.style.height, 2) / 100) * this.util.getNumber(cover.style.width, 2), 2) + '%';
951
+ } else {
952
+ container.style.minWidth = '';
953
+ cover.style.width = this.context.resizing._rotateVertical ? (element.style.height || element.offsetHeight) : (element.style.width || '100%');
954
+ cover.style.paddingBottom = cover.style.height;
955
+ }
956
+
957
+ if (!this.util.hasClass(container, '__se__float-' + align)) {
958
+ this.util.removeClass(container, contextVideo._floatClassRegExp);
959
+ this.util.addClass(container, '__se__float-' + align);
960
+ }
961
+
962
+ element.setAttribute('data-align', align);
963
+ },
964
+
965
+ /**
966
+ * @Override dialog
967
+ */
968
+ init: function () {
969
+ const contextVideo = this.context.video;
970
+ if (contextVideo.videoInputFile) contextVideo.videoInputFile.value = '';
971
+ if (contextVideo.videoUrlFile) contextVideo._linkValue = contextVideo.preview.textContent = contextVideo.videoUrlFile.value = '';
972
+ if (contextVideo.videoInputFile && contextVideo.videoUrlFile) {
973
+ contextVideo.videoUrlFile.removeAttribute('disabled');
974
+ contextVideo.preview.style.textDecoration = '';
975
+ }
976
+
977
+ contextVideo._origin_w = this.options.videoWidth;
978
+ contextVideo._origin_h = this.options.videoHeight;
979
+ contextVideo.modal.querySelector('input[name="suneditor_video_radio"][value="none"]').checked = true;
980
+
981
+ if (contextVideo._resizing) {
982
+ contextVideo.inputX.value = this.options.videoWidth === contextVideo._defaultSizeX ? '' : this.options.videoWidth;
983
+ contextVideo.inputY.value = this.options.videoHeight === contextVideo._defaultSizeY ? '' : this.options.videoHeight;
984
+ contextVideo.proportion.checked = true;
985
+ contextVideo.proportion.disabled = true;
986
+ this.plugins.video.setVideoRatioSelect.call(this, contextVideo._defaultRatio);
987
+ }
988
+ }
989
+ };