suneditor 2.46.2 → 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 -69
  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
@@ -1,1126 +0,0 @@
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 anchor from '../modules/_anchor';
12
- import component from '../modules/component';
13
- import resizing from '../modules/resizing';
14
- import fileManager from '../modules/fileManager';
15
-
16
- export default {
17
- name: 'image',
18
- display: 'dialog',
19
- add: function (core) {
20
- core.addModule([dialog, anchor, component, resizing, fileManager]);
21
-
22
- const options = core.options;
23
- const context = core.context;
24
- const contextImage = context.image = {
25
- _infoList: [], // @Override fileManager
26
- _infoIndex: 0, // @Override fileManager
27
- _uploadFileLength: 0, // @Override fileManager
28
- focusElement: null, // @Override dialog // This element has focus when the dialog is opened.
29
- sizeUnit: options._imageSizeUnit,
30
- _linkElement: '',
31
- _altText: '',
32
- _align: 'none',
33
- _floatClassRegExp: '__se__float\\-[a-z]+',
34
- _v_src: {_linkValue: ''},
35
- svgDefaultSize: '30%',
36
- base64RenderIndex: 0,
37
- // @require @Override component
38
- _element: null,
39
- _cover: null,
40
- _container: null,
41
- // @Override resizing properties
42
- inputX: null,
43
- inputY: null,
44
- _element_w: 1,
45
- _element_h: 1,
46
- _element_l: 0,
47
- _element_t: 0,
48
- _defaultSizeX: 'auto',
49
- _defaultSizeY: 'auto',
50
- _origin_w: options.imageWidth === 'auto' ? '' : options.imageWidth,
51
- _origin_h: options.imageHeight === 'auto' ? '' : options.imageHeight,
52
- _proportionChecked: true,
53
- _resizing: options.imageResizing,
54
- _resizeDotHide: !options.imageHeightShow,
55
- _rotation: options.imageRotation,
56
- _alignHide: !options.imageAlignShow,
57
- _onlyPercentage: options.imageSizeOnlyPercentage,
58
- _ratio: false,
59
- _ratioX: 1,
60
- _ratioY: 1,
61
- _captionShow: true,
62
- _captionChecked: false,
63
- _caption: null,
64
- captionCheckEl: null
65
- };
66
-
67
- /** image dialog */
68
- let image_dialog = this.setDialog(core);
69
- contextImage.modal = image_dialog;
70
- contextImage.imgInputFile = image_dialog.querySelector('._se_image_file');
71
- contextImage.imgUrlFile = image_dialog.querySelector('._se_image_url');
72
- contextImage.focusElement = contextImage.imgInputFile || contextImage.imgUrlFile;
73
- contextImage.altText = image_dialog.querySelector('._se_image_alt');
74
- contextImage.captionCheckEl = image_dialog.querySelector('._se_image_check_caption');
75
- contextImage.previewSrc = image_dialog.querySelector('._se_tab_content_image .se-link-preview');
76
-
77
- /** add event listeners */
78
- image_dialog.querySelector('.se-dialog-tabs').addEventListener('click', this.openTab.bind(core));
79
- image_dialog.querySelector('form').addEventListener('submit', this.submit.bind(core));
80
- if (contextImage.imgInputFile) image_dialog.querySelector('.se-file-remove').addEventListener('click', this._removeSelectedFiles.bind(contextImage.imgInputFile, contextImage.imgUrlFile, contextImage.previewSrc));
81
- if (contextImage.imgUrlFile) contextImage.imgUrlFile.addEventListener('input', this._onLinkPreview.bind(contextImage.previewSrc, contextImage._v_src, options.linkProtocol));
82
- if (contextImage.imgInputFile && contextImage.imgUrlFile) contextImage.imgInputFile.addEventListener('change', this._fileInputChange.bind(contextImage));
83
-
84
- const imageGalleryButton = image_dialog.querySelector('.__se__gallery');
85
- if (imageGalleryButton) imageGalleryButton.addEventListener('click', this._openGallery.bind(core));
86
-
87
- contextImage.proportion = {};
88
- contextImage.inputX = {};
89
- contextImage.inputY = {};
90
- if (options.imageResizing) {
91
- contextImage.proportion = image_dialog.querySelector('._se_image_check_proportion');
92
- contextImage.inputX = image_dialog.querySelector('._se_image_size_x');
93
- contextImage.inputY = image_dialog.querySelector('._se_image_size_y');
94
- contextImage.inputX.value = options.imageWidth;
95
- contextImage.inputY.value = options.imageHeight;
96
-
97
- contextImage.inputX.addEventListener('keyup', this.setInputSize.bind(core, 'x'));
98
- contextImage.inputY.addEventListener('keyup', this.setInputSize.bind(core, 'y'));
99
-
100
- contextImage.inputX.addEventListener('change', this.setRatio.bind(core));
101
- contextImage.inputY.addEventListener('change', this.setRatio.bind(core));
102
- contextImage.proportion.addEventListener('change', this.setRatio.bind(core));
103
-
104
- image_dialog.querySelector('.se-dialog-btn-revert').addEventListener('click', this.sizeRevert.bind(core));
105
- }
106
-
107
- /** append html */
108
- context.dialog.modal.appendChild(image_dialog);
109
-
110
- /** link event */
111
- core.plugins.anchor.initEvent.call(core, 'image', image_dialog.querySelector('._se_tab_content_url'));
112
- contextImage.anchorCtx = core.context.anchor.caller.image;
113
-
114
- /** empty memory */
115
- image_dialog = null;
116
- },
117
-
118
- /** dialog */
119
- setDialog: function (core) {
120
- const option = core.options;
121
- const lang = core.lang;
122
- const dialog = core.util.createElement('DIV');
123
-
124
- dialog.className = 'se-dialog-content se-dialog-image';
125
- dialog.style.display = 'none';
126
-
127
- let html = '' +
128
- '<div class="se-dialog-header">' +
129
- '<button type="button" data-command="close" class="se-btn se-dialog-close" class="close" title="' + lang.dialogBox.close + '" aria-label="' + lang.dialogBox.close + '">' +
130
- core.icons.cancel +
131
- '</button>' +
132
- '<span class="se-modal-title">' + lang.dialogBox.imageBox.title + '</span>' +
133
- '</div>' +
134
- '<div class="se-dialog-tabs">' +
135
- '<button type="button" class="_se_tab_link active" data-tab-link="image">' + lang.toolbar.image + '</button>' +
136
- '<button type="button" class="_se_tab_link" data-tab-link="url">' + lang.toolbar.link + '</button>' +
137
- '</div>' +
138
- '<form method="post" enctype="multipart/form-data">' +
139
- '<div class="_se_tab_content _se_tab_content_image">' +
140
- '<div class="se-dialog-body"><div style="border-bottom: 1px dashed #ccc;">';
141
-
142
- if (option.imageFileInput) {
143
- html += '' +
144
- '<div class="se-dialog-form">' +
145
- '<label>' + lang.dialogBox.imageBox.file + '</label>' +
146
- '<div class="se-dialog-form-files">' +
147
- '<input class="se-input-form _se_image_file" type="file" accept="' + option.imageAccept + '"' + (option.imageMultipleFile ? ' multiple="multiple"' : '') + '/>' +
148
- '<button type="button" class="se-btn se-dialog-files-edge-button se-file-remove" title="' + lang.controller.remove + '" aria-label="' + lang.controller.remove + '">' + core.icons.cancel + '</button>' +
149
- '</div>' +
150
- '</div>' ;
151
- }
152
-
153
- if (option.imageUrlInput) {
154
- html += '' +
155
- '<div class="se-dialog-form">' +
156
- '<label>' + lang.dialogBox.imageBox.url + '</label>' +
157
- '<div class="se-dialog-form-files">' +
158
- '<input class="se-input-form se-input-url _se_image_url" type="text" />' +
159
- ((option.imageGalleryUrl && core.plugins.imageGallery) ? '<button type="button" class="se-btn se-dialog-files-edge-button __se__gallery" title="' + lang.toolbar.imageGallery + '" aria-label="' + lang.toolbar.imageGallery + '">' + core.icons.image_gallery + '</button>' : '') +
160
- '</div>' +
161
- '<pre class="se-link-preview"></pre>' +
162
- '</div>';
163
- }
164
-
165
- html += '</div>' +
166
- '<div class="se-dialog-form">' +
167
- '<label>' + lang.dialogBox.imageBox.altText + '</label><input class="se-input-form _se_image_alt" type="text" />' +
168
- '</div>';
169
-
170
- if (option.imageResizing) {
171
- const onlyPercentage = option.imageSizeOnlyPercentage;
172
- const onlyPercentDisplay = onlyPercentage ? ' style="display: none !important;"' : '';
173
- const heightDisplay = !option.imageHeightShow ? ' style="display: none !important;"' : '';
174
- html += '<div class="se-dialog-form">';
175
- if (onlyPercentage || !option.imageHeightShow) {
176
- html += '' +
177
- '<div class="se-dialog-size-text">' +
178
- '<label class="size-w">' + lang.dialogBox.size + '</label>' +
179
- '</div>';
180
- } else {
181
- html += '' +
182
- '<div class="se-dialog-size-text">' +
183
- '<label class="size-w">' + lang.dialogBox.width + '</label>' +
184
- '<label class="se-dialog-size-x">&nbsp;</label>' +
185
- '<label class="size-h">' + lang.dialogBox.height + '</label>' +
186
- '</div>';
187
- }
188
- html += '' +
189
- '<input class="se-input-control _se_image_size_x" placeholder="auto"' + (onlyPercentage ? ' type="number" min="1"' : 'type="text"') + (onlyPercentage ? ' max="100"' : '') + ' />' +
190
- '<label class="se-dialog-size-x"' + heightDisplay + '>' + (onlyPercentage ? '%' : 'x') + '</label>' +
191
- '<input type="text" class="se-input-control _se_image_size_y" placeholder="auto"' + onlyPercentDisplay + (onlyPercentage ? ' max="100"' : '') + heightDisplay + '/>' +
192
- '<label' + onlyPercentDisplay + heightDisplay + '><input type="checkbox" class="se-dialog-btn-check _se_image_check_proportion" checked/>&nbsp;' + lang.dialogBox.proportion + '</label>' +
193
- '<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>' +
194
- '</div>' ;
195
- }
196
-
197
- html += '' +
198
- '<div class="se-dialog-form se-dialog-form-footer">' +
199
- '<label><input type="checkbox" class="se-dialog-btn-check _se_image_check_caption" />&nbsp;' + lang.dialogBox.caption + '</label>' +
200
- '</div>' +
201
- '</div>' +
202
- '</div>' +
203
- '<div class="_se_tab_content _se_tab_content_url" style="display: none">' +
204
- core.context.anchor.forms.innerHTML +
205
- '</div>' +
206
- '<div class="se-dialog-footer">' +
207
- '<div' + (option.imageAlignShow ? '' : ' style="display: none"') + '>' +
208
- '<label><input type="radio" name="suneditor_image_radio" class="se-dialog-btn-radio" value="none" checked>' + lang.dialogBox.basic + '</label>' +
209
- '<label><input type="radio" name="suneditor_image_radio" class="se-dialog-btn-radio" value="left">' + lang.dialogBox.left + '</label>' +
210
- '<label><input type="radio" name="suneditor_image_radio" class="se-dialog-btn-radio" value="center">' + lang.dialogBox.center + '</label>' +
211
- '<label><input type="radio" name="suneditor_image_radio" class="se-dialog-btn-radio" value="right">' + lang.dialogBox.right + '</label>' +
212
- '</div>' +
213
- '<button type="submit" class="se-btn-primary" title="' + lang.dialogBox.submitButton + '" aria-label="' + lang.dialogBox.submitButton + '"><span>' + lang.dialogBox.submitButton + '</span></button>' +
214
- '</div>' +
215
- '</form>';
216
-
217
- dialog.innerHTML = html;
218
-
219
- return dialog;
220
- },
221
-
222
- _fileInputChange: function () {
223
- if (!this.imgInputFile.value) {
224
- this.imgUrlFile.removeAttribute('disabled');
225
- this.previewSrc.style.textDecoration = '';
226
- } else {
227
- this.imgUrlFile.setAttribute('disabled', true);
228
- this.previewSrc.style.textDecoration = 'line-through';
229
- }
230
- },
231
-
232
- _removeSelectedFiles: function (urlInput, previewSrc) {
233
- this.value = '';
234
- if (urlInput) {
235
- urlInput.removeAttribute('disabled');
236
- previewSrc.style.textDecoration = '';
237
- }
238
- },
239
-
240
- _openGallery: function () {
241
- this.callPlugin('imageGallery', this.plugins.imageGallery.open.bind(this, this.plugins.image._setUrlInput.bind(this.context.image)), null);
242
- },
243
-
244
- _setUrlInput: function (target) {
245
- this.altText.value = target.alt;
246
- this._v_src._linkValue = this.previewSrc.textContent = this.imgUrlFile.value = target.getAttribute('data-value') || target.src;
247
- this.imgUrlFile.focus();
248
- },
249
-
250
- _onLinkPreview: function (context, protocol, e) {
251
- const value = e.target.value.trim();
252
- context._linkValue = this.textContent = !value ? '' : (protocol && value.indexOf('://') === -1 && value.indexOf('#') !== 0) ? protocol + value : value.indexOf('://') === -1 ? '/' + value : value;
253
- },
254
-
255
- /**
256
- * @Override @Required fileManager
257
- */
258
- fileTags: ['img'],
259
-
260
- /**
261
- * @Override core, fileManager, resizing
262
- * @description It is called from core.selectComponent.
263
- * @param {Element} element Target element
264
- */
265
- select: function (element) {
266
- this.plugins.image.onModifyMode.call(this, element, this.plugins.resizing.call_controller_resize.call(this, element, 'image'));
267
- },
268
-
269
- /**
270
- * @Override fileManager, resizing
271
- */
272
- destroy: function (element) {
273
- const imageEl = element || this.context.image._element;
274
- const imageContainer = this.util.getParentElement(imageEl, this.util.isMediaComponent) || imageEl;
275
- const dataIndex = imageEl.getAttribute('data-index') * 1;
276
-
277
- // event
278
- if (typeof this.functions.onImageDeleteBefore === 'function' && (this.functions.onImageDeleteBefore(imageEl, imageContainer, dataIndex, this) === false)) return;
279
-
280
- let focusEl = (imageContainer.previousElementSibling || imageContainer.nextElementSibling);
281
-
282
- const emptyDiv = imageContainer.parentNode;
283
- this.util.removeItem(imageContainer);
284
- this.plugins.image.init.call(this);
285
- this.controllersOff();
286
-
287
- if (emptyDiv !== this.context.element.wysiwyg) this.util.removeItemAllParents(emptyDiv, function (current) { return current.childNodes.length === 0; }, null);
288
-
289
- // focus
290
- this.focusEdge(focusEl);
291
-
292
- // event
293
- this.plugins.fileManager.deleteInfo.call(this, 'image', dataIndex, this.functions.onImageUpload);
294
-
295
- // history stack
296
- this.history.push(false);
297
- },
298
-
299
- /**
300
- * @Required @Override dialog
301
- */
302
- on: function (update) {
303
- const contextImage = this.context.image;
304
-
305
- if (!update) {
306
- contextImage.inputX.value = contextImage._origin_w = this.options.imageWidth === contextImage._defaultSizeX ? '' : this.options.imageWidth;
307
- contextImage.inputY.value = contextImage._origin_h = this.options.imageHeight === contextImage._defaultSizeY ? '' : this.options.imageHeight;
308
- if (contextImage.imgInputFile && this.options.imageMultipleFile) contextImage.imgInputFile.setAttribute('multiple', 'multiple');
309
- } else {
310
- if (contextImage.imgInputFile && this.options.imageMultipleFile) contextImage.imgInputFile.removeAttribute('multiple');
311
- }
312
- this.plugins.anchor.on.call(this, contextImage.anchorCtx, update);
313
- },
314
-
315
- /**
316
- * @Required @Override dialog
317
- */
318
- open: function () {
319
- this.plugins.dialog.open.call(this, 'image', 'image' === this.currentControllerName);
320
- },
321
-
322
- openTab: function (e) {
323
- const modal = this.context.image.modal;
324
- const targetElement = (e === 'init' ? modal.querySelector('._se_tab_link') : e.target);
325
-
326
- if (!/^BUTTON$/i.test(targetElement.tagName)) {
327
- return false;
328
- }
329
-
330
- // Declare all variables
331
- const tabName = targetElement.getAttribute('data-tab-link');
332
- const contentClassName = '_se_tab_content';
333
- let i, tabContent, tabLinks;
334
-
335
- // Get all elements with class="tabcontent" and hide them
336
- tabContent = modal.getElementsByClassName(contentClassName);
337
- for (i = 0; i < tabContent.length; i++) {
338
- tabContent[i].style.display = 'none';
339
- }
340
-
341
- // Get all elements with class="tablinks" and remove the class "active"
342
- tabLinks = modal.getElementsByClassName('_se_tab_link');
343
- for (i = 0; i < tabLinks.length; i++) {
344
- this.util.removeClass(tabLinks[i], 'active');
345
- }
346
-
347
- // Show the current tab, and add an "active" class to the button that opened the tab
348
- modal.querySelector('.' + contentClassName + '_' + tabName).style.display = 'block';
349
- this.util.addClass(targetElement, 'active');
350
-
351
- // focus
352
- if (tabName === 'image' && this.context.image.focusElement) {
353
- this.context.image.focusElement.focus();
354
- } else if (tabName === 'url') {
355
- this.context.anchor.caller.image.urlInput.focus();
356
- }
357
-
358
- return false;
359
- },
360
-
361
- submit: function (e) {
362
- const contextImage = this.context.image;
363
- const imagePlugin = this.plugins.image;
364
-
365
- e.preventDefault();
366
- e.stopPropagation();
367
-
368
- contextImage._altText = contextImage.altText.value;
369
- contextImage._align = contextImage.modal.querySelector('input[name="suneditor_image_radio"]:checked').value;
370
- contextImage._captionChecked = contextImage.captionCheckEl.checked;
371
- if (contextImage._resizing) contextImage._proportionChecked = contextImage.proportion.checked;
372
-
373
- try {
374
- if (this.context.dialog.updateModal) {
375
- imagePlugin.update_image.call(this, false, true, false);
376
- }
377
-
378
- if (contextImage.imgInputFile && contextImage.imgInputFile.files.length > 0) {
379
- this.showLoading();
380
- imagePlugin.submitAction.call(this, this.context.image.imgInputFile.files);
381
- } else if (contextImage.imgUrlFile && contextImage._v_src._linkValue.length > 0) {
382
- this.showLoading();
383
- imagePlugin.onRender_imgUrl.call(this, contextImage._v_src._linkValue);
384
- }
385
- } catch (error) {
386
- this.closeLoading();
387
- throw Error('[SUNEDITOR.image.submit.fail] cause : "' + error.message + '"');
388
- } finally {
389
- this.plugins.dialog.close.call(this);
390
- }
391
-
392
- return false;
393
- },
394
-
395
- submitAction: function (fileList) {
396
- if (fileList.length === 0) return;
397
-
398
- let fileSize = 0;
399
- let files = [];
400
- for (let i = 0, len = fileList.length; i < len; i++) {
401
- if (/image/i.test(fileList[i].type)) {
402
- files.push(fileList[i]);
403
- fileSize += fileList[i].size;
404
- }
405
- }
406
-
407
- const limitSize = this.options.imageUploadSizeLimit;
408
- if (limitSize > 0) {
409
- let infoSize = 0;
410
- const imagesInfo = this.context.image._infoList;
411
- for (let i = 0, len = imagesInfo.length; i < len; i++) {
412
- infoSize += imagesInfo[i].size * 1;
413
- }
414
-
415
- if ((fileSize + infoSize) > limitSize) {
416
- this.closeLoading();
417
- const err = '[SUNEDITOR.imageUpload.fail] Size of uploadable total images: ' + (limitSize/1000) + 'KB';
418
- if (typeof this.functions.onImageUploadError !== 'function' || this.functions.onImageUploadError(err, { 'limitSize': limitSize, 'currentSize': infoSize, 'uploadSize': fileSize }, this)) {
419
- this.functions.noticeOpen(err);
420
- }
421
- return;
422
- }
423
- }
424
-
425
- const contextImage = this.context.image;
426
- contextImage._uploadFileLength = files.length;
427
-
428
- const anchor = this.plugins.anchor.createAnchor.call(this, contextImage.anchorCtx, true);
429
- const info = {
430
- anchor: anchor,
431
- inputWidth: contextImage.inputX.value,
432
- inputHeight: contextImage.inputY.value,
433
- align: contextImage._align,
434
- isUpdate: this.context.dialog.updateModal,
435
- alt: contextImage._altText,
436
- element: contextImage._element
437
- };
438
-
439
- if (typeof this.functions.onImageUploadBefore === 'function') {
440
- const result = this.functions.onImageUploadBefore(files, info, this, function (data) {
441
- if (data && this._w.Array.isArray(data.result)) {
442
- this.plugins.image.register.call(this, info, data);
443
- } else {
444
- this.plugins.image.upload.call(this, info, data);
445
- }
446
- }.bind(this));
447
-
448
- if (typeof result === 'undefined') return;
449
- if (!result) {
450
- this.closeLoading();
451
- return;
452
- }
453
- if (this._w.Array.isArray(result) && result.length > 0) files = result;
454
- }
455
-
456
- this.plugins.image.upload.call(this, info, files);
457
- },
458
-
459
- error: function (message, response) {
460
- this.closeLoading();
461
- if (typeof this.functions.onImageUploadError !== 'function' || this.functions.onImageUploadError(message, response, this)) {
462
- this.functions.noticeOpen(message);
463
- throw Error('[SUNEDITOR.plugin.image.error] response: ' + message);
464
- }
465
- },
466
-
467
- upload: function (info, files) {
468
- if (!files) {
469
- this.closeLoading();
470
- return;
471
- }
472
- if (typeof files === 'string') {
473
- this.plugins.image.error.call(this, files, null);
474
- return;
475
- }
476
-
477
- const imageUploadUrl = this.options.imageUploadUrl;
478
- const filesLen = this.context.dialog.updateModal ? 1 : files.length;
479
-
480
- // server upload
481
- if (typeof imageUploadUrl === 'string' && imageUploadUrl.length > 0) {
482
- const formData = new FormData();
483
- for (let i = 0; i < filesLen; i++) {
484
- formData.append('file-' + i, files[i]);
485
- }
486
- this.plugins.fileManager.upload.call(this, imageUploadUrl, this.options.imageUploadHeader, formData, this.plugins.image.callBack_imgUpload.bind(this, info), this.functions.onImageUploadError);
487
- } else { // base64
488
- this.plugins.image.setup_reader.call(this, files, info.anchor, info.inputWidth, info.inputHeight, info.align, info.alt, filesLen, info.isUpdate);
489
- }
490
- },
491
-
492
- callBack_imgUpload: function (info, xmlHttp) {
493
- if (typeof this.functions.imageUploadHandler === 'function') {
494
- this.functions.imageUploadHandler(xmlHttp, info, this);
495
- } else {
496
- const response = JSON.parse(xmlHttp.responseText);
497
- if (response.errorMessage) {
498
- this.plugins.image.error.call(this, response.errorMessage, response);
499
- } else {
500
- this.plugins.image.register.call(this, info, response);
501
- }
502
- }
503
- },
504
-
505
- register: function (info, response) {
506
- const fileList = response.result;
507
-
508
- for (let i = 0, len = fileList.length, file; i < len; i++) {
509
- file = { name: fileList[i].name, size: fileList[i].size };
510
- if (info.isUpdate) {
511
- this.plugins.image.update_src.call(this, fileList[i].url, info.element, file);
512
- break;
513
- } else {
514
- this.plugins.image.create_image.call(this, fileList[i].url, info.anchor, info.inputWidth, info.inputHeight, info.align, file, info.alt);
515
- }
516
- }
517
-
518
- this.closeLoading();
519
- },
520
-
521
- setup_reader: function (files, anchor, width, height, align, alt, filesLen, isUpdate) {
522
- try {
523
- if (filesLen === 0) {
524
- this.closeLoading();
525
- console.warn('[SUNEDITOR.image.base64.fail] cause : No applicable files');
526
- return;
527
- }
528
-
529
- this.context.image.base64RenderIndex = filesLen;
530
- const wFileReader = this._w.FileReader;
531
- const filesStack = [filesLen];
532
- this.context.image.inputX.value = width;
533
- this.context.image.inputY.value = height;
534
-
535
- for (let i = 0, reader, file; i < filesLen; i++) {
536
- reader = new wFileReader();
537
- file = files[i];
538
-
539
- reader.onload = function (reader, update, updateElement, file, index) {
540
- filesStack[index] = { result: reader.result, file: file };
541
-
542
- if (--this.context.image.base64RenderIndex === 0) {
543
- this.plugins.image.onRender_imgBase64.call(this, update, filesStack, updateElement, anchor, width, height, align, alt);
544
- this.closeLoading();
545
- }
546
- }.bind(this, reader, isUpdate, this.context.image._element, file, i);
547
-
548
- reader.readAsDataURL(file);
549
- }
550
- } catch (e) {
551
- this.closeLoading();
552
- throw Error('[SUNEDITOR.image.setup_reader.fail] cause : "' + e.message + '"');
553
- }
554
- },
555
-
556
- onRender_imgBase64: function (update, filesStack, updateElement, anchor, width, height, align, alt) {
557
- const updateMethod = this.plugins.image.update_src;
558
- const createMethod = this.plugins.image.create_image;
559
-
560
- for (let i = 0, len = filesStack.length; i < len; i++) {
561
- if (update) {
562
- this.context.image._element.setAttribute('data-file-name', filesStack[i].file.name);
563
- this.context.image._element.setAttribute('data-file-size', filesStack[i].file.size);
564
- updateMethod.call(this, filesStack[i].result, updateElement, filesStack[i].file);
565
- } else {
566
- createMethod.call(this, filesStack[i].result, anchor, width, height, align, filesStack[i].file, alt);
567
- }
568
- }
569
- },
570
-
571
- onRender_imgUrl: function (url) {
572
- if (!url) url = this.context.image._v_src._linkValue;
573
- if (!url) return false;
574
- const contextImage = this.context.image;
575
-
576
- try {
577
- const file = {name: url.split('/').pop(), size: 0};
578
- if (this.context.dialog.updateModal) this.plugins.image.update_src.call(this, url, contextImage._element, file);
579
- else this.plugins.image.create_image.call(this, url, this.plugins.anchor.createAnchor.call(this, contextImage.anchorCtx, true), contextImage.inputX.value, contextImage.inputY.value, contextImage._align, file, contextImage._altText);
580
- } catch (e) {
581
- throw Error('[SUNEDITOR.image.URLRendering.fail] cause : "' + e.message + '"');
582
- } finally {
583
- this.closeLoading();
584
- }
585
- },
586
-
587
- onRender_link: function (imgTag, anchor) {
588
- if (anchor) {
589
- anchor.setAttribute('data-image-link', 'image');
590
- imgTag.setAttribute('data-image-link', anchor.href);
591
- anchor.appendChild(imgTag);
592
- return anchor;
593
- }
594
-
595
- return imgTag;
596
- },
597
-
598
- /**
599
- * @Override resizing
600
- * @param {String} xy 'x': width, 'y': height
601
- * @param {KeyboardEvent} e Event object
602
- */
603
- setInputSize: function (xy, e) {
604
- if (e && e.keyCode === 32) {
605
- e.preventDefault();
606
- return;
607
- }
608
-
609
- this.plugins.resizing._module_setInputSize.call(this, this.context.image, xy);
610
- },
611
-
612
- /**
613
- * @Override resizing
614
- */
615
- setRatio: function () {
616
- this.plugins.resizing._module_setRatio.call(this, this.context.image);
617
- },
618
-
619
- /**
620
- * @Override fileManager
621
- */
622
- checkFileInfo: function () {
623
- const imagePlugin = this.plugins.image;
624
- const contextImage = this.context.image;
625
-
626
- const modifyHandler = function (tag) {
627
- imagePlugin.onModifyMode.call(this, tag, null);
628
- imagePlugin.openModify.call(this, true);
629
- // get size
630
- contextImage.inputX.value = contextImage._origin_w;
631
- contextImage.inputY.value = contextImage._origin_h;
632
- // get align
633
- const format = this.util.getFormatElement(tag);
634
- if (format) contextImage._align = format.style.textAlign || format.style.float;
635
- // link
636
- if (this.util.isAnchor(tag.parentNode) && !contextImage.anchorCtx.linkValue) contextImage.anchorCtx.linkValue = ' ';
637
-
638
- imagePlugin.update_image.call(this, true, false, true);
639
- imagePlugin.init.call(this);
640
- }.bind(this);
641
-
642
- this.plugins.fileManager.checkInfo.call(this, 'image', ['img'], this.functions.onImageUpload, modifyHandler, true);
643
- },
644
-
645
- /**
646
- * @Override fileManager
647
- */
648
- resetFileInfo: function () {
649
- this.plugins.fileManager.resetInfo.call(this, 'image', this.functions.onImageUpload);
650
- },
651
-
652
- create_image: function (src, anchor, width, height, align, file, alt) {
653
- const imagePlugin = this.plugins.image;
654
- const contextImage = this.context.image;
655
- this.context.resizing._resize_plugin = 'image';
656
-
657
- let oImg = this.util.createElement('IMG');
658
- oImg.src = src;
659
- oImg.alt = alt;
660
- oImg.setAttribute('data-rotate', '0');
661
- anchor = imagePlugin.onRender_link.call(this, oImg, anchor ? anchor.cloneNode(false) : null);
662
-
663
- if (contextImage._resizing) {
664
- oImg.setAttribute('data-proportion', contextImage._proportionChecked);
665
- }
666
-
667
- const cover = this.plugins.component.set_cover.call(this, anchor);
668
- const container = this.plugins.component.set_container.call(this, cover, 'se-image-container');
669
-
670
- // caption
671
- if (contextImage._captionChecked) {
672
- contextImage._caption = this.plugins.component.create_caption.call(this);
673
- cover.appendChild(contextImage._caption);
674
- }
675
-
676
- contextImage._element = oImg;
677
- contextImage._cover = cover;
678
- contextImage._container = container;
679
-
680
- // set size
681
- imagePlugin.applySize.call(this, width, height);
682
-
683
- // align
684
- imagePlugin.setAlign.call(this, align, oImg, cover, container);
685
-
686
- oImg.onload = imagePlugin._image_create_onload.bind(this, oImg, contextImage.svgDefaultSize, container);
687
- if (this.insertComponent(container, true, true, true)) this.plugins.fileManager.setInfo.call(this, 'image', oImg, this.functions.onImageUpload, file, true);
688
- this.context.resizing._resize_plugin = '';
689
- },
690
-
691
- _image_create_onload: function (oImg, svgDefaultSize, container) {
692
- // svg exception handling
693
- if (oImg.offsetWidth === 0) this.plugins.image.applySize.call(this, svgDefaultSize, '');
694
- if (this.options.mediaAutoSelect) {
695
- this.selectComponent(oImg, 'image');
696
- } else {
697
- const line = this.appendFormatTag(container, null);
698
- if (line) this.setRange(line, 0, line, 0);
699
- }
700
- },
701
-
702
- update_image: function (init, openController, notHistoryPush) {
703
- const contextImage = this.context.image;
704
- let imageEl = contextImage._element;
705
- let cover = contextImage._cover;
706
- let container = contextImage._container;
707
- let isNewContainer = false;
708
-
709
- if (cover === null) {
710
- isNewContainer = true;
711
- imageEl = contextImage._element.cloneNode(true);
712
- cover = this.plugins.component.set_cover.call(this, imageEl);
713
- }
714
-
715
- if (container === null) {
716
- cover = cover.cloneNode(true);
717
- imageEl = cover.querySelector('img');
718
- isNewContainer = true;
719
- container = this.plugins.component.set_container.call(this, cover, 'se-image-container');
720
- } else if (isNewContainer) {
721
- container.innerHTML = '';
722
- container.appendChild(cover);
723
- contextImage._cover = cover;
724
- contextImage._element = imageEl;
725
- isNewContainer = false;
726
- }
727
-
728
- // check size
729
- let changeSize;
730
- const x = this.util.isNumber(contextImage.inputX.value) ? contextImage.inputX.value + contextImage.sizeUnit : contextImage.inputX.value;
731
- const y = this.util.isNumber(contextImage.inputY.value) ? contextImage.inputY.value + contextImage.sizeUnit : contextImage.inputY.value;
732
- if (/%$/.test(imageEl.style.width)) {
733
- changeSize = x !== container.style.width || y !== container.style.height;
734
- } else {
735
- changeSize = x !== imageEl.style.width || y !== imageEl.style.height;
736
- }
737
-
738
- // alt
739
- imageEl.alt = contextImage._altText;
740
-
741
- // caption
742
- let modifiedCaption = false;
743
- if (contextImage._captionChecked) {
744
- if (!contextImage._caption) {
745
- contextImage._caption = this.plugins.component.create_caption.call(this);
746
- cover.appendChild(contextImage._caption);
747
- modifiedCaption = true;
748
- }
749
- } else {
750
- if (contextImage._caption) {
751
- this.util.removeItem(contextImage._caption);
752
- contextImage._caption = null;
753
- modifiedCaption = true;
754
- }
755
- }
756
-
757
- // link
758
- let isNewAnchor = null;
759
- const anchor = this.plugins.anchor.createAnchor.call(this, contextImage.anchorCtx, true);
760
- if (anchor) {
761
- if (contextImage._linkElement !== anchor || (isNewContainer && !container.contains(anchor))) {
762
- contextImage._linkElement = anchor.cloneNode(false);
763
- cover.insertBefore(this.plugins.image.onRender_link.call(this, imageEl, contextImage._linkElement), contextImage._caption);
764
- isNewAnchor = contextImage._element;
765
- } else {
766
- contextImage._linkElement.setAttribute('data-image-link', 'image');
767
- }
768
- } else if (contextImage._linkElement !== null) {
769
- const imageElement = imageEl;
770
- imageElement.setAttribute('data-image-link', '');
771
- if (cover.contains(contextImage._linkElement)) {
772
- const newEl = imageElement.cloneNode(true);
773
- cover.removeChild(contextImage._linkElement);
774
- cover.insertBefore(newEl, contextImage._caption);
775
- contextImage._element = imageEl = newEl;
776
- }
777
- }
778
-
779
- let existElement = null;
780
- if (isNewContainer) {
781
- existElement = (this.util.isRangeFormatElement(contextImage._element.parentNode) || this.util.isWysiwygDiv(contextImage._element.parentNode)) ?
782
- contextImage._element :
783
- this.util.isAnchor(contextImage._element.parentNode) ? contextImage._element.parentNode : this.util.getFormatElement(contextImage._element) || contextImage._element;
784
-
785
- if (this.util.getParentElement(contextImage._element, this.util.isNotCheckingNode)) {
786
- existElement = isNewAnchor ? anchor : contextImage._element;
787
- existElement.parentNode.replaceChild(container, existElement);
788
- } else if (this.util.isListCell(existElement)) {
789
- const refer = this.util.getParentElement(contextImage._element, function (current) { return current.parentNode === existElement; });
790
- existElement.insertBefore(container, refer);
791
- this.util.removeItem(contextImage._element);
792
- this.util.removeEmptyNode(refer, null, true);
793
- } else if (this.util.isFormatElement(existElement)) {
794
- const refer = this.util.getParentElement(contextImage._element, function (current) { return current.parentNode === existElement; });
795
- existElement = this.util.splitElement(existElement, refer);
796
- existElement.parentNode.insertBefore(container, existElement);
797
- this.util.removeItem(contextImage._element);
798
- this.util.removeEmptyNode(existElement, null, true);
799
- if (existElement.children.length === 0) existElement.innerHTML = this.util.htmlRemoveWhiteSpace(existElement.innerHTML);
800
- } else {
801
- if (this.util.isFormatElement(existElement.parentNode)) {
802
- const formats = existElement.parentNode;
803
- formats.parentNode.insertBefore(container, existElement.previousSibling ? formats.nextElementSibling : formats);
804
- if (contextImage.__updateTags.map(function (current) { return existElement.contains(current); }).length === 0) this.util.removeItem(existElement);
805
- } else {
806
- existElement = this.util.isFigures(existElement.parentNode) ? existElement.parentNode : existElement;
807
- existElement.parentNode.replaceChild(container, existElement);
808
- }
809
- }
810
-
811
- imageEl = container.querySelector('img');
812
-
813
- contextImage._element = imageEl;
814
- contextImage._cover = cover;
815
- contextImage._container = container;
816
- }
817
-
818
- if (isNewAnchor) {
819
- if (!isNewContainer) {
820
- this.util.removeItem(anchor);
821
- } else {
822
- this.util.removeItem(isNewAnchor);
823
- if (this.util.getListChildren(anchor, function (current) { return /IMG/i.test(current.tagName); }).length === 0) {
824
- this.util.removeItem(anchor);
825
- }
826
- }
827
- }
828
-
829
- // transform
830
- if (modifiedCaption || (!contextImage._onlyPercentage && changeSize)) {
831
- if (!init && (/\d+/.test(imageEl.style.height) || (this.context.resizing._rotateVertical && contextImage._captionChecked))) {
832
- if (/%$/.test(contextImage.inputX.value) || /%$/.test(contextImage.inputY.value)) {
833
- this.plugins.resizing.resetTransform.call(this, imageEl);
834
- } else {
835
- this.plugins.resizing.setTransformSize.call(this, imageEl, this.util.getNumber(contextImage.inputX.value, 0), this.util.getNumber(contextImage.inputY.value, 0));
836
- }
837
- }
838
- }
839
-
840
- // size
841
- if (contextImage._resizing) {
842
- imageEl.setAttribute('data-proportion', contextImage._proportionChecked);
843
- if (changeSize) {
844
- this.plugins.image.applySize.call(this);
845
- }
846
- }
847
-
848
- // align
849
- this.plugins.image.setAlign.call(this, null, imageEl, null, null);
850
-
851
- // set imagesInfo
852
- if (init) {
853
- this.plugins.fileManager.setInfo.call(this, 'image', imageEl, this.functions.onImageUpload, null, true);
854
- }
855
-
856
- if (openController) {
857
- this.selectComponent(imageEl, 'image');
858
- }
859
-
860
- // history stack
861
- if (!notHistoryPush) this.history.push(false);
862
- },
863
-
864
- update_src: function (src, element, file) {
865
- element.src = src;
866
- this._w.setTimeout(this.plugins.fileManager.setInfo.bind(this, 'image', element, this.functions.onImageUpload, file, true));
867
- this.selectComponent(element, 'image');
868
- },
869
-
870
- /**
871
- * @Required @Override fileManager, resizing
872
- */
873
- onModifyMode: function (element, size) {
874
- if (!element) return;
875
-
876
- const contextImage = this.context.image;
877
- contextImage._linkElement = contextImage.anchorCtx.linkAnchor = this.util.isAnchor(element.parentNode) ? element.parentNode : null;
878
- contextImage._element = element;
879
- contextImage._cover = this.util.getParentElement(element, 'FIGURE');
880
- contextImage._container = this.util.getParentElement(element, this.util.isMediaComponent);
881
- contextImage._caption = this.util.getChildElement(contextImage._cover, 'FIGCAPTION');
882
- contextImage._align = element.getAttribute('data-align') || element.style.float || 'none';
883
- element.style.float = '';
884
- this.plugins.anchor.setCtx(contextImage._linkElement, contextImage.anchorCtx);
885
-
886
- if (size) {
887
- contextImage._element_w = size.w;
888
- contextImage._element_h = size.h;
889
- contextImage._element_t = size.t;
890
- contextImage._element_l = size.l;
891
- }
892
-
893
- let userSize = contextImage._element.getAttribute('data-size') || contextImage._element.getAttribute('data-origin');
894
- let w, h;
895
- if (userSize) {
896
- userSize = userSize.split(',');
897
- w = userSize[0];
898
- h = userSize[1];
899
- } else if (size) {
900
- w = size.w;
901
- h = size.h;
902
- }
903
-
904
- contextImage._origin_w = w || element.style.width || element.width || '';
905
- contextImage._origin_h = h || element.style.height || element.height || '';
906
- },
907
-
908
- /**
909
- * @Required @Override fileManager, resizing
910
- */
911
- openModify: function (notOpen) {
912
- const contextImage = this.context.image;
913
- if (contextImage.imgUrlFile) {
914
- contextImage._v_src._linkValue = contextImage.previewSrc.textContent = contextImage.imgUrlFile.value = contextImage._element.src;
915
- }
916
- contextImage._altText = contextImage.altText.value = contextImage._element.alt;
917
- (contextImage.modal.querySelector('input[name="suneditor_image_radio"][value="' + contextImage._align + '"]') || contextImage.modal.querySelector('input[name="suneditor_image_radio"][value="none"]')).checked = true;
918
- contextImage._align = contextImage.modal.querySelector('input[name="suneditor_image_radio"]:checked').value;
919
- contextImage._captionChecked = contextImage.captionCheckEl.checked = !!contextImage._caption;
920
-
921
- if (contextImage._resizing) {
922
- this.plugins.resizing._module_setModifyInputSize.call(this, contextImage, this.plugins.image);
923
- }
924
-
925
- if (!notOpen) this.plugins.dialog.open.call(this, 'image', true);
926
- },
927
-
928
- /**
929
- * @Override fileManager
930
- */
931
- applySize: function (w, h) {
932
- const contextImage = this.context.image;
933
-
934
- if (!w) w = contextImage.inputX.value || this.options.imageWidth;
935
- if (!h) h = contextImage.inputY.value || this.options.imageHeight;
936
-
937
- if ((contextImage._onlyPercentage && !!w) || /%$/.test(w)) {
938
- this.plugins.image.setPercentSize.call(this, w, h);
939
- return true;
940
- } else if ((!w || w === 'auto') && (!h || h === 'auto')) {
941
- this.plugins.image.setAutoSize.call(this);
942
- } else {
943
- this.plugins.image.setSize.call(this, w, h, false);
944
- }
945
-
946
- return false;
947
- },
948
-
949
- /**
950
- * @Override resizing
951
- */
952
- sizeRevert: function () {
953
- this.plugins.resizing._module_sizeRevert.call(this, this.context.image);
954
- },
955
-
956
- /**
957
- * @Override resizing
958
- */
959
- setSize: function (w, h, notResetPercentage, direction) {
960
- const contextImage = this.context.image;
961
- const onlyW = /^(rw|lw)$/.test(direction) && /\d+/.test(contextImage._element.style.height);
962
- const onlyH = /^(th|bh)$/.test(direction) && /\d+/.test(contextImage._element.style.width);
963
-
964
- if (!onlyH) {
965
- contextImage._element.style.width = this.util.isNumber(w) ? w + contextImage.sizeUnit : w;
966
- this.plugins.image.cancelPercentAttr.call(this);
967
- }
968
- if (!onlyW) {
969
- contextImage._element.style.height = this.util.isNumber(h) ? h + contextImage.sizeUnit : /%$/.test(h) ? '' : h;
970
- }
971
-
972
- if (contextImage._align === 'center') this.plugins.image.setAlign.call(this, null, null, null, null);
973
- if (!notResetPercentage) contextImage._element.removeAttribute('data-percentage');
974
-
975
- // save current size
976
- this.plugins.resizing._module_saveCurrentSize.call(this, contextImage);
977
- },
978
-
979
- /**
980
- * @Override resizing
981
- */
982
- setAutoSize: function () {
983
- const contextImage = this.context.image;
984
-
985
- if (contextImage._caption) contextImage._caption.style.marginTop = '';
986
- this.plugins.resizing.resetTransform.call(this, contextImage._element);
987
- this.plugins.image.cancelPercentAttr.call(this);
988
-
989
- contextImage._element.style.maxWidth = '';
990
- contextImage._element.style.width = '';
991
- contextImage._element.style.height = '';
992
- contextImage._cover.style.width = '';
993
- contextImage._cover.style.height = '';
994
-
995
- this.plugins.image.setAlign.call(this, null, null, null, null);
996
- contextImage._element.setAttribute('data-percentage', 'auto,auto');
997
-
998
- // save current size
999
- this.plugins.resizing._module_saveCurrentSize.call(this, contextImage);
1000
- },
1001
-
1002
- /**
1003
- * @Override resizing
1004
- */
1005
- setOriginSize: function () {
1006
- const contextImage = this.context.image;
1007
- contextImage._element.removeAttribute('data-percentage');
1008
-
1009
- this.plugins.resizing.resetTransform.call(this, contextImage._element);
1010
- this.plugins.image.cancelPercentAttr.call(this);
1011
-
1012
- const originSize = (contextImage._element.getAttribute('data-origin') || '').split(',');
1013
- const w = originSize[0];
1014
- const h = originSize[1];
1015
-
1016
- if (originSize) {
1017
- if (contextImage._onlyPercentage || (/%$/.test(w) && (/%$/.test(h) || !/\d/.test(h)))) {
1018
- this.plugins.image.setPercentSize.call(this, w, h);
1019
- } else {
1020
- this.plugins.image.setSize.call(this, w, h);
1021
- }
1022
-
1023
- // save current size
1024
- this.plugins.resizing._module_saveCurrentSize.call(this, contextImage);
1025
- }
1026
- },
1027
-
1028
- /**
1029
- * @Override resizing
1030
- */
1031
- setPercentSize: function (w, h) {
1032
- const contextImage = this.context.image;
1033
- h = !!h && !/%$/.test(h) && !this.util.getNumber(h, 0) ? this.util.isNumber(h) ? h + '%' : h : this.util.isNumber(h) ? h + contextImage.sizeUnit : (h || '');
1034
- const heightPercentage = /%$/.test(h);
1035
-
1036
- contextImage._container.style.width = this.util.isNumber(w) ? w + '%' : w;
1037
- contextImage._container.style.height = '';
1038
- contextImage._cover.style.width = '100%';
1039
- contextImage._cover.style.height = !heightPercentage ? '' : h;
1040
- contextImage._element.style.width = '100%';
1041
- contextImage._element.style.height = heightPercentage ? '' : h;
1042
- contextImage._element.style.maxWidth = '';
1043
-
1044
- if (contextImage._align === 'center') this.plugins.image.setAlign.call(this, null, null, null, null);
1045
-
1046
- contextImage._element.setAttribute('data-percentage', w + ',' + h);
1047
- this.plugins.resizing.setCaptionPosition.call(this, contextImage._element);
1048
-
1049
- // save current size
1050
- this.plugins.resizing._module_saveCurrentSize.call(this, contextImage);
1051
- },
1052
-
1053
- /**
1054
- * @Override resizing
1055
- */
1056
- cancelPercentAttr: function () {
1057
- const contextImage = this.context.image;
1058
-
1059
- contextImage._cover.style.width = '';
1060
- contextImage._cover.style.height = '';
1061
- contextImage._container.style.width = '';
1062
- contextImage._container.style.height = '';
1063
-
1064
- this.util.removeClass(contextImage._container, this.context.image._floatClassRegExp);
1065
- this.util.addClass(contextImage._container, '__se__float-' + contextImage._align);
1066
-
1067
- if (contextImage._align === 'center') this.plugins.image.setAlign.call(this, null, null, null, null);
1068
- },
1069
-
1070
- /**
1071
- * @Override resizing
1072
- */
1073
- setAlign: function (align, element, cover, container) {
1074
- const contextImage = this.context.image;
1075
-
1076
- if (!align) align = contextImage._align;
1077
- if (!element) element = contextImage._element;
1078
- if (!cover) cover = contextImage._cover;
1079
- if (!container) container = contextImage._container;
1080
-
1081
- if (/%$/.test(element.style.width) && align === 'center') {
1082
- container.style.minWidth = '100%';
1083
- cover.style.width = container.style.width;
1084
- } else {
1085
- container.style.minWidth = '';
1086
- cover.style.width = this.context.resizing._rotateVertical ? (element.style.height || element.offsetHeight) : ((!element.style.width || element.style.width === 'auto') ? '' : element.style.width || '100%');
1087
- }
1088
-
1089
- if (!this.util.hasClass(container, '__se__float-' + align)) {
1090
- this.util.removeClass(container, contextImage._floatClassRegExp);
1091
- this.util.addClass(container, '__se__float-' + align);
1092
- }
1093
-
1094
- element.setAttribute('data-align', align);
1095
- },
1096
-
1097
- /**
1098
- * @Override dialog
1099
- */
1100
- init: function () {
1101
- const contextImage = this.context.image;
1102
- if (contextImage.imgInputFile) contextImage.imgInputFile.value = '';
1103
- if (contextImage.imgUrlFile) contextImage._v_src._linkValue = contextImage.previewSrc.textContent = contextImage.imgUrlFile.value = '';
1104
- if (contextImage.imgInputFile && contextImage.imgUrlFile) {
1105
- contextImage.imgUrlFile.removeAttribute('disabled');
1106
- contextImage.previewSrc.style.textDecoration = '';
1107
- }
1108
-
1109
- contextImage.altText.value = '';
1110
- contextImage.modal.querySelector('input[name="suneditor_image_radio"][value="none"]').checked = true;
1111
- contextImage.captionCheckEl.checked = false;
1112
- contextImage._element = null;
1113
- this.plugins.image.openTab.call(this, 'init');
1114
-
1115
- if (contextImage._resizing) {
1116
- contextImage.inputX.value = this.options.imageWidth === contextImage._defaultSizeX ? '' : this.options.imageWidth;
1117
- contextImage.inputY.value = this.options.imageHeight === contextImage._defaultSizeY ? '' : this.options.imageHeight;
1118
- contextImage.proportion.checked = true;
1119
- contextImage._ratio = false;
1120
- contextImage._ratioX = 1;
1121
- contextImage._ratioY = 1;
1122
- }
1123
-
1124
- this.plugins.anchor.init.call(this, contextImage.anchorCtx);
1125
- }
1126
- };