suneditor 3.0.0-alpha.2 → 3.0.0-alpha.20

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 (306) hide show
  1. package/.eslintrc.json +4 -3
  2. package/CONTRIBUTING.md +4 -2
  3. package/README.md +19 -11
  4. package/README_V3_TEMP.md +705 -0
  5. package/dist/suneditor.min.css +1 -0
  6. package/dist/suneditor.min.js +1 -0
  7. package/example.md +587 -0
  8. package/package.json +15 -9
  9. package/src/assets/icons/_default.js +166 -131
  10. package/src/assets/{suneditor-content.css → suneditor-contents.css} +182 -45
  11. package/src/assets/suneditor.css +1195 -556
  12. package/src/assets/variables.css +138 -0
  13. package/src/core/base/eventHandlers/handler_toolbar.js +35 -14
  14. package/src/core/base/eventHandlers/handler_ww_clipboard.js +29 -4
  15. package/src/core/base/eventHandlers/handler_ww_dragDrop.js +59 -15
  16. package/src/core/base/eventHandlers/handler_ww_key_input.js +426 -212
  17. package/src/core/base/eventHandlers/handler_ww_mouse.js +108 -32
  18. package/src/core/base/eventManager.js +540 -209
  19. package/src/core/base/events.js +616 -320
  20. package/src/core/base/history.js +93 -39
  21. package/src/core/class/char.js +29 -13
  22. package/src/core/class/component.js +332 -145
  23. package/src/core/class/format.js +671 -509
  24. package/src/core/class/html.js +504 -290
  25. package/src/core/class/menu.js +114 -47
  26. package/src/core/class/nodeTransform.js +111 -66
  27. package/src/core/class/offset.js +409 -105
  28. package/src/core/class/selection.js +220 -108
  29. package/src/core/class/shortcuts.js +68 -8
  30. package/src/core/class/toolbar.js +106 -116
  31. package/src/core/class/ui.js +330 -0
  32. package/src/core/class/viewer.js +178 -74
  33. package/src/core/editor.js +489 -384
  34. package/src/core/section/actives.js +118 -22
  35. package/src/core/section/constructor.js +504 -170
  36. package/src/core/section/context.js +28 -23
  37. package/src/core/section/documentType.js +561 -0
  38. package/src/editorInjector/_classes.js +19 -5
  39. package/src/editorInjector/_core.js +71 -7
  40. package/src/editorInjector/index.js +63 -1
  41. package/src/helper/converter.js +137 -19
  42. package/src/helper/dom/domCheck.js +294 -0
  43. package/src/helper/dom/domQuery.js +609 -0
  44. package/src/helper/dom/domUtils.js +533 -0
  45. package/src/helper/dom/index.js +12 -0
  46. package/src/helper/env.js +42 -19
  47. package/src/helper/index.js +7 -4
  48. package/src/helper/keyCodeMap.js +183 -0
  49. package/src/helper/numbers.js +8 -8
  50. package/src/helper/unicode.js +5 -5
  51. package/src/langs/ckb.js +69 -3
  52. package/src/langs/cs.js +67 -1
  53. package/src/langs/da.js +68 -2
  54. package/src/langs/de.js +68 -3
  55. package/src/langs/en.js +29 -1
  56. package/src/langs/es.js +68 -3
  57. package/src/langs/fa.js +70 -2
  58. package/src/langs/fr.js +68 -2
  59. package/src/langs/he.js +68 -3
  60. package/src/langs/hu.js +226 -0
  61. package/src/langs/index.js +3 -2
  62. package/src/langs/it.js +65 -0
  63. package/src/langs/ja.js +68 -3
  64. package/src/langs/ko.js +66 -1
  65. package/src/langs/lv.js +68 -3
  66. package/src/langs/nl.js +68 -3
  67. package/src/langs/pl.js +68 -3
  68. package/src/langs/pt_br.js +65 -0
  69. package/src/langs/ro.js +69 -4
  70. package/src/langs/ru.js +68 -3
  71. package/src/langs/se.js +68 -3
  72. package/src/langs/tr.js +68 -0
  73. package/src/langs/ua.js +68 -3
  74. package/src/langs/ur.js +71 -6
  75. package/src/langs/zh_cn.js +69 -4
  76. package/src/modules/ApiManager.js +77 -54
  77. package/src/modules/Browser.js +667 -0
  78. package/src/modules/ColorPicker.js +162 -102
  79. package/src/modules/Controller.js +233 -136
  80. package/src/modules/Figure.js +913 -489
  81. package/src/modules/FileManager.js +141 -72
  82. package/src/modules/HueSlider.js +113 -61
  83. package/src/modules/Modal.js +292 -113
  84. package/src/modules/ModalAnchorEditor.js +380 -230
  85. package/src/modules/SelectMenu.js +270 -168
  86. package/src/modules/_DragHandle.js +2 -1
  87. package/src/modules/index.js +3 -3
  88. package/src/plugins/browser/audioGallery.js +83 -0
  89. package/src/plugins/browser/fileBrowser.js +103 -0
  90. package/src/plugins/browser/fileGallery.js +83 -0
  91. package/src/plugins/browser/imageGallery.js +81 -0
  92. package/src/plugins/browser/videoGallery.js +103 -0
  93. package/src/plugins/command/blockquote.js +40 -27
  94. package/src/plugins/command/exportPDF.js +134 -0
  95. package/src/plugins/command/fileUpload.js +226 -158
  96. package/src/plugins/command/list_bulleted.js +93 -47
  97. package/src/plugins/command/list_numbered.js +93 -47
  98. package/src/plugins/dropdown/align.js +66 -54
  99. package/src/plugins/dropdown/backgroundColor.js +76 -45
  100. package/src/plugins/dropdown/font.js +71 -47
  101. package/src/plugins/dropdown/fontColor.js +78 -46
  102. package/src/plugins/dropdown/formatBlock.js +74 -33
  103. package/src/plugins/dropdown/hr.js +102 -51
  104. package/src/plugins/dropdown/layout.js +37 -26
  105. package/src/plugins/dropdown/lineHeight.js +54 -38
  106. package/src/plugins/dropdown/list.js +60 -45
  107. package/src/plugins/dropdown/paragraphStyle.js +51 -30
  108. package/src/plugins/dropdown/table.js +1269 -777
  109. package/src/plugins/dropdown/template.js +38 -26
  110. package/src/plugins/dropdown/textStyle.js +43 -31
  111. package/src/plugins/field/mention.js +144 -82
  112. package/src/plugins/index.js +32 -6
  113. package/src/plugins/input/fontSize.js +161 -108
  114. package/src/plugins/input/pageNavigator.js +70 -0
  115. package/src/plugins/modal/audio.js +341 -169
  116. package/src/plugins/modal/drawing.js +530 -0
  117. package/src/plugins/modal/embed.js +886 -0
  118. package/src/plugins/modal/image.js +673 -358
  119. package/src/plugins/modal/link.js +100 -71
  120. package/src/plugins/modal/math.js +384 -168
  121. package/src/plugins/modal/video.js +693 -336
  122. package/src/plugins/popup/anchor.js +222 -0
  123. package/src/suneditor.js +54 -12
  124. package/src/themes/dark.css +85 -0
  125. package/src/typedef.js +86 -0
  126. package/types/assets/icons/_default.d.ts +152 -0
  127. package/types/core/base/eventHandlers/handler_toolbar.d.ts +41 -0
  128. package/types/core/base/eventHandlers/handler_ww_clipboard.d.ts +40 -0
  129. package/types/core/base/eventHandlers/handler_ww_dragDrop.d.ts +35 -0
  130. package/types/core/base/eventHandlers/handler_ww_key_input.d.ts +45 -0
  131. package/types/core/base/eventHandlers/handler_ww_mouse.d.ts +39 -0
  132. package/types/core/base/eventManager.d.ts +377 -0
  133. package/types/core/base/events.d.ts +297 -0
  134. package/types/core/base/history.d.ts +81 -0
  135. package/types/core/class/char.d.ts +60 -0
  136. package/types/core/class/component.d.ts +259 -0
  137. package/types/core/class/format.d.ts +615 -0
  138. package/types/core/class/html.d.ts +377 -0
  139. package/types/core/class/menu.d.ts +118 -0
  140. package/types/core/class/nodeTransform.d.ts +93 -0
  141. package/types/core/class/offset.d.ts +512 -0
  142. package/types/core/class/selection.d.ts +188 -0
  143. package/types/core/class/shortcuts.d.ts +142 -0
  144. package/types/core/class/toolbar.d.ts +189 -0
  145. package/types/core/class/ui.d.ts +144 -0
  146. package/types/core/class/viewer.d.ts +140 -0
  147. package/types/core/editor.d.ts +606 -0
  148. package/types/core/section/actives.d.ts +46 -0
  149. package/types/core/section/constructor.d.ts +748 -0
  150. package/types/core/section/context.d.ts +45 -0
  151. package/types/core/section/documentType.d.ts +178 -0
  152. package/types/editorInjector/_classes.d.ts +41 -0
  153. package/types/editorInjector/_core.d.ts +92 -0
  154. package/types/editorInjector/index.d.ts +71 -0
  155. package/types/helper/converter.d.ts +150 -0
  156. package/types/helper/dom/domCheck.d.ts +182 -0
  157. package/types/helper/dom/domQuery.d.ts +214 -0
  158. package/types/helper/dom/domUtils.d.ts +211 -0
  159. package/types/helper/dom/index.d.ts +9 -0
  160. package/types/helper/env.d.ts +149 -0
  161. package/types/helper/index.d.ts +163 -0
  162. package/types/helper/keyCodeMap.d.ts +110 -0
  163. package/types/helper/numbers.d.ts +43 -0
  164. package/types/helper/unicode.d.ts +28 -0
  165. package/types/index.d.ts +0 -0
  166. package/{typings/Lang.d.ts → types/langs/_Lang.d.ts} +170 -103
  167. package/types/langs/ckb.d.ts +384 -0
  168. package/types/langs/cs.d.ts +384 -0
  169. package/types/langs/da.d.ts +384 -0
  170. package/types/langs/de.d.ts +384 -0
  171. package/types/langs/en.d.ts +384 -0
  172. package/types/langs/es.d.ts +384 -0
  173. package/types/langs/fa.d.ts +384 -0
  174. package/types/langs/fr.d.ts +384 -0
  175. package/types/langs/he.d.ts +384 -0
  176. package/types/langs/hu.d.ts +384 -0
  177. package/types/langs/index.d.ts +48 -0
  178. package/types/langs/it.d.ts +384 -0
  179. package/types/langs/ja.d.ts +384 -0
  180. package/types/langs/ko.d.ts +384 -0
  181. package/types/langs/lv.d.ts +384 -0
  182. package/types/langs/nl.d.ts +384 -0
  183. package/types/langs/pl.d.ts +384 -0
  184. package/types/langs/pt_br.d.ts +384 -0
  185. package/types/langs/ro.d.ts +384 -0
  186. package/types/langs/ru.d.ts +384 -0
  187. package/types/langs/se.d.ts +384 -0
  188. package/types/langs/tr.d.ts +384 -0
  189. package/types/langs/ua.d.ts +384 -0
  190. package/types/langs/ur.d.ts +384 -0
  191. package/types/langs/zh_cn.d.ts +384 -0
  192. package/types/modules/ApiManager.d.ts +125 -0
  193. package/types/modules/Browser.d.ts +326 -0
  194. package/types/modules/ColorPicker.d.ts +131 -0
  195. package/types/modules/Controller.d.ts +231 -0
  196. package/types/modules/Figure.d.ts +504 -0
  197. package/types/modules/FileManager.d.ts +202 -0
  198. package/types/modules/HueSlider.d.ts +136 -0
  199. package/types/modules/Modal.d.ts +117 -0
  200. package/types/modules/ModalAnchorEditor.d.ts +236 -0
  201. package/types/modules/SelectMenu.d.ts +194 -0
  202. package/types/modules/_DragHandle.d.ts +7 -0
  203. package/types/modules/index.d.ts +26 -0
  204. package/types/plugins/browser/audioGallery.d.ts +55 -0
  205. package/types/plugins/browser/fileBrowser.d.ts +64 -0
  206. package/types/plugins/browser/fileGallery.d.ts +55 -0
  207. package/types/plugins/browser/imageGallery.d.ts +51 -0
  208. package/types/plugins/browser/videoGallery.d.ts +57 -0
  209. package/types/plugins/command/blockquote.d.ts +28 -0
  210. package/types/plugins/command/exportPDF.d.ts +46 -0
  211. package/types/plugins/command/fileUpload.d.ts +156 -0
  212. package/types/plugins/command/list_bulleted.d.ts +56 -0
  213. package/types/plugins/command/list_numbered.d.ts +56 -0
  214. package/types/plugins/dropdown/align.d.ts +60 -0
  215. package/types/plugins/dropdown/backgroundColor.d.ts +63 -0
  216. package/types/plugins/dropdown/font.d.ts +54 -0
  217. package/types/plugins/dropdown/fontColor.d.ts +63 -0
  218. package/types/plugins/dropdown/formatBlock.d.ts +58 -0
  219. package/types/plugins/dropdown/hr.d.ts +81 -0
  220. package/types/plugins/dropdown/layout.d.ts +40 -0
  221. package/types/plugins/dropdown/lineHeight.d.ts +50 -0
  222. package/types/plugins/dropdown/list.d.ts +39 -0
  223. package/types/plugins/dropdown/paragraphStyle.d.ts +54 -0
  224. package/types/plugins/dropdown/table.d.ts +579 -0
  225. package/types/plugins/dropdown/template.d.ts +40 -0
  226. package/types/plugins/dropdown/textStyle.d.ts +41 -0
  227. package/types/plugins/field/mention.d.ts +102 -0
  228. package/types/plugins/index.d.ts +107 -0
  229. package/types/plugins/input/fontSize.d.ts +170 -0
  230. package/types/plugins/input/pageNavigator.d.ts +28 -0
  231. package/types/plugins/modal/audio.d.ts +269 -0
  232. package/types/plugins/modal/drawing.d.ts +246 -0
  233. package/types/plugins/modal/embed.d.ts +387 -0
  234. package/types/plugins/modal/image.d.ts +451 -0
  235. package/types/plugins/modal/link.d.ts +128 -0
  236. package/types/plugins/modal/math.d.ts +193 -0
  237. package/types/plugins/modal/video.d.ts +485 -0
  238. package/types/plugins/popup/anchor.d.ts +56 -0
  239. package/types/suneditor.d.ts +51 -0
  240. package/types/typedef-global.d.ts +144 -0
  241. package/src/core/class/notice.js +0 -42
  242. package/src/helper/domUtils.js +0 -1177
  243. package/src/modules/FileBrowser.js +0 -271
  244. package/src/plugins/command/exportPdf.js +0 -168
  245. package/src/plugins/fileBrowser/imageGallery.js +0 -81
  246. package/src/themes/test.css +0 -61
  247. package/typings/CommandPlugin.d.ts +0 -8
  248. package/typings/DialogPlugin.d.ts +0 -20
  249. package/typings/FileBrowserPlugin.d.ts +0 -30
  250. package/typings/Module.d.ts +0 -15
  251. package/typings/Plugin.d.ts +0 -42
  252. package/typings/SubmenuPlugin.d.ts +0 -8
  253. package/typings/_classes.d.ts +0 -17
  254. package/typings/_colorPicker.d.ts +0 -60
  255. package/typings/_core.d.ts +0 -55
  256. package/typings/align.d.ts +0 -5
  257. package/typings/audio.d.ts +0 -5
  258. package/typings/backgroundColor.d.ts +0 -5
  259. package/typings/blockquote.d.ts +0 -5
  260. package/typings/char.d.ts +0 -39
  261. package/typings/component.d.ts +0 -38
  262. package/typings/context.d.ts +0 -39
  263. package/typings/converter.d.ts +0 -33
  264. package/typings/dialog.d.ts +0 -28
  265. package/typings/domUtils.d.ts +0 -361
  266. package/typings/editor.d.ts +0 -7
  267. package/typings/editor.ts +0 -542
  268. package/typings/env.d.ts +0 -70
  269. package/typings/eventManager.d.ts +0 -37
  270. package/typings/events.d.ts +0 -262
  271. package/typings/fileBrowser.d.ts +0 -42
  272. package/typings/fileManager.d.ts +0 -67
  273. package/typings/font.d.ts +0 -5
  274. package/typings/fontColor.d.ts +0 -5
  275. package/typings/fontSize.d.ts +0 -5
  276. package/typings/format.d.ts +0 -191
  277. package/typings/formatBlock.d.ts +0 -5
  278. package/typings/history.d.ts +0 -48
  279. package/typings/horizontalRule.d.ts +0 -5
  280. package/typings/image.d.ts +0 -5
  281. package/typings/imageGallery.d.ts +0 -5
  282. package/typings/index.d.ts +0 -21
  283. package/typings/index.modules.d.ts +0 -11
  284. package/typings/index.plugins.d.ts +0 -58
  285. package/typings/lineHeight.d.ts +0 -5
  286. package/typings/link.d.ts +0 -5
  287. package/typings/list.d.ts +0 -5
  288. package/typings/math.d.ts +0 -5
  289. package/typings/mediaContainer.d.ts +0 -25
  290. package/typings/mention.d.ts +0 -5
  291. package/typings/node.d.ts +0 -57
  292. package/typings/notice.d.ts +0 -16
  293. package/typings/numbers.d.ts +0 -29
  294. package/typings/offset.d.ts +0 -24
  295. package/typings/options.d.ts +0 -589
  296. package/typings/paragraphStyle.d.ts +0 -5
  297. package/typings/resizing.d.ts +0 -141
  298. package/typings/selection.d.ts +0 -94
  299. package/typings/shortcuts.d.ts +0 -13
  300. package/typings/suneditor.d.ts +0 -9
  301. package/typings/table.d.ts +0 -5
  302. package/typings/template.d.ts +0 -5
  303. package/typings/textStyle.d.ts +0 -5
  304. package/typings/toolbar.d.ts +0 -32
  305. package/typings/unicode.d.ts +0 -25
  306. package/typings/video.d.ts +0 -5
