suneditor 2.46.1 → 3.0.0-alpha.1

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 (290) hide show
  1. package/.eslintignore +7 -0
  2. package/.eslintrc.json +64 -0
  3. package/CONTRIBUTING.md +36 -0
  4. package/LICENSE.txt +1 -1
  5. package/README.md +174 -805
  6. package/dist/suneditor.min.css +1 -0
  7. package/dist/suneditor.min.js +1 -2
  8. package/package.json +96 -70
  9. package/src/assets/icons/_default.js +194 -0
  10. package/src/assets/suneditor-content.css +646 -0
  11. package/src/assets/suneditor.css +3378 -0
  12. package/src/core/base/eventHandlers/handler_toolbar.js +114 -0
  13. package/src/core/base/eventHandlers/handler_ww_clipboard.js +31 -0
  14. package/src/core/base/eventHandlers/handler_ww_dragDrop.js +69 -0
  15. package/src/core/base/eventHandlers/handler_ww_key_input.js +975 -0
  16. package/src/core/base/eventHandlers/handler_ww_mouse.js +118 -0
  17. package/src/core/base/eventManager.js +1115 -0
  18. package/src/core/base/events.js +320 -0
  19. package/src/core/base/history.js +301 -0
  20. package/src/core/class/char.js +146 -0
  21. package/src/core/class/component.js +627 -0
  22. package/src/core/class/format.js +3255 -0
  23. package/src/core/class/html.js +1621 -0
  24. package/src/core/class/menu.js +260 -0
  25. package/src/core/class/nodeTransform.js +379 -0
  26. package/src/core/class/notice.js +42 -0
  27. package/src/core/class/offset.js +578 -0
  28. package/src/core/class/selection.js +508 -0
  29. package/src/core/class/shortcuts.js +38 -0
  30. package/src/core/class/toolbar.js +440 -0
  31. package/src/core/class/viewer.js +646 -0
  32. package/src/core/editor.js +1593 -0
  33. package/src/core/section/actives.js +107 -0
  34. package/src/core/section/constructor.js +1237 -0
  35. package/src/core/section/context.js +97 -0
  36. package/src/editorInjector/_classes.js +22 -0
  37. package/src/editorInjector/_core.js +28 -0
  38. package/src/editorInjector/index.js +13 -0
  39. package/src/helper/converter.js +313 -0
  40. package/src/helper/domUtils.js +1177 -0
  41. package/src/helper/env.js +250 -0
  42. package/src/helper/index.js +19 -0
  43. package/src/helper/numbers.js +68 -0
  44. package/src/helper/unicode.js +43 -0
  45. package/src/langs/ckb.js +161 -0
  46. package/src/langs/cs.js +161 -0
  47. package/src/langs/da.js +161 -0
  48. package/src/langs/de.js +162 -0
  49. package/src/langs/en.js +199 -0
  50. package/src/langs/es.js +162 -0
  51. package/src/langs/fa.js +159 -0
  52. package/src/langs/fr.js +161 -0
  53. package/src/langs/he.js +162 -0
  54. package/src/{lang → langs}/index.js +0 -2
  55. package/src/langs/it.js +162 -0
  56. package/src/langs/ja.js +162 -0
  57. package/src/langs/ko.js +162 -0
  58. package/src/langs/lv.js +162 -0
  59. package/src/langs/nl.js +162 -0
  60. package/src/langs/pl.js +162 -0
  61. package/src/langs/pt_br.js +162 -0
  62. package/src/langs/ro.js +162 -0
  63. package/src/langs/ru.js +162 -0
  64. package/src/langs/se.js +162 -0
  65. package/src/langs/tr.js +159 -0
  66. package/src/langs/ua.js +162 -0
  67. package/src/langs/ur.js +162 -0
  68. package/src/langs/zh_cn.js +162 -0
  69. package/src/modules/ApiManager.js +168 -0
  70. package/src/modules/ColorPicker.js +302 -0
  71. package/src/modules/Controller.js +315 -0
  72. package/src/modules/Figure.js +1160 -0
  73. package/src/modules/FileBrowser.js +271 -0
  74. package/src/modules/FileManager.js +290 -0
  75. package/src/modules/HueSlider.js +513 -0
  76. package/src/modules/Modal.js +177 -0
  77. package/src/modules/ModalAnchorEditor.js +494 -0
  78. package/src/modules/SelectMenu.js +447 -0
  79. package/src/modules/_DragHandle.js +16 -0
  80. package/src/modules/index.js +14 -0
  81. package/src/plugins/command/blockquote.js +47 -47
  82. package/src/plugins/command/exportPdf.js +168 -0
  83. package/src/plugins/command/fileUpload.js +389 -0
  84. package/src/plugins/command/list_bulleted.js +112 -0
  85. package/src/plugins/command/list_numbered.js +115 -0
  86. package/src/plugins/dropdown/align.js +143 -0
  87. package/src/plugins/dropdown/backgroundColor.js +73 -0
  88. package/src/plugins/dropdown/font.js +113 -0
  89. package/src/plugins/dropdown/fontColor.js +73 -0
  90. package/src/plugins/dropdown/formatBlock.js +141 -0
  91. package/src/plugins/dropdown/hr.js +111 -0
  92. package/src/plugins/dropdown/layout.js +72 -0
  93. package/src/plugins/dropdown/lineHeight.js +114 -0
  94. package/src/plugins/dropdown/list.js +107 -0
  95. package/src/plugins/dropdown/paragraphStyle.js +117 -0
  96. package/src/plugins/dropdown/table.js +2810 -0
  97. package/src/plugins/dropdown/template.js +71 -0
  98. package/src/plugins/dropdown/textStyle.js +137 -0
  99. package/src/plugins/field/mention.js +172 -0
  100. package/src/plugins/fileBrowser/imageGallery.js +76 -59
  101. package/src/plugins/index.js +86 -24
  102. package/src/plugins/input/fontSize.js +357 -0
  103. package/src/plugins/modal/audio.js +510 -0
  104. package/src/plugins/modal/image.js +1062 -0
  105. package/src/plugins/modal/link.js +211 -0
  106. package/src/plugins/modal/math.js +347 -0
  107. package/src/plugins/modal/video.js +870 -0
  108. package/src/suneditor.js +62 -67
  109. package/src/themes/test.css +61 -0
  110. package/typings/CommandPlugin.d.ts +8 -0
  111. package/typings/DialogPlugin.d.ts +20 -0
  112. package/typings/FileBrowserPlugin.d.ts +30 -0
  113. package/typings/Lang.d.ts +124 -0
  114. package/typings/Module.d.ts +15 -0
  115. package/typings/Plugin.d.ts +42 -0
  116. package/typings/SubmenuPlugin.d.ts +8 -0
  117. package/typings/_classes.d.ts +17 -0
  118. package/typings/_colorPicker.d.ts +60 -0
  119. package/typings/_core.d.ts +55 -0
  120. package/typings/align.d.ts +5 -0
  121. package/{src/plugins/dialog → typings}/audio.d.ts +1 -1
  122. package/typings/backgroundColor.d.ts +5 -0
  123. package/{src/plugins/command → typings}/blockquote.d.ts +1 -1
  124. package/typings/char.d.ts +39 -0
  125. package/typings/component.d.ts +38 -0
  126. package/typings/context.d.ts +39 -0
  127. package/typings/converter.d.ts +33 -0
  128. package/typings/dialog.d.ts +28 -0
  129. package/typings/domUtils.d.ts +361 -0
  130. package/typings/editor.d.ts +7 -0
  131. package/typings/editor.ts +542 -0
  132. package/typings/env.d.ts +70 -0
  133. package/typings/eventManager.d.ts +37 -0
  134. package/typings/events.d.ts +262 -0
  135. package/typings/fileBrowser.d.ts +42 -0
  136. package/typings/fileManager.d.ts +67 -0
  137. package/typings/font.d.ts +5 -0
  138. package/typings/fontColor.d.ts +5 -0
  139. package/typings/fontSize.d.ts +5 -0
  140. package/typings/format.d.ts +191 -0
  141. package/typings/formatBlock.d.ts +5 -0
  142. package/typings/history.d.ts +48 -0
  143. package/typings/horizontalRule.d.ts +5 -0
  144. package/{src/plugins/dialog → typings}/image.d.ts +1 -1
  145. package/{src/plugins/fileBrowser → typings}/imageGallery.d.ts +1 -1
  146. package/typings/index.d.ts +21 -0
  147. package/{src/plugins/modules/index.d.ts → typings/index.modules.d.ts} +3 -3
  148. package/typings/index.plugins.d.ts +58 -0
  149. package/typings/lineHeight.d.ts +5 -0
  150. package/{src/plugins/dialog → typings}/link.d.ts +1 -1
  151. package/typings/list.d.ts +5 -0
  152. package/{src/plugins/dialog → typings}/math.d.ts +1 -1
  153. package/typings/mediaContainer.d.ts +25 -0
  154. package/typings/node.d.ts +57 -0
  155. package/typings/notice.d.ts +16 -0
  156. package/typings/numbers.d.ts +29 -0
  157. package/typings/offset.d.ts +24 -0
  158. package/typings/options.d.ts +589 -0
  159. package/typings/paragraphStyle.d.ts +5 -0
  160. package/typings/resizing.d.ts +141 -0
  161. package/typings/selection.d.ts +94 -0
  162. package/typings/shortcuts.d.ts +13 -0
  163. package/typings/suneditor.d.ts +9 -0
  164. package/typings/table.d.ts +5 -0
  165. package/typings/template.d.ts +5 -0
  166. package/typings/textStyle.d.ts +5 -0
  167. package/typings/toolbar.d.ts +32 -0
  168. package/typings/unicode.d.ts +25 -0
  169. package/{src/plugins/dialog → typings}/video.d.ts +1 -1
  170. package/dist/css/suneditor.min.css +0 -1
  171. package/src/assets/css/suneditor-contents.css +0 -562
  172. package/src/assets/css/suneditor.css +0 -566
  173. package/src/assets/defaultIcons.js +0 -103
  174. package/src/lang/Lang.d.ts +0 -144
  175. package/src/lang/ckb.d.ts +0 -5
  176. package/src/lang/ckb.js +0 -188
  177. package/src/lang/cs.d.ts +0 -5
  178. package/src/lang/cs.js +0 -188
  179. package/src/lang/da.d.ts +0 -5
  180. package/src/lang/da.js +0 -191
  181. package/src/lang/de.d.ts +0 -5
  182. package/src/lang/de.js +0 -188
  183. package/src/lang/en.d.ts +0 -5
  184. package/src/lang/en.js +0 -188
  185. package/src/lang/es.d.ts +0 -5
  186. package/src/lang/es.js +0 -188
  187. package/src/lang/fa.d.ts +0 -5
  188. package/src/lang/fa.js +0 -188
  189. package/src/lang/fr.d.ts +0 -5
  190. package/src/lang/fr.js +0 -188
  191. package/src/lang/he.d.ts +0 -5
  192. package/src/lang/he.js +0 -188
  193. package/src/lang/index.d.ts +0 -23
  194. package/src/lang/it.d.ts +0 -5
  195. package/src/lang/it.js +0 -188
  196. package/src/lang/ja.d.ts +0 -5
  197. package/src/lang/ja.js +0 -188
  198. package/src/lang/ko.d.ts +0 -5
  199. package/src/lang/ko.js +0 -188
  200. package/src/lang/lv.d.ts +0 -5
  201. package/src/lang/lv.js +0 -188
  202. package/src/lang/nl.d.ts +0 -5
  203. package/src/lang/nl.js +0 -188
  204. package/src/lang/pl.d.ts +0 -5
  205. package/src/lang/pl.js +0 -188
  206. package/src/lang/pt_br.d.ts +0 -5
  207. package/src/lang/pt_br.js +0 -189
  208. package/src/lang/ro.d.ts +0 -5
  209. package/src/lang/ro.js +0 -188
  210. package/src/lang/ru.d.ts +0 -5
  211. package/src/lang/ru.js +0 -188
  212. package/src/lang/se.d.ts +0 -5
  213. package/src/lang/se.js +0 -191
  214. package/src/lang/tr.d.ts +0 -5
  215. package/src/lang/tr.js +0 -191
  216. package/src/lang/ua.d.ts +0 -5
  217. package/src/lang/ua.js +0 -188
  218. package/src/lang/ur.d.ts +0 -5
  219. package/src/lang/ur.js +0 -188
  220. package/src/lang/zh_cn.d.ts +0 -5
  221. package/src/lang/zh_cn.js +0 -187
  222. package/src/lib/constructor.js +0 -954
  223. package/src/lib/context.d.ts +0 -42
  224. package/src/lib/context.js +0 -71
  225. package/src/lib/core.d.ts +0 -1135
  226. package/src/lib/core.js +0 -9395
  227. package/src/lib/history.d.ts +0 -48
  228. package/src/lib/history.js +0 -219
  229. package/src/lib/util.d.ts +0 -678
  230. package/src/lib/util.js +0 -2131
  231. package/src/options.d.ts +0 -608
  232. package/src/plugins/CommandPlugin.d.ts +0 -8
  233. package/src/plugins/DialogPlugin.d.ts +0 -20
  234. package/src/plugins/FileBrowserPlugin.d.ts +0 -30
  235. package/src/plugins/Module.d.ts +0 -15
  236. package/src/plugins/Plugin.d.ts +0 -42
  237. package/src/plugins/SubmenuPlugin.d.ts +0 -8
  238. package/src/plugins/dialog/audio.js +0 -559
  239. package/src/plugins/dialog/image.js +0 -1126
  240. package/src/plugins/dialog/link.js +0 -223
  241. package/src/plugins/dialog/math.js +0 -295
  242. package/src/plugins/dialog/mention.js +0 -242
  243. package/src/plugins/dialog/video.js +0 -979
  244. package/src/plugins/index.d.ts +0 -79
  245. package/src/plugins/modules/_anchor.js +0 -461
  246. package/src/plugins/modules/_colorPicker.d.ts +0 -60
  247. package/src/plugins/modules/_colorPicker.js +0 -201
  248. package/src/plugins/modules/_notice.d.ts +0 -21
  249. package/src/plugins/modules/_notice.js +0 -72
  250. package/src/plugins/modules/_selectMenu.js +0 -119
  251. package/src/plugins/modules/component.d.ts +0 -25
  252. package/src/plugins/modules/component.js +0 -81
  253. package/src/plugins/modules/dialog.d.ts +0 -28
  254. package/src/plugins/modules/dialog.js +0 -175
  255. package/src/plugins/modules/fileBrowser.d.ts +0 -42
  256. package/src/plugins/modules/fileBrowser.js +0 -374
  257. package/src/plugins/modules/fileManager.d.ts +0 -67
  258. package/src/plugins/modules/fileManager.js +0 -326
  259. package/src/plugins/modules/index.js +0 -9
  260. package/src/plugins/modules/resizing.d.ts +0 -154
  261. package/src/plugins/modules/resizing.js +0 -903
  262. package/src/plugins/submenu/align.d.ts +0 -5
  263. package/src/plugins/submenu/align.js +0 -160
  264. package/src/plugins/submenu/font.d.ts +0 -5
  265. package/src/plugins/submenu/font.js +0 -123
  266. package/src/plugins/submenu/fontColor.d.ts +0 -5
  267. package/src/plugins/submenu/fontColor.js +0 -101
  268. package/src/plugins/submenu/fontSize.d.ts +0 -5
  269. package/src/plugins/submenu/fontSize.js +0 -112
  270. package/src/plugins/submenu/formatBlock.d.ts +0 -5
  271. package/src/plugins/submenu/formatBlock.js +0 -273
  272. package/src/plugins/submenu/hiliteColor.d.ts +0 -5
  273. package/src/plugins/submenu/hiliteColor.js +0 -102
  274. package/src/plugins/submenu/horizontalRule.d.ts +0 -5
  275. package/src/plugins/submenu/horizontalRule.js +0 -98
  276. package/src/plugins/submenu/lineHeight.d.ts +0 -5
  277. package/src/plugins/submenu/lineHeight.js +0 -104
  278. package/src/plugins/submenu/list.d.ts +0 -5
  279. package/src/plugins/submenu/list.js +0 -456
  280. package/src/plugins/submenu/paragraphStyle.d.ts +0 -5
  281. package/src/plugins/submenu/paragraphStyle.js +0 -135
  282. package/src/plugins/submenu/table.d.ts +0 -5
  283. package/src/plugins/submenu/table.js +0 -1431
  284. package/src/plugins/submenu/template.d.ts +0 -5
  285. package/src/plugins/submenu/template.js +0 -72
  286. package/src/plugins/submenu/textStyle.d.ts +0 -5
  287. package/src/plugins/submenu/textStyle.js +0 -167
  288. package/src/suneditor.d.ts +0 -9
  289. package/src/suneditor_build.js +0 -18
  290. /package/{src/plugins/dialog → typings}/mention.d.ts +0 -0