@@ -1,122 +1,164 @@
1
1
  import EditorInjector from '../editorInjector';
2
2
  import SelectMenu from './SelectMenu';
3
3
  import FileManager from './FileManager';
4
- import { domUtils, numbers, env, unicode } from '../helper';
4
+ import { dom, numbers, env, unicode } from '../helper';
5
5
  import { CreateTooltipInner } from '../core/section/constructor';
6
6
  const { NO_EVENT } = env;
7
7
 
8
8
  /**
9
- * @param {*} inst
10
- * @param {Element} modalForm
11
- * @param {object} params
12
- * @param {boolean} params.textToDisplay - Create Text to display input.
13
- * @param {string} params.title - Modal title
14
- * @param {boolean} params.openNewWindow - Default checked value of the "Open in new window" checkbox.
15
- * @param {boolean} params.relList - The "rel" attribute list of anchor tag.
16
- * @param {object} params.defaultRel - Default "rel" attributes of anchor tag.
17
- * @param {boolean} params.noAutoPrefix - If true, disables the automatic prefixing of the host URL to the value of the link.
18
- Example:
9
+ * @typedef {{default?: string, check_new_window?: string, check_bookmark?: string}} RELAttr
10
+ */
11
+
12
+ /**
13
+ * @typedef {Object} ModalAnchorEditorParams
14
+ * @property {boolean} [title=false] - Modal title display.
15
+ * @property {boolean} [textToDisplay=''] - Create Text to display input.
16
+ * @property {boolean} [openNewWindow=false] - Default checked value of the "Open in new window" checkbox.
17
+ * @property {boolean} [noAutoPrefix=false] - If true, disables the automatic prefixing of the host URL to the value of the link.
18
+ * @property {Array<string>} [relList=[]] - The "rel" attribute list of anchor tag.
19
+ * @property {RELAttr} [defaultRel={}] - Default "rel" attributes of anchor tag.
20
+ * @property {string=} uploadUrl - File upload URL.
21
+ * @property {Object<string, string>=} uploadHeaders - File upload headers.
22
+ * @property {number=} uploadSizeLimit - File upload size limit.
23
+ * @property {number=} uploadSingleSizeLimit - File upload single size limit.
24
+ * @property {string=} acceptedFormats - File upload accepted formats.
25
+ * @property {boolean=} enableFileUpload - If true, enables file upload.
26
+ * @example "REL" structure
19
27
  {
20
28
  default: 'nofollow', // Default rel
21
29
  check_new_window: 'noreferrer noopener', // When "open new window" is checked
22
30
  check_bookmark: 'bookmark' // When "bookmark" is checked
23
31
  }
24
- * @param {boolean} params.noAutoPrefix - If true, disables the automatic prefixing of the host URL to the value of the link.
32
+ If true, disables the automatic prefixing of the host URL to the value of the link.
25
33
  */