@@ -0,0 +1,510 @@
1
+ import EditorInjector from '../../editorInjector';
2
+ import { Modal, Controller, FileManager, Figure, _DragHandle } from '../../modules';
3
+ import { domUtils, numbers, env } from '../../helper';
4
+ const { NO_EVENT, ON_OVER_COMPONENT } = env;
5
+
6
+ const Audio_ = function (editor, pluginOptions) {
7
+ // plugin bisic properties
8
+ EditorInjector.call(this, editor);
9
+ this.title = this.lang.audio;
10
+ this.icon = 'audio';
11
+
12
+ // define plugin options
13
+ this.pluginOptions = {
14
+ defaultWidth: !pluginOptions.defaultWidth ? '' : numbers.is(pluginOptions.defaultWidth) ? pluginOptions.defaultWidth + 'px' : pluginOptions.defaultWidth,
15
+ defaultHeight: !pluginOptions.defaultHeight ? '' : numbers.is(pluginOptions.defaultHeight) ? pluginOptions.defaultHeight + 'px' : pluginOptions.defaultHeight,
16
+ createFileInput: !!pluginOptions.createFileInput,
17
+ createUrlInput: pluginOptions.createUrlInput === undefined || !pluginOptions.createFileInput ? true : pluginOptions.createUrlInput,
18
+ uploadUrl: typeof pluginOptions.uploadUrl === 'string' ? pluginOptions.uploadUrl : null,
19
+ uploadHeaders: pluginOptions.uploadHeaders || null,
20
+ uploadSizeLimit: /\d+/.test(pluginOptions.uploadSizeLimit) ? numbers.get(pluginOptions.uploadSizeLimit, 0) : null,
21
+ uploadSingleSizeLimit: /\d+/.test(pluginOptions.uploadSingleSizeLimit) ? numbers.get(pluginOptions.uploadSingleSizeLimit, 0) : null,
22
+ allowMultiple: !!pluginOptions.allowMultiple,
23
+ acceptedFormats: typeof pluginOptions.acceptedFormats !== 'string' || pluginOptions.acceptedFormats.trim() === '*' ? 'audio/*' : pluginOptions.acceptedFormats.trim() || 'audio/*',
24
+ audioTagAttributes: pluginOptions.audioTagAttributes || null
25
+ };
26
+
27
+ // create HTML
28
+ const modalEl = CreateHTML_modal(editor, this.pluginOptions);
29
+ const controllerEl = CreateHTML_controller(editor);
30
+
31
+ // modules
32
+ this.modal = new Modal(this, modalEl);
33
+ this.controller = new Controller(this, controllerEl, { position: 'bottom', disabled: true });
34
+ this.fileManager = new FileManager(this, {
35
+ query: 'audio',
36
+ loadHandler: this.events.onAudioLoad,
37
+ eventHandler: this.events.onAudioAction
38
+ });
39
+
40
+ // members
41
+ this.figure = new Figure(this, null, {});
42
+ this.fileModalWrapper = modalEl.querySelector('.se-flex-input-wrapper');
43
+ this.audioInputFile = modalEl.querySelector('.__se__file_input');
44
+ this.audioUrlFile = modalEl.querySelector('.se-input-url');
45
+ this.preview = modalEl.querySelector('.se-link-preview');
46
+ this.defaultWidth = this.pluginOptions.defaultWidth;
47
+ this.defaultHeight = this.pluginOptions.defaultHeight;
48
+ this.urlValue = '';
49
+ this._element = null;
50
+
51
+ // init
52
+ if (this.audioInputFile) {
53
+ modalEl.querySelector('.se-modal-files-edge-button').addEventListener('click', RemoveSelectedFiles.bind(this.audioInputFile, this.audioUrlFile, this.preview));
54
+ if (this.audioUrlFile) {
55
+ this.audioInputFile.addEventListener('change', FileInputChange.bind(this));
56
+ }
57
+ }
58
+ if (this.audioUrlFile) {
59
+ this.audioUrlFile.addEventListener('input', OnLinkPreview.bind(this));
60
+ }
61
+ };
62
+
63
+ Audio_.key = 'audio';
64
+ Audio_.type = 'modal';
65
+ Audio_.className = '';
66
+ Audio_.component = function (node) {
67
+ return /^AUDIO$/i.test(node?.nodeName) ? node : null;
68
+ };
69
+ Audio_.prototype = {
70
+ /**
71
+ * @override type = "modal"
72
+ */
73
+ open() {
74
+ this.modal.open();
75
+ },
76
+
77
+ /**
78
+ * @override modal
79
+ * @param {boolean} isUpdate open state is update
80
+ */
81
+ on(isUpdate) {
82
+ if (!isUpdate) {
83
+ if (this.audioInputFile && this.pluginOptions.allowMultiple) this.audioInputFile.setAttribute('multiple', 'multiple');
84
+ } else if (this._element) {
85
+ this.urlValue = this.preview.textContent = this.audioUrlFile.value = this._element.src;
86
+ if (this.audioInputFile && this.pluginOptions.allowMultiple) this.audioInputFile.removeAttribute('multiple');
87
+ } else {
88
+ if (this.audioInputFile && this.pluginOptions.allowMultiple) this.audioInputFile.removeAttribute('multiple');
89
+ }
90
+ },
91
+
92
+ /**
93
+ * @description On paste or drop
94
+ * @param {*} params { frameContext, event, file }
95
+ */
96
+ onPastAndDrop({ file }) {
97
+ if (!/^audio/.test(file.type)) return;
98
+
99
+ this._submitFile([file]);
100
+ this.editor.focus();
101
+
102
+ return false;
103
+ },
104
+
105
+ /**
106
+ * @override modal
107
+ * @returns {boolean | undefined}
108
+ */
109
+ modalAction() {
110
+ if (this.audioInputFile && this.audioInputFile?.files.length > 0) {
111
+ return this._submitFile(this.audioInputFile.files);
112
+ } else if (this.audioUrlFile && this.urlValue.length > 0) {
113
+ return this._submitURL(this.urlValue);
114
+ }
115
+ return false;
116
+ },
117
+
118
+ /**
119
+ * @override modal
120
+ */
121
+ init() {
122
+ Modal.OnChangeFile(this.fileModalWrapper, []);
123
+ if (this.audioInputFile) this.audioInputFile.value = '';
124
+ if (this.audioUrlFile) this.urlValue = this.preview.textContent = this.audioUrlFile.value = '';
125
+ if (this.audioInputFile && this.audioUrlFile) {
126
+ this.audioUrlFile.removeAttribute('disabled');
127
+ this.preview.style.textDecoration = '';
128
+ }
129
+ },
130
+
131
+ /**
132
+ * @override controller
133
+ * @param {Element} target Target button element
134
+ * @returns
135
+ */
136
+ controllerAction(target) {
137
+ if (/update/.test(target.getAttribute('data-command'))) {
138
+ if (this.audioUrlFile) this.urlValue = this.preview.textContent = this.audioUrlFile.value = this._element.src;
139
+ this.open();
140
+ } else {
141
+ this.destroy();
142
+ }
143
+ },
144
+
145
+ /**
146
+ * @override controller
147
+ */
148
+ close() {
149
+ if (!this._element) return;
150
+ domUtils.removeClass(this._element, 'active');
151
+ domUtils.removeClass(this._element.parentElement, 'se-figure-selected');
152
+ },
153
+
154
+ /**
155
+ * @override core
156
+ */
157
+ retainFormat() {
158
+ return {
159
+ query: 'audio',
160
+ method: (element) => {
161
+ const figureInfo = Figure.GetContainer(element);
162
+ if (figureInfo && figureInfo.container && figureInfo.cover) return;
163
+
164
+ this._setTagAttrs(element);
165
+ const figure = Figure.CreateContainer(element.cloneNode(true), 'se-flex-component');
166
+ this.figure._retainFigureFormat(figure.container, element, null);
167
+ }
168
+ };
169
+ },
170
+
171
+ /**
172
+ * @override component, fileManager
173
+ * @description Called when a container is selected.
174
+ * @param {Element} element Target element
175
+ */
176
+ select(element) {
177
+ this.figure.open(element, { nonResizing: true, nonSizeInfo: true, nonBorder: true, figureTarget: true, __fileManagerInfo: false });
178
+ this.ready(element);
179
+ },
180
+
181
+ /**
182
+ * @override fileManager
183
+ */
184
+ ready(target) {
185
+ if (_DragHandle.get('__overInfo') === ON_OVER_COMPONENT) return;
186
+ domUtils.addClass(target, 'active');
187
+ domUtils.addClass(target.parentElement, 'se-figure-selected');
188
+ this._element = target;
189
+ this.controller.open(target, null, { isWWTarget: false, initMethod: UnSelect.bind(null, target), addOffset: null });
190
+ },
191
+
192
+ /**
193
+ * @override fileManager
194
+ */
195
+ async destroy(element) {
196
+ element = element || this._element;
197
+ const figure = Figure.GetContainer(element);
198
+ const container = figure.container || element;
199
+ const focusEl = container.previousElementSibling || container.nextElementSibling;
200
+
201
+ const message = await this.triggerEvent('onAudioDeleteBefore', { target: element, container: figure, url: element.getAttribute('src') });
202
+ if (message === false) return;
203
+
204
+ const emptyDiv = container.parentNode;
205
+ domUtils.removeItem(container);
206
+ this.init();
207
+ this.controller.close();
208
+
209
+ if (emptyDiv !== this.editor.frameContext.get('wysiwyg')) {
210
+ this.nodeTransform.removeAllParents(
211
+ emptyDiv,
212
+ function (current) {
213
+ return current.childNodes.length === 0;
214
+ },
215
+ null
216
+ );
217
+ }
218
+
219
+ // focus
220
+ this.editor.focusEdge(focusEl);
221
+ this.history.push(false);
222
+ },
223
+
224
+ _register(info, response) {
225
+ const fileList = response.result;
226
+
227
+ for (let i = 0, len = fileList.length, file, oAudio; i < len; i++) {
228
+ if (info.isUpdate) oAudio = info.element;
229
+ else oAudio = this._createAudioTag();
230
+
231
+ file = { name: fileList[i].name, size: fileList[i].size };
232
+ this._createComp(oAudio, fileList[i].url, file, info.isUpdate);
233
+ }
234
+ },
235
+
236
+ async _submitFile(fileList) {
237
+ if (fileList.length === 0) return false;
238
+
239
+ let fileSize = 0;
240
+ const files = [];
241
+ const slngleSizeLimit = this.uploadSingleSizeLimit;
242
+ for (let i = 0, len = fileList.length, f, s; i < len; i++) {
243
+ f = fileList[i];
244
+ if (!/audio/i.test(f.type)) continue;
245
+
246
+ s = f.size;
247
+ if (slngleSizeLimit && slngleSizeLimit > s) {
248
+ const err = '[SUNEDITOR.audioUpload.fail] Size of uploadable single file: ' + slngleSizeLimit / 1000 + 'KB';
249
+ const message = await this.triggerEvent('onAudioUploadError', {
250
+ error: err,
251
+ limitSize: slngleSizeLimit,
252
+ uploadSize: s,
253
+ file: f
254
+ });
255
+
256
+ this.notice.open(message === NO_EVENT ? err : message || err);
257
+
258
+ return false;
259
+ }
260
+
261
+ files.push(f);
262
+ fileSize += s;
263
+ }
264
+
265
+ const limitSize = this.pluginOptions.uploadSizeLimit;
266
+ if (limitSize > 0 && fileSize + this.fileManager.getSize() > limitSize) {
267
+ const err = '[SUNEDITOR.audioUpload.fail] Size of uploadable total audios: ' + limitSize / 1000 + 'KB';
268
+ const message = await this.triggerEvent('onAudioUploadError', { error: err, limitSize, currentSize: this.fileManager.getSize(), uploadSize: fileSize });
269
+
270
+ this.notice.open(message === NO_EVENT ? err : message || err);
271
+
272
+ return false;
273
+ }
274
+
275
+ const audioInfo = {
276
+ files,
277
+ isUpdate: this.modal.isUpdate,
278
+ element: this._element
279
+ };
280
+
281
+ const handler = function (newInfos, infos) {
282
+ infos = newInfos || infos;
283
+ this._serverUpload(infos, infos.files);
284
+ }.bind(this, audioInfo);
285
+
286
+ const result = await this.triggerEvent('onAudioUploadBefore', {
287
+ ...audioInfo,
288
+ handler
289
+ });
290
+
291
+ if (typeof result === 'undefined') return true;
292
+ if (!result) return false;
293
+ if (result !== null && typeof result === 'object') handler(result);
294
+
295
+ if (result === true || result === NO_EVENT) handler(null);
296
+
297
+ return true;
298
+ },
299
+
300
+ async _submitURL(url) {
301
+ if (url.length === 0) return false;
302
+
303
+ const file = { name: url.split('/').pop(), size: 0 };
304
+ const audioInfo = {
305
+ url,
306
+ files: file,
307
+ isUpdate: this.modal.isUpdate,
308
+ element: this._createAudioTag()
309
+ };
310
+
311
+ const handler = function (newInfos, infos) {
312
+ infos = newInfos || infos;
313
+ this._createComp(infos.element, infos.url, infos.files, infos.isUpdate);
314
+ }.bind(this, audioInfo);
315
+
316
+ const result = await this.triggerEvent('onAudioUploadBefore', {
317
+ ...audioInfo,
318
+ handler
319
+ });
320
+
321
+ if (typeof result === 'undefined') return true;
322
+ if (!result) return false;
323
+ if (result !== null && typeof result === 'object') handler(result);
324
+
325
+ if (result === true || result === NO_EVENT) handler(null);
326
+
327
+ return true;
328
+ },
329
+
330
+ _createComp(element, src, file, isUpdate) {
331
+ // create new tag
332
+ if (!isUpdate) {
333
+ this.fileManager.setFileData(element, file);
334
+ element.src = src;
335
+ const figure = Figure.CreateContainer(element, 'se-flex-component');
336
+ if (!this.component.insert(figure.container, false, !this.options.get('mediaAutoSelect'))) {
337
+ this.editor.focus();
338
+ return;
339
+ }
340
+ if (!this.options.get('mediaAutoSelect')) {
341
+ const line = this.format.addLine(figure.container, null);
342
+ if (line) this.selection.setRange(line, 0, line, 0);
343
+ }
344
+ } else {
345
+ if (this._element) element = this._element;
346
+ this.fileManager.setFileData(element, file);
347
+ if (element && element.src !== src) {
348
+ element.src = src;
349
+ this.component.select(element, Audio_.key, false);
350
+ } else {
351
+ this.component.select(element, Audio_.key, false);
352
+ return;
353
+ }
354
+ }
355
+
356
+ if (isUpdate) this.history.push(false);
357
+ },
358
+
359
+ _createAudioTag() {
360
+ const w = this.defaultWidth;
361
+ const h = this.defaultHeight;
362
+ const oAudio = domUtils.createElement('AUDIO', { style: (w ? 'width:' + w + '; ' : '') + (h ? 'height:' + h + ';' : '') });
363
+ this._setTagAttrs(oAudio);
364
+ return oAudio;
365
+ },
366
+
367
+ _setTagAttrs(element) {
368
+ element.setAttribute('controls', true);
369
+
370
+ const attrs = this.pluginOptions.audioTagAttributes;
371
+ if (!attrs) return;
372
+
373
+ for (const key in attrs) {
374
+ element.setAttribute(key, attrs[key]);
375
+ }
376
+ },
377
+
378
+ _serverUpload(info, files) {
379
+ if (!files) return;
380
+
381
+ const uploadFiles = this.modal.isUpdate ? [files[0]] : files;
382
+ this.fileManager.upload(this.pluginOptions.uploadUrl, this.pluginOptions.uploadHeaders, uploadFiles, UploadCallBack.bind(this, info), this._error.bind(this));
383
+ },
384
+
385
+ async _error(response) {
386
+ const message = await this.triggerEvent('onAudioUploadError', { error: response });
387
+ const err = message === NO_EVENT ? response.errorMessage : message || response.errorMessage;
388
+ this.notice.open(err);
389
+ console.error('[SUNEDITOR.plugin.audio.error]', err);
390
+ },
391
+
392
+ constructor: Audio_
393
+ };
394
+
395
+ function UnSelect(target) {
396
+ if (target) {
397
+ domUtils.removeClass(target, 'active');
398
+ domUtils.removeClass(target.parentElement, 'se-figure-selected');
399
+ }
400
+ }
401
+
402
+ async function UploadCallBack(info, xmlHttp) {
403
+ if ((await this.triggerEvent('audioUploadHandler', { xmlHttp, info })) === NO_EVENT) {
404
+ const response = JSON.parse(xmlHttp.responseText);
405
+ if (response.errorMessage) {
406
+ this._error(response);
407
+ } else {
408
+ this._register(info, response);
409
+ }
410
+ }
411
+ }
412
+
413
+ function OnLinkPreview(e) {
414
+ const value = e.target.value.trim();
415
+ this.urlValue = this.preview.textContent = !value
416
+ ? ''
417
+ : this.options.get('defaultUrlProtocol') && !value.includes('://') && value.indexOf('#') !== 0
418
+ ? this.options.get('defaultUrlProtocol') + value
419
+ : !value.includes('://')
420
+ ? '/' + value
421
+ : value;
422
+ }
423
+
424
+ // Disable url input when uploading files
425
+ function RemoveSelectedFiles(urlInput, preview) {
426
+ this.value = '';
427
+ if (urlInput) {
428
+ urlInput.removeAttribute('disabled');
429
+ preview.style.textDecoration = '';
430
+ }
431
+
432
+ // inputFile check
433
+ Modal.OnChangeFile(this.fileModalWrapper, []);
434
+ }
435
+
436
+ // Disable url input when uploading files
437
+ function FileInputChange({ target }) {
438
+ if (!this.audioInputFile.value) {
439
+ this.audioUrlFile.removeAttribute('disabled');
440
+ this.preview.style.textDecoration = '';
441
+ } else {
442
+ this.audioUrlFile.setAttribute('disabled', true);
443
+ this.preview.style.textDecoration = 'line-through';
444
+ }
445
+
446
+ // inputFile check
447
+ Modal.OnChangeFile(this.fileModalWrapper, target.files);
448
+ }
449
+
450
+ function CreateHTML_modal({ lang, icons }, pluginOptions) {
451
+ let html = /*html*/ `
452
+ <form method="post" enctype="multipart/form-data">
453
+ <div class="se-modal-header">
454
+ <button type="button" data-command="close" class="se-btn se-close-btn" title="${lang.close}" aria-label="${lang.close}">
455
+ ${icons.cancel}
456
+ </button>
457
+ <span class="se-modal-title">${lang.audio_modal_title}</span>
458
+ </div>
459
+ <div class="se-modal-body">`;
460
+ if (pluginOptions.createFileInput) {
461
+ html += /*html*/ `
462
+ <div class="se-modal-form">
463
+ <label>${lang.audio_modal_file}</label>
464
+ ${Modal.CreateFileInput({ lang, icons }, pluginOptions)}
465
+ </div>`;
466
+ }
467
+ if (pluginOptions.createUrlInput) {
468
+ html += /*html*/ `
469
+ <div class="se-modal-form">
470
+ <label>${lang.audio_modal_url}</label>
471
+ <input class="se-input-form se-input-url" data-focus type="text" />
472
+ <pre class="se-link-preview"></pre>
473
+ </div>`;
474
+ }
475
+ html += /*html*/ `
476
+ </div>
477
+ <div class="se-modal-footer">
478
+ <button type="submit" class="se-btn-primary" title="${lang.submitButton}" aria-label="${lang.submitButton}">
479
+ <span>${lang.submitButton}</span>
480
+ </button>
481
+ </div>
482
+ </form>`;
483
+
484
+ return domUtils.createElement('DIV', { class: 'se-modal-content' }, html);
485
+ }
486
+
487
+ function CreateHTML_controller({ lang, icons }) {
488
+ const html = /*html*/ `
489
+ <div class="se-arrow se-arrow-up"></div>
490
+ <div class="link-content">
491
+ <div class="se-btn-group">
492
+ <button type="button" data-command="update" tabindex="-1" class="se-btn se-tooltip">
493
+ ${icons.edit}
494
+ <span class="se-tooltip-inner">
495
+ <span class="se-tooltip-text">${lang.edit}</span>
496
+ </span>
497
+ </button>
498
+ <button type="button" data-command="delete" tabindex="-1" class="se-btn se-tooltip">
499
+ ${icons.delete}
500
+ <span class="se-tooltip-inner">
501
+ <span class="se-tooltip-text">${lang.remove}</span>
502
+ </span>
503
+ </button>
504
+ </div>
505
+ </div>`;
506
+
507
+ return domUtils.createElement('DIV', { class: 'se-controller' }, html);
508
+ }
509
+
510
+ export default Audio_;