26
- const ModalAnchorEditor = function (inst, modalForm, params) {
27
- // plugin bisic properties
28
- EditorInjector.call(this, inst.editor);
29
-
30
- // params
31
- this.openNewWindow = !!params.openNewWindow;
32
- this.relList = Array.isArray(params.relList) ? params.relList : [];
33
- this.defaultRel = params.defaultRel || {};
34
- this.noAutoPrefix = !!params.noAutoPrefix;
35
- // file upload
36
- if (params.enableFileUpload) {
37
- this.uploadUrl = typeof params.uploadUrl === 'string' ? params.uploadUrl : null;
38
- this.uploadHeaders = params.uploadHeaders || null;
39
- this.uploadSizeLimit = /\d+/.test(params.uploadSizeLimit) ? numbers.get(params.uploadSizeLimit, 0) : null;
40
- this.uploadSingleSizeLimit = /\d+/.test(params.uploadSingleSizeLimit) ? numbers.get(params.uploadSingleSizeLimit, 0) : null;
41
- this.input = domUtils.createElement('input', { type: 'file', accept: params.acceptedFormats || '*' });
42
- this.eventManager.addEvent(this.input, 'change', OnChangeFile.bind(this));
43
- // file manager
44
- this.fileManager = new FileManager(this, {
45
- query: 'a[download]:not([data-se-file-download])',
46
- loadHandler: this.events.onFileLoad,
47
- eventHandler: this.events.onFileAction
48
- });
49
- }
50
34
 
51
- // create HTML
52
- const forms = CreatetModalForm(inst.editor, params, this.relList);
53
-
54
- // members
55
- this.kink = inst.constructor.key || inst.constructor.name;
56
- this.inst = inst;
57
- this.modalForm = modalForm;
58
- this.host = (this._w.location.origin + this._w.location.pathname).replace(/\/$/, '');
59
- this.urlInput = forms.querySelector('.se-input-url');
60
- this.displayInput = forms.querySelector('._se_display_text');
61
- this.titleInput = forms.querySelector('._se_title');
62
- this.newWindowCheck = forms.querySelector('._se_anchor_check');
63
- this.downloadCheck = forms.querySelector('._se_anchor_download');
64
- this.download = forms.querySelector('._se_anchor_download_icon');
65
- this.preview = forms.querySelector('.se-link-preview');
66
- this.bookmark = forms.querySelector('._se_anchor_bookmark_icon');
67
- this.bookmarkButton = forms.querySelector('._se_bookmark_button');
68
- this.currentRel = [];
69
- this.currentTarget = null;
70
- this.linkValue = '';
71
- this._change = false;
72
- this._isRel = this.relList.length > 0;
73
- // members - rel
74
- if (this._isRel) {
75
- this.relButton = forms.querySelector('.se-anchor-rel-btn');
76
- this.relPreview = forms.querySelector('.se-anchor-rel-preview');
77
- const relList = this.relList;
78
- const defaultRel = (this.defaultRel.default || '').split(' ');
79
- const list = [];
80
- for (let i = 0, len = relList.length, rel; i < len; i++) {
81
- rel = relList[i];
82
- list.push(
83
- domUtils.createElement(
84
- 'BUTTON',
85
- {
86
- type: 'button',
87
- class: 'se-btn-list' + (defaultRel.includes(rel) ? ' se-checked' : ''),
88
- 'data-command': rel,
89
- title: rel,
90
- 'aria-label': rel
91
- },
92
- rel + '<span class="se-svg">' + this.icons.checked + '</span>'
93
- )
94
- );
35
+ /**
36
+ * @class
37
+ * @description Modal form Anchor tag editor
38
+ * - Use it by inserting it into Modal in a plugin that uses Modal.
39
+ */
40
+ class ModalAnchorEditor extends EditorInjector {
41
+ /**
42
+ * @constructor
43
+ * @param {*} inst The instance object that called the constructor.
44
+ * @param {Node} modalForm The modal form element
45
+ * @param {ModalAnchorEditorParams} params ModalAnchorEditor options
46
+ */
47
+ constructor(inst, modalForm, params) {
48
+ // plugin bisic properties
49
+ super(inst.editor);
50
+
51
+ // params
52
+ this.openNewWindow = !!params.openNewWindow;
53
+ this.relList = Array.isArray(params.relList) ? params.relList : [];
54
+ this.defaultRel = params.defaultRel || {};
55
+ this.noAutoPrefix = !!params.noAutoPrefix;
56
+ // file upload
57
+ if (params.enableFileUpload) {
58
+ this.uploadUrl = typeof params.uploadUrl === 'string' ? params.uploadUrl : null;
59
+ this.uploadHeaders = params.uploadHeaders || null;
60
+ this.uploadSizeLimit = numbers.get(params.uploadSizeLimit, 0) || null;
61
+ this.uploadSingleSizeLimit = numbers.get(params.uploadSingleSizeLimit, 0) || null;
62
+ this.input = dom.utils.createElement('input', { type: 'file', accept: params.acceptedFormats || '*' });
63
+ this.eventManager.addEvent(this.input, 'change', this.#OnChangeFile.bind(this));
64
+ // file manager
65
+ this.fileManager = new FileManager(this, {
66
+ query: 'a[download]:not([data-se-file-download])',
67
+ loadHandler: this.events.onFileLoad,
68
+ eventHandler: this.events.onFileAction
69
+ });
95
70
  }
96
- this.selectMenu_rel = new SelectMenu(this, { checkList: true, position: 'right-middle', dir: 'ltr' });
97
- this.selectMenu_rel.on(this.relButton, SetRelItem.bind(this));
98
- this.selectMenu_rel.create(list);
99
- this.eventManager.addEvent(this.relButton, 'click', OnClick_relbutton.bind(this));
100
- }
101
71
 
102
- // init
103
- modalForm.querySelector('.se-anchor-editor').appendChild(forms);
104
- this.selectMenu_bookmark = new SelectMenu(this, { checkList: false, position: 'bottom-left', dir: 'ltr' });
105
- this.selectMenu_bookmark.on(this.urlInput, SetHeaderBookmark.bind(this));
106
- this.eventManager.addEvent(this.newWindowCheck, 'change', OnChange_newWindowCheck.bind(this));
107
- this.eventManager.addEvent(this.downloadCheck, 'change', OnChange_downloadCheck.bind(this));
108
- this.eventManager.addEvent(this.displayInput, 'input', OnChange_displayInput.bind(this));
109
- this.eventManager.addEvent(this.urlInput, 'input', OnChange_urlInput.bind(this));
110
- this.eventManager.addEvent(this.urlInput, 'focus', OnFocus_urlInput.bind(this));
111
- this.eventManager.addEvent(this.bookmarkButton, 'click', OnClick_bookmarkButton.bind(this));
112
- this.eventManager.addEvent(forms.querySelector('._se_upload_button'), 'click', () => this.input.click());
113
- };
114
-
115
- ModalAnchorEditor.prototype = {
72
+ // create HTML
73
+ const forms = CreatetModalForm(inst.editor, params, this.relList);
74
+
75
+ // members
76
+ this.kink = inst.constructor.key || inst.constructor.name;
77
+ this.inst = inst;
78
+ this.modalForm = /** @type {HTMLElement} */ (modalForm);
79
+ this.host = (this._w.location.origin + this._w.location.pathname).replace(/\/$/, '');
80
+
81
+ /** @type {HTMLInputElement} */
82
+ this.urlInput = forms.querySelector('.se-input-url');
83
+ /** @type {HTMLInputElement} */
84
+ this.displayInput = forms.querySelector('._se_display_text');
85
+ /** @type {HTMLInputElement} */
86
+ this.titleInput = forms.querySelector('._se_title');
87
+ /** @type {HTMLInputElement} */
88
+ this.newWindowCheck = forms.querySelector('._se_anchor_check');
89
+ /** @type {HTMLInputElement} */
90
+ this.downloadCheck = forms.querySelector('._se_anchor_download');
91
+ /** @type {HTMLElement} */
92
+ this.download = forms.querySelector('._se_anchor_download_icon');
93
+ /** @type {HTMLElement} */
94
+ this.preview = forms.querySelector('.se-link-preview');
95
+ /** @type {HTMLElement} */
96
+ this.bookmark = forms.querySelector('._se_anchor_bookmark_icon');
97
+ /** @type {HTMLButtonElement} */
98
+ this.bookmarkButton = forms.querySelector('._se_bookmark_button');
99
+
100
+ this.currentRel = [];
101
+ this.currentTarget = null;
102
+ this.linkValue = '';
103
+ this._change = false;
104
+ this._isRel = this.relList.length > 0;
105
+ // members - rel
106
+ if (this._isRel) {
107
+ /** @type {HTMLButtonElement} */
108
+ this.relButton = forms.querySelector('.se-anchor-rel-btn');
109
+ /** @type {HTMLElement} */
110
+ this.relPreview = forms.querySelector('.se-anchor-rel-preview');
111
+
112
+ const relList = this.relList;
113
+ const defaultRel = (this.defaultRel.default || '').split(' ');
114
+ const list = [];
115
+ for (let i = 0, len = relList.length, rel; i < len; i++) {
116
+ rel = relList[i];
117
+ list.push(
118
+ dom.utils.createElement(
119
+ 'BUTTON',
120
+ {
121
+ type: 'button',
122
+ class: 'se-btn-list' + (defaultRel.includes(rel) ? ' se-checked' : ''),
123
+ 'data-command': rel,
124
+ title: rel,
125
+ 'aria-label': rel
126
+ },
127
+ rel + '<span class="se-svg">' + this.icons.checked + '</span>'
128
+ )
129
+ );
130
+ }
131
+ this.selectMenu_rel = new SelectMenu(this, { checkList: true, position: 'right-middle', dir: 'ltr' });
132
+ this.selectMenu_rel.on(this.relButton, this.#SetRelItem.bind(this));
133
+ this.selectMenu_rel.create(list);
134
+ this.eventManager.addEvent(this.relButton, 'click', this.#OnClick_relbutton.bind(this));
135
+ }
136
+
137
+ // init
138
+ this.modalForm.querySelector('.se-anchor-editor').appendChild(forms);
139
+ this.selectMenu_bookmark = new SelectMenu(this, { checkList: false, position: 'bottom-left', dir: 'ltr' });
140
+ this.selectMenu_bookmark.on(this.urlInput, this.#SetHeaderBookmark.bind(this));
141
+ this.eventManager.addEvent(this.newWindowCheck, 'change', this.#OnChange_newWindowCheck.bind(this));
142
+ this.eventManager.addEvent(this.downloadCheck, 'change', this.#OnChange_downloadCheck.bind(this));
143
+ this.eventManager.addEvent(this.displayInput, 'input', this.#OnChange_displayInput.bind(this));
144
+ this.eventManager.addEvent(this.urlInput, 'input', this.#OnChange_urlInput.bind(this));
145
+ this.eventManager.addEvent(this.urlInput, 'focus', this.#OnFocus_urlInput.bind(this));
146
+ this.eventManager.addEvent(this.bookmarkButton, 'click', this.#OnClick_bookmarkButton.bind(this));
147
+ this.eventManager.addEvent(forms.querySelector('._se_upload_button'), 'click', () => this.input.click());
148
+ }
149
+ /**
150
+ * @description Initialize.
151
+ * - Sets the current anchor element to be edited.
152
+ * @param {Node} element Modal target element
153
+ */
116
154
  set(element) {
117
- this.currentTarget = element;
118
- },
155
+ this.currentTarget = /** @type {HTMLAnchorElement} */ (element);
156
+ }
119
157
 
158
+ /**
159
+ * @description Opens the anchor editor modal and populates it with data.
160
+ * @param {boolean} isUpdate - Indicates whether an existing anchor is being updated (`true`) or a new one is being created (`false`).
161
+ */
120
162
  on(isUpdate) {
121
163
  if (!isUpdate) {
122
164
  this.init();
@@ -124,31 +166,39 @@ ModalAnchorEditor.prototype = {
124
166
  this.newWindowCheck.checked = this.openNewWindow;
125
167
  this.titleInput.value = '';
126
168
  } else if (this.currentTarget) {
127
- const href = this.currentTarget.getAttribute('href');
128
- this.linkValue = this.preview.textContent = this.urlInput.value = this._selfPathBookmark(href) ? href.substr(href.lastIndexOf('#')) : href;
169
+ const href = this.currentTarget.href;
170
+ this.linkValue = this.preview.textContent = this.urlInput.value = this._selfPathBookmark(href) ? href.substring(href.lastIndexOf('#')) : href;
129
171
  this.displayInput.value = this.currentTarget.textContent;
130
172
  this.titleInput.value = this.currentTarget.title;
131
173
  this.newWindowCheck.checked = /_blank/i.test(this.currentTarget.target) ? true : false;
132
- this.downloadCheck.checked = this.currentTarget.download;
174
+ this.downloadCheck.checked = !!this.currentTarget.download;
133
175
  }
134
176
 
135
177
  this._setRel(isUpdate && this.currentTarget ? this.currentTarget.rel : this.defaultRel.default || '');
136
178
  this._setLinkPreview(this.linkValue);
137
- },
179
+ }
138
180
 
181
+ /**
182
+ * @description Creates an anchor (`<a>`) element with the specified attributes.
183
+ * @param {boolean} notText - If `true`, the anchor will not contain text content.
184
+ * @returns {HTMLElement|null} - The newly created anchor element, or `null` if the URL is empty.
185
+ */
139
186
  create(notText) {
140
187
  if (this.linkValue.length === 0) return null;
141
188
 
142
189
  const url = this.linkValue;
143
190
  const displayText = this.displayInput.value.length === 0 ? url : this.displayInput.value;
144
191
 
145
- const oA = this.currentTarget || domUtils.createElement('A');
192
+ const oA = /** @type {HTMLAnchorElement} */ (this.currentTarget || dom.utils.createElement('A'));
146
193
  this._updateAnchor(oA, url, displayText, this.titleInput.value, notText);
147
194
  this.linkValue = this.preview.textContent = this.urlInput.value = this.displayInput.value = '';
148
195
 
149
196
  return oA;
150
- },
197
+ }
151
198
 
199
+ /**
200
+ * @description Resets the ModalAnchorEditor to its initial state.
201
+ */
152
202
  init() {
153
203
  this.currentTarget = null;
154
204
  this.linkValue = this.preview.textContent = this.urlInput.value = '';
@@ -157,8 +207,17 @@ ModalAnchorEditor.prototype = {
157
207
  this.downloadCheck.checked = false;
158
208
  this._change = false;
159
209
  this._setRel(this.defaultRel.default || '');
160
- },
210
+ }
161
211
 
212
+ /**
213
+ * @private
214
+ * @description Updates the anchor element with new attributes.
215
+ * @param {HTMLAnchorElement} anchor - The anchor (`<a>`) element to update.
216
+ * @param {string} url - The URL for the anchor's `href` attribute.
217
+ * @param {string} displayText - The text to be displayed inside the anchor.
218
+ * @param {string} title - The tooltip text (title attribute).
219
+ * @param {boolean} notText - If `true`, the anchor will not contain text content.
220
+ */
162
221
  _updateAnchor(anchor, url, displayText, title, notText) {
163
222
  // download
164
223
  if (!this._selfPathBookmark(url) && this.downloadCheck.checked) {
@@ -186,13 +245,24 @@ ModalAnchorEditor.prototype = {
186
245
  } else {
187
246
  anchor.textContent = displayText;
188
247
  }
189
- },
248
+ }
190
249
 
250
+ /**
251
+ * @private
252
+ * @description Checks if the given path is an internal bookmark.
253
+ * @param {string} path - The URL or anchor link.
254
+ * @returns {boolean} - `true` if the path is an internal bookmark, otherwise `false`.
255
+ */
191
256
  _selfPathBookmark(path) {
192
257
  const href = this._w.location.href.replace(/\/$/, '');
193
- return path.indexOf('#') === 0 || (path.indexOf(href) === 0 && path.indexOf('#') === (!href.includes('#') ? href.length : href.substr(0, href.indexOf('#')).length));
194
- },
258
+ return path.indexOf('#') === 0 || (path.indexOf(href) === 0 && path.indexOf('#') === (!href.includes('#') ? href.length : href.substring(0, href.indexOf('#')).length));
259
+ }
195
260
 
261
+ /**
262
+ * @private
263
+ * @description Updates the `rel` attribute list in the modal and preview.
264
+ * @param {string} relAttr - The `rel` attribute string to set.
265
+ */
196
266
  _setRel(relAttr) {
197
267
  if (!this._isRel) return;
198
268
 
@@ -201,22 +271,27 @@ ModalAnchorEditor.prototype = {
201
271
  for (let i = 0, len = checkedRel.length, cmd; i < len; i++) {
202
272
  cmd = checkedRel[i].getAttribute('data-command');
203
273
  if (rels.includes(cmd)) {
204
- domUtils.addClass(checkedRel[i], 'se-checked');
274
+ dom.utils.addClass(checkedRel[i], 'se-checked');
205
275
  } else {
206
- domUtils.removeClass(checkedRel[i], 'se-checked');
276
+ dom.utils.removeClass(checkedRel[i], 'se-checked');
207
277
  }
208
278
  }
209
279
 
210
280
  this.relPreview.title = this.relPreview.textContent = rels.join(' ');
211
281
  if (rels.length > 0) {
212
- domUtils.addClass(this.relButton, 'on');
282
+ dom.utils.addClass(this.relButton, 'on');
213
283
  } else {
214
- domUtils.removeClass(this.relButton, 'on');
284
+ dom.utils.removeClass(this.relButton, 'on');
215
285
  }
216
- },
286
+ }
217
287
 
218
- _createHeaderList(urlValue) {
219
- const headers = domUtils.getListChildren(this.editor.frameContext.get('wysiwyg'), (current) => /h[1-6]/i.test(current.nodeName));
288
+ /**
289
+ * @private
290
+ * @description Generates a list of bookmark headers within the editor.
291
+ * @param {string} urlValue - The current URL input value.
292
+ */
293
+ _createBookmarkList(urlValue) {
294
+ const headers = dom.query.getListChildren(this.editor.frameContext.get('wysiwyg'), (current) => /h[1-6]/i.test(current.nodeName) || (dom.check.isAnchor(current) && !!current.id));
220
295
  if (headers.length === 0) return;
221
296
 
222
297
  const valueRegExp = new RegExp(`^${urlValue.replace(/^#/, '')}`, 'i');
@@ -226,7 +301,7 @@ ModalAnchorEditor.prototype = {
226
301
  v = headers[i];
227
302
  if (!valueRegExp.test(v.textContent)) continue;
228
303
  list.push(v);
229
- menus.push('<div style="' + v.style.cssText + '">' + v.textContent + '</div>');
304
+ menus.push(dom.check.isAnchor(v) ? `<div><span class="se-text-prefix-icon">${this.icons.bookmark_anchor}</span>${v.id}</div>` : `<div style="${v.style.cssText}">${v.textContent}</div>`);
230
305
  }
231
306
 
232
307
  if (list.length === 0) {
@@ -235,14 +310,19 @@ ModalAnchorEditor.prototype = {
235
310
  this.selectMenu_bookmark.create(list, menus);
236
311
  this.selectMenu_bookmark.open(this.options.get('_rtl') ? 'bottom-right' : '');
237
312
  }
238
- },
313
+ }
239
314
 
315
+ /**
316
+ * @private
317
+ * @description Updates the preview of the anchor link.
318
+ * @param {string} value - The current URL value.
319
+ */
240
320
  _setLinkPreview(value) {
241
321
  const preview = this.preview;
242
322
  const protocol = this.options.get('defaultUrlProtocol');
243
323
  const noPrefix = this.noAutoPrefix;
244
324
  const reservedProtocol = /^(mailto:|tel:|sms:|https*:\/\/|#)/.test(value) || value.indexOf(protocol) === 0;
245
- const sameProtocol = !protocol ? false : RegExp('^' + unicode.escapeStringRegexp(value.substr(0, protocol.length))).test(protocol);
325
+ const sameProtocol = !protocol ? false : RegExp('^' + unicode.escapeStringRegexp(value.substring(0, protocol.length))).test(protocol);
246
326
 
247
327
  value =
248
328
  this.linkValue =
@@ -251,10 +331,10 @@ ModalAnchorEditor.prototype = {
251
331
 
252
332
  if (this._selfPathBookmark(value)) {
253
333
  this.bookmark.style.display = 'block';
254
- domUtils.addClass(this.bookmarkButton, 'active');
334
+ dom.utils.addClass(this.bookmarkButton, 'active');
255
335
  } else {
256
336
  this.bookmark.style.display = 'none';
257
- domUtils.removeClass(this.bookmarkButton, 'active');
337
+ dom.utils.removeClass(this.bookmarkButton, 'active');
258
338
  }
259
339
 
260
340
  if (!this._selfPathBookmark(value) && this.downloadCheck.checked) {
@@ -262,8 +342,14 @@ ModalAnchorEditor.prototype = {
262
342
  } else {
263
343
  this.download.style.display = 'none';
264
344
  }
265
- },
345
+ }
266
346
 
347
+ /**
348
+ * @private
349
+ * @description Merges the given `rel` attribute value with the current list.
350
+ * @param {string} relAttr - The `rel` attribute to merge.
351
+ * @returns {string} - The updated `rel` attribute string.
352
+ */
267
353
  _relMerge(relAttr) {
268
354
  const current = this.currentRel;
269
355
  if (!relAttr) return current.join(' ');
@@ -280,8 +366,14 @@ ModalAnchorEditor.prototype = {
280
366
  }
281
367
 
282
368
  return current.join(' ');
283
- },
369
+ }
284
370
 
371
+ /**
372
+ * @private
373
+ * @description Removes the specified `rel` attribute from the current list.
374
+ * @param {string} relAttr - The `rel` attribute to remove.
375
+ * @returns {string} - The updated `rel` attribute string.
376
+ */
285
377
  _relDelete(relAttr) {
286
378
  if (!relAttr) return this.currentRel.join(' ');
287
379
  if (/^only:/.test(relAttr)) relAttr = relAttr.replace(/^only:/, '').trim();
@@ -289,24 +381,39 @@ ModalAnchorEditor.prototype = {
289
381
  const rels = this.currentRel.join(' ').replace(RegExp(relAttr + '\\s*'), '');
290
382
  this.currentRel = rels.split(' ');
291
383
  return rels;
292
- },
384
+ }
293
385
 
386
+ /**
387
+ * @private
388
+ * @description Registers a newly uploaded file and sets its URL in the modal form.
389
+ * @param {Object<string, *>} response - The response object from the file upload request.
390
+ */
294
391
  _register(response) {
295
392
  const file = response.result[0];
296
393
  this.linkValue = this.preview.textContent = this.urlInput.value = file.url;
297
394
  this.displayInput.value = file.name;
298
395
  this.downloadCheck.checked = true;
299
396
  this.download.style.display = 'block';
300
- },
397
+ }
301
398
 
399
+ /**
400
+ * @private
401
+ * @description Handles file upload errors.
402
+ * @param {Object<string, *>} response - The error response object.
403
+ * @returns {Promise<void>}
404
+ */
302
405
  async _error(response) {
303
406
  const message = await this.triggerEvent('onFileUploadError', { error: response });
304
407
  if (message === false) return;
305
408
  const err = message === NO_EVENT ? response.errorMessage : message || response.errorMessage;
306
- this.notice.open(err);
409
+ this.ui.noticeOpen(err);
307
410
  console.error('[SUNEDITOR.plugin.fileUpload.error]', err);
308
- },
411
+ }
309
412
 
413
+ /**
414
+ * @description Handles the callback after a file upload completes.
415
+ * @param {XMLHttpRequest} xmlHttp - The XMLHttpRequest object containing the response.
416
+ */
310
417
  _uploadCallBack(xmlHttp) {
311
418
  const response = JSON.parse(xmlHttp.responseText);
312
419
  if (response.errorMessage) {
@@ -314,127 +421,170 @@ ModalAnchorEditor.prototype = {
314
421
  } else {
315
422
  this._register(response);
316
423
  }
317
- },
318
-
319
- constructor: ModalAnchorEditor
320
- };
321
-
322
- async function OnChangeFile(e) {
323
- const files = e.target.files;
324
- if (!files[0]) return;
325
-
326
- const fileInfo = {
327
- url: this.uploadUrl,
328
- uploadHeaders: this.uploadHeaders,
329
- files
330
- };
331
-
332
- const handler = async function (infos, newInfos) {
333
- infos = newInfos || infos;
334
- const xmlHttp = await this.fileManager.asyncUpload(infos.url, infos.uploadHeaders, infos.files);
335
- this._uploadCallBack(xmlHttp);
336
- }.bind(this, fileInfo);
337
-
338
- const result = await this.triggerEvent('onFileUploadBefore', {
339
- ...fileInfo,
340
- handler
341
- });
342
-
343
- if (result === undefined) return true;
344
- if (result === false) return false;
345
- if (result !== null && typeof result === 'object') handler(result);
424
+ }
346
425
 
347
- if (result === true || result === NO_EVENT) handler(null);
348
- }
426
+ /**
427
+ * @description Handles file input change events.
428
+ * @param {InputEvent} e - The change event object.
429
+ */
430
+ async #OnChangeFile(e) {
431
+ /** @type {HTMLInputElement} */
432
+ const eventTarget = dom.query.getEventTarget(e);
433
+ const files = eventTarget.files;
434
+ if (!files[0]) return;
435
+
436
+ const fileInfo = {
437
+ url: this.uploadUrl,
438
+ uploadHeaders: this.uploadHeaders,
439
+ files
440
+ };
441
+
442
+ const handler = async function (infos, newInfos) {
443
+ infos = newInfos || infos;
444
+ const xmlHttp = await this.fileManager.asyncUpload(infos.url, infos.uploadHeaders, infos.files);
445
+ this._uploadCallBack(xmlHttp);
446
+ }.bind(this, fileInfo);
447
+ // se-ts-ignore
448
+ void this._uploadCallBack;
449
+
450
+ const result = await this.triggerEvent('onFileUploadBefore', {
451
+ info: fileInfo,
452
+ handler
453
+ });
349
454
 
350
- function OnClick_relbutton() {
351
- this.selectMenu_rel.open(this.options.get('_rtl') ? 'left-middle' : '');
352
- }
455
+ if (result === undefined) return true;
456
+ if (result === false) return false;
457
+ if (result !== null && typeof result === 'object') handler(result);
353
458
 
354
- function SetHeaderBookmark(item) {
355
- const id = item.id || 'h_' + Math.random().toString().replace(/.+\./, '');
356
- item.id = id;
357
- this.urlInput.value = '#' + id;
459
+ if (result === true || result === NO_EVENT) handler(null);
460
+ }
358
461
 
359
- this._setLinkPreview(this.urlInput.value);
360
- this.selectMenu_bookmark.close();
361
- this.urlInput.focus();
362
- }
462
+ /**
463
+ * @description Opens the `rel` attribute selection menu.
464
+ */
465
+ #OnClick_relbutton() {
466
+ this.selectMenu_rel.open(this.options.get('_rtl') ? 'left-middle' : '');
467
+ }
363
468
 
364
- function SetRelItem(item) {
365
- const cmd = item.getAttribute('data-command');
366
- if (!cmd) return;
469
+ /**
470
+ * @description Sets the selected bookmark as the URL.
471
+ * @param {HTMLElement} item - The selected bookmark element.
472
+ */
473
+ #SetHeaderBookmark(item) {
474
+ const id = item.id || 'h_' + Math.random().toString().replace(/.+\./, '');
475
+ item.id = id;
476
+ this.urlInput.value = '#' + id;
477
+
478
+ this._setLinkPreview(this.urlInput.value);
479
+ this.selectMenu_bookmark.close();
480
+ this.urlInput.focus();
481
+ }
367
482
 
368
- const current = this.currentRel;
369
- const index = current.indexOf(cmd);
370
- if (index === -1) current.push(cmd);
371
- else current.splice(index, 1);
483
+ /**
484
+ * @param {HTMLElement} item - The selected `rel` attribute element.
485
+ */
486
+ #SetRelItem(item) {
487
+ const cmd = item.getAttribute('data-command');
488
+ if (!cmd) return;
372
489
 
373
- this.relPreview.title = this.relPreview.textContent = current.join(', ');
374
- }
490
+ const current = this.currentRel;
491
+ const index = current.indexOf(cmd);
492
+ if (index === -1) current.push(cmd);
493
+ else current.splice(index, 1);
375
494
 
376
- function OnChange_displayInput(e) {
377
- this._change = !!e.target.value.trim();
378
- }
495
+ this.relPreview.title = this.relPreview.textContent = current.join(', ');
496
+ }
379
497
 
380
- function OnChange_urlInput(e) {
381
- const value = e.target.value.trim();
382
- this._setLinkPreview(value);
383
- if (this._selfPathBookmark(value)) this._createHeaderList(value);
384
- else this.selectMenu_bookmark.close();
385
- }
498
+ /**
499
+ * @param {InputEvent} e - Event object
500
+ */
501
+ #OnChange_displayInput(e) {
502
+ /** @type {HTMLInputElement} */
503
+ const eventTarget = dom.query.getEventTarget(e);
504
+ this._change = !!eventTarget.value.trim();
505
+ }
386
506
 
387
- function OnFocus_urlInput() {
388
- const value = this.urlInput.value;
389
- if (this._selfPathBookmark(value)) this._createHeaderList(value);
390
- }
507
+ /**
508
+ * @param {InputEvent} e - Event object
509
+ */
510
+ #OnChange_urlInput(e) {
511
+ /** @type {HTMLInputElement} */
512
+ const eventTarget = dom.query.getEventTarget(e);
513
+ const value = eventTarget.value.trim();
514
+ this._setLinkPreview(value);
515
+ if (this._selfPathBookmark(value)) this._createBookmarkList(value);
516
+ else this.selectMenu_bookmark.close();
517
+ }
391
518
 
392
- function OnClick_bookmarkButton() {
393
- let url = this.urlInput.value;
394
- if (this._selfPathBookmark(url)) {
395
- url = url.substr(1);
396
- this.bookmark.style.display = 'none';
397
- domUtils.removeClass(this.bookmarkButton, 'active');
398
- } else {
399
- url = '#' + url;
400
- this.bookmark.style.display = 'block';
401
- domUtils.addClass(this.bookmarkButton, 'active');
402
- this.downloadCheck.checked = false;
403
- this.download.style.display = 'none';
404
- this._createHeaderList(url);
519
+ #OnFocus_urlInput() {
520
+ const value = this.urlInput.value;
521
+ if (this._selfPathBookmark(value)) this._createBookmarkList(value);
405
522
  }
406
523
 
407
- this.urlInput.value = url;
408
- this._setLinkPreview(url);
409
- this.urlInput.focus();
410
- }
524
+ #OnClick_bookmarkButton() {
525
+ let url = this.urlInput.value;
526
+ if (this._selfPathBookmark(url)) {
527
+ url = url.substring(1);
528
+ this.bookmark.style.display = 'none';
529
+ dom.utils.removeClass(this.bookmarkButton, 'active');
530
+ } else {
531
+ url = '#' + url;
532
+ this.bookmark.style.display = 'block';
533
+ dom.utils.addClass(this.bookmarkButton, 'active');
534
+ this.downloadCheck.checked = false;
535
+ this.download.style.display = 'none';
536
+ this._createBookmarkList(url);
537
+ }
411
538
 
412
- function OnChange_newWindowCheck(e) {
413
- if (typeof this.defaultRel.check_new_window !== 'string') return;
414
- if (e.target.checked) {
415
- this._setRel(this._relMerge(this.defaultRel.check_new_window));
416
- } else {
417
- this._setRel(this._relDelete(this.defaultRel.check_new_window));
539
+ this.urlInput.value = url;
540
+ this._setLinkPreview(url);
541
+ this.urlInput.focus();
418
542
  }
419
- }
420
543
 
421
- function OnChange_downloadCheck(e) {
422
- if (e.target.checked) {
423
- this.download.style.display = 'block';
424
- this.bookmark.style.display = 'none';
425
- domUtils.removeClass(this.bookmarkButton, 'active');
426
- this.linkValue = this.preview.textContent = this.urlInput.value = this.urlInput.value.replace(/^#+/, '');
427
- if (typeof this.defaultRel.check_bookmark === 'string') {
428
- this._setRel(this._relMerge(this.defaultRel.check_bookmark));
544
+ /**
545
+ * @param {InputEvent} e - Event object
546
+ */
547
+ #OnChange_newWindowCheck(e) {
548
+ if (typeof this.defaultRel.check_new_window !== 'string') return;
549
+ /** @type {HTMLInputElement} */
550
+ const eventTarget = dom.query.getEventTarget(e);
551
+ if (eventTarget.checked) {
552
+ this._setRel(this._relMerge(this.defaultRel.check_new_window));
553
+ } else {
554
+ this._setRel(this._relDelete(this.defaultRel.check_new_window));
429
555
  }
430
- } else {
431
- this.download.style.display = 'none';
432
- if (typeof this.defaultRel.check_bookmark === 'string') {
433
- this._setRel(this._relDelete(this.defaultRel.check_bookmark));
556
+ }
557
+
558
+ /**
559
+ * @param {InputEvent} e - Event object
560
+ */
561
+ #OnChange_downloadCheck(e) {
562
+ /** @type {HTMLInputElement} */
563
+ const eventTarget = dom.query.getEventTarget(e);
564
+ if (eventTarget.checked) {
565
+ this.download.style.display = 'block';
566
+ this.bookmark.style.display = 'none';
567
+ dom.utils.removeClass(this.bookmarkButton, 'active');
568
+ this.linkValue = this.preview.textContent = this.urlInput.value = this.urlInput.value.replace(/^#+/, '');
569
+ if (typeof this.defaultRel.check_bookmark === 'string') {
570
+ this._setRel(this._relMerge(this.defaultRel.check_bookmark));
571
+ }
572
+ } else {
573
+ this.download.style.display = 'none';
574
+ if (typeof this.defaultRel.check_bookmark === 'string') {
575
+ this._setRel(this._relDelete(this.defaultRel.check_bookmark));
576
+ }
434
577
  }
435
578
  }
436
579
  }
437
580
 
581
+ /**
582
+ * @private
583
+ * @param {__se__EditorCore} editor - Editor instance
584
+ * @param {ModalAnchorEditorParams} params - ModalAnchorEditor options
585
+ * @param {Array<string>} relList - REL attribute list
586
+ * @returns {HTMLElement} - Modal form element
587
+ */
438
588
  function CreatetModalForm(editor, params, relList) {
439
589
  const lang = editor.lang;
440
590
  const icons = editor.icons;
@@ -488,7 +638,7 @@ function CreatetModalForm(editor, params, relList) {
488
638
 
489
639
  html += '</div></div>';
490
640
 
491
- return domUtils.createElement('DIV', null, html);
641
+ return dom.utils.createElement('DIV', null, html);
492
642
  }
493
643
 
494
644
  export default ModalAnchorEditor;