chuijs 3.6.2 → 3.6.4

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 (119) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +1203 -162
  3. package/framework/appLayout/default/chui_app_layout.js +747 -747
  4. package/framework/appLayout/default/global_style.css +592 -568
  5. package/framework/appLayout/default/main_theme_style.css +118 -101
  6. package/framework/components/chui_accordion/accordion.js +63 -63
  7. package/framework/components/chui_accordion/styles.css +79 -75
  8. package/framework/components/chui_badge/badge.js +55 -55
  9. package/framework/components/chui_badge/styles.css +29 -29
  10. package/framework/components/chui_button/button.js +48 -48
  11. package/framework/components/chui_button/styles.css +75 -70
  12. package/framework/components/chui_calendar/calendar.js +97 -97
  13. package/framework/components/chui_card/card.js +87 -0
  14. package/framework/components/chui_card/styles.css +72 -0
  15. package/framework/components/chui_code/code.js +18 -18
  16. package/framework/components/chui_code/styles.css +9 -9
  17. package/framework/components/chui_console/console.js +27 -27
  18. package/framework/components/chui_console/styles.css +31 -31
  19. package/framework/components/chui_content_block/content_block.js +51 -51
  20. package/framework/components/chui_content_block/styles.css +2 -2
  21. package/framework/components/chui_context_menu/context_menu.js +230 -0
  22. package/framework/components/chui_context_menu/styles.css +136 -0
  23. package/framework/components/chui_custom_element/custom_element.js +24 -24
  24. package/framework/components/chui_details/details.js +85 -85
  25. package/framework/components/chui_details/styles.css +70 -66
  26. package/framework/components/chui_fieldset/fieldset.js +40 -40
  27. package/framework/components/chui_fieldset/styles.css +24 -24
  28. package/framework/components/chui_form/form.js +40 -40
  29. package/framework/components/chui_form/styles.css +21 -21
  30. package/framework/components/chui_graphs/graphs.js +234 -190
  31. package/framework/components/chui_graphs/styles.css +37 -32
  32. package/framework/components/chui_hero/hero.js +98 -0
  33. package/framework/components/chui_hero/styles.css +91 -0
  34. package/framework/components/chui_html_block/html_block.js +16 -16
  35. package/framework/components/chui_html_block/styles.css +5 -5
  36. package/framework/components/chui_hx/hx.js +15 -15
  37. package/framework/components/chui_hx/styles.css +38 -38
  38. package/framework/components/chui_icons/icons.js +2144 -2144
  39. package/framework/components/chui_icons/styles.css +13 -13
  40. package/framework/components/chui_inputs/chui_check_box/check_box.js +32 -32
  41. package/framework/components/chui_inputs/chui_check_box/styles.css +91 -86
  42. package/framework/components/chui_inputs/chui_combo_box/combo_box.js +166 -150
  43. package/framework/components/chui_inputs/chui_combo_box/styles.css +113 -107
  44. package/framework/components/chui_inputs/chui_date/date.js +177 -174
  45. package/framework/components/chui_inputs/chui_date/styles.css +163 -128
  46. package/framework/components/chui_inputs/chui_email/email.js +61 -61
  47. package/framework/components/chui_inputs/chui_email/styles.css +69 -71
  48. package/framework/components/chui_inputs/chui_file/file.js +76 -76
  49. package/framework/components/chui_inputs/chui_file/styles.css +99 -99
  50. package/framework/components/chui_inputs/chui_multi_combo_box/multi_combo_box.js +295 -295
  51. package/framework/components/chui_inputs/chui_multi_combo_box/styles.css +212 -235
  52. package/framework/components/chui_inputs/chui_number/number.js +108 -108
  53. package/framework/components/chui_inputs/chui_number/styles.css +84 -84
  54. package/framework/components/chui_inputs/chui_password/password.js +99 -99
  55. package/framework/components/chui_inputs/chui_password/styles.css +97 -97
  56. package/framework/components/chui_inputs/chui_radio_button/radio_button.js +45 -45
  57. package/framework/components/chui_inputs/chui_radio_button/styles.css +76 -73
  58. package/framework/components/chui_inputs/chui_select_box/select_box.js +187 -170
  59. package/framework/components/chui_inputs/chui_select_box/styles.css +123 -117
  60. package/framework/components/chui_inputs/chui_text/styles.css +83 -84
  61. package/framework/components/chui_inputs/chui_text/text.js +91 -91
  62. package/framework/components/chui_inputs/chui_text_area/styles.css +57 -57
  63. package/framework/components/chui_inputs/chui_text_area/text_area.js +61 -61
  64. package/framework/components/chui_inputs/chui_toggle/styles.css +66 -61
  65. package/framework/components/chui_inputs/chui_toggle/toggle.js +36 -36
  66. package/framework/components/chui_label/label.js +54 -54
  67. package/framework/components/chui_label/styles.css +11 -11
  68. package/framework/components/chui_media/audio.js +908 -908
  69. package/framework/components/chui_media/audio_styles.css +458 -458
  70. package/framework/components/chui_media/image.js +105 -105
  71. package/framework/components/chui_media/image_styles.css +61 -61
  72. package/framework/components/chui_media/video.js +248 -248
  73. package/framework/components/chui_media/video_styles.css +160 -160
  74. package/framework/components/chui_menu_bar/menu_bar.js +66 -74
  75. package/framework/components/chui_menu_bar/styles.css +114 -76
  76. package/framework/components/chui_modal/modal.js +142 -135
  77. package/framework/components/chui_modal/styles.css +36 -36
  78. package/framework/components/chui_notification/notification.js +72 -72
  79. package/framework/components/chui_notification/notification_download.js +78 -78
  80. package/framework/components/chui_notification/notification_download_progress.css +119 -123
  81. package/framework/components/chui_notification/notification_download_progress.js +105 -105
  82. package/framework/components/chui_notification/notification_update.js +54 -54
  83. package/framework/components/chui_notification/styles.css +91 -91
  84. package/framework/components/chui_notification/styles_download.css +85 -85
  85. package/framework/components/chui_notification/styles_update.css +73 -73
  86. package/framework/components/chui_paragraph/paragraph.js +14 -14
  87. package/framework/components/chui_paragraph/styles.css +6 -6
  88. package/framework/components/chui_popups/popups.js +250 -250
  89. package/framework/components/chui_popups/styles.css +129 -115
  90. package/framework/components/chui_progress_bar/progress_bar.js +28 -28
  91. package/framework/components/chui_progress_bar/styles.css +28 -28
  92. package/framework/components/chui_radio_group/radio_group.js +57 -57
  93. package/framework/components/chui_radio_group/styles.css +3 -3
  94. package/framework/components/chui_slideshow/slideshow.js +75 -75
  95. package/framework/components/chui_slideshow/styles.css +94 -85
  96. package/framework/components/chui_spinner/spinner.js +45 -45
  97. package/framework/components/chui_spinner/styles.css +23 -23
  98. package/framework/components/chui_table/styles.css +42 -42
  99. package/framework/components/chui_table/table.js +234 -234
  100. package/framework/components/chui_tabs/chui_tabs.js +77 -77
  101. package/framework/components/chui_tabs/styles.css +54 -48
  102. package/framework/components/chui_text_editor/styles.css +217 -217
  103. package/framework/components/chui_text_editor/text_editor.js +144 -144
  104. package/framework/components/chui_text_editor/text_editor_panel.js +568 -568
  105. package/framework/components/chui_tree_view/styles.css +81 -75
  106. package/framework/components/chui_tree_view/tree_view.js +90 -90
  107. package/framework/components/chui_webview/styles.css +27 -27
  108. package/framework/components/chui_webview/webview.js +103 -103
  109. package/framework/components/telegram_bot/chui_telegram_bot.js +183 -183
  110. package/framework/modules/chui_animations/animations.js +121 -121
  111. package/framework/modules/chui_animations/styles.css +79 -79
  112. package/framework/modules/chui_fonts.js +7129 -6974
  113. package/framework/modules/chui_functions.js +106 -78
  114. package/framework/modules/chui_logger/chui_logger.js +53 -53
  115. package/framework/modules/chui_page/page.js +86 -86
  116. package/framework/modules/chui_page/styles.css +9 -9
  117. package/framework/tray_bar/chui_menu_items.js +48 -48
  118. package/index.js +570 -555
  119. package/package.json +51 -46
@@ -1,569 +1,569 @@
1
- const {Icon, Icons} = require("../chui_icons/icons");
2
- const {Animation} = require("../../modules/chui_animations/animations");
3
- const {Dialog} = require("../chui_modal/modal");
4
- const {Button} = require("../chui_button/button");
5
- const {TextInput} = require("../chui_inputs/chui_text/text");
6
- const {Label} = require("../chui_label/label");
7
- const {ContentBlock} = require("../chui_content_block/content_block");
8
- const {Notification} = require("../chui_notification/notification");
9
- const {NumberInput} = require("../chui_inputs/chui_number/number");
10
- const {CheckBox} = require("../chui_inputs/chui_check_box/check_box");
11
- const {FileInput, AcceptTypes} = require("../chui_inputs/chui_file/file");
12
-
13
-
14
-
15
- class Commands {
16
- static COPY = "copy"
17
- static CUT = "cut"
18
- static PASTE = "paste"
19
- static DELETE = "delete"
20
- static UNDO = "undo"
21
- static REDO = "redo"
22
- //
23
- static BOLD = "bold"
24
- static ITALIC = "italic"
25
- static STRIKE_THROUGH = "strikeThrough"
26
- static UNDERLINE = "underline"
27
- //
28
- static REMOVE_FORMAT = "removeFormat"
29
- //
30
- static SUPER_SCRIPT = "superscript"
31
- static SUB_SCRIPT = "subscript"
32
- //
33
- static JUSTIFY_LEFT = "justifyLeft"
34
- static JUSTIFY_RIGHT = "justifyRight"
35
- static JUSTIFY_CENTER = "justifyCenter"
36
- static JUSTIFY_FULL = "justifyFull"
37
- //
38
- static FORMAT_BLOCK = "formatBlock"
39
- static NONE = "none"
40
- // ITEMS
41
- static CREATE_LINK = "createLink"
42
- static UNLINK = "unlink"
43
- static INSERT_IMAGE = "insertImage"
44
- static INSERT_LINE_BREAK = "insertLineBreak"
45
- static INSERT_HTML = "insertHTML"
46
- // LIST
47
- static INSERT_ORDERED_LIST = "insertOrderedList"
48
- static INSERT_UNORDERED_LIST = "insertUnorderedList"
49
- }
50
-
51
- class TextEditorButtons {
52
- #button = undefined;
53
- constructor(options = { icon: undefined, command: undefined, value: undefined, disableFocus: false, listener: () => {} }) {
54
- this.#button = document.createElement('chui_button_format');
55
- this.#button.innerHTML = new Icon(options.icon).getHTML();
56
- if (options.disableFocus) {
57
- this.#button.addEventListener("mousedown", () => {
58
- return false
59
- })
60
- }
61
- if (options.listener !== undefined) {
62
- this.#button.addEventListener("click", options.listener)
63
- } else {
64
- this.#button.addEventListener("click", () => {
65
- if (options.value !== undefined) {
66
- document.execCommand(options.command, false, options.value);
67
- } else {
68
- document.execCommand(options.command, false);
69
- }
70
- })
71
- }
72
- }
73
- set() {
74
- return this.#button;
75
- }
76
- }
77
-
78
- class TextEditorSelects {
79
- #id = require("randomstring").generate();
80
- #id_sb = require("randomstring").generate();
81
- #Select_main = document.createElement('chui_text_editor_select_box');
82
- #Select_second = document.createElement('text_editor_select_box');
83
- #input = document.createElement('input');
84
- #div_value = document.createElement("text_editor_div_value")
85
- #button_open = document.createElement('text_editor_select_button_open');
86
- #dropdown = document.createElement('text_editor_selectbox_dropdown');
87
- constructor(options = { icon: String() }) {
88
- if (options.icon !== undefined) {
89
- this.#div_value.innerHTML = options.icon;
90
- }
91
- this.#input.setAttribute('id', this.#id_sb);
92
- this.#input.classList.add('text_editor_selectbox_input');
93
- this.#input.type = 'text';
94
- this.#input.disabled = true
95
- this.#input.style.display = 'none'
96
- this.#button_open.innerHTML = new Icon(Icons.HARDWARE.KEYBOARD_ARROW_DOWN, undefined, "var(--blue_prime_background)").getHTML();
97
- this.#dropdown.setAttribute('id', this.#id);
98
- this.#Select_second.appendChild(this.#input)
99
- this.#Select_second.appendChild(this.#div_value)
100
- this.#Select_second.appendChild(this.#button_open)
101
- this.#Select_second.appendChild(this.#dropdown)
102
- //LISTENERS
103
- this.#Select_second.addEventListener('click', (event) => {
104
- if (event.target.parentNode === this.#Select_second) {
105
- this.#input.focus()
106
- new Animation(this.#dropdown).fadeIn();
107
- TextEditorSelects.#setOptionDisplay(document.getElementById(this.#id));
108
- }
109
- });
110
- window.addEventListener('click', (event) => {
111
- if (event.target.parentNode !== this.#Select_second) {
112
- new Animation(this.#dropdown).fadeOut();
113
- }
114
- });
115
- this.#input.addEventListener('input', (event) => {
116
- let dropdown = document.getElementById(this.#id);
117
- for (let option of dropdown.childNodes) {
118
- if (!option.getAttribute('option_value').includes(event.target.value)) {
119
- option.style.display = 'none'
120
- } else {
121
- option.style.display = 'block'
122
- }
123
- }
124
- });
125
- this.#Select_main.appendChild(this.#Select_second)
126
- }
127
- addOptionsFontSize(...options) {
128
- for (let opt of options) {
129
- let option = document.createElement(`text_editor_selectbox_option`);
130
- let fontSize = document.createElement("font");
131
- fontSize.setAttribute("size", opt.value)
132
- fontSize.innerHTML = opt.name;
133
- option.setAttribute('option_value', opt.value);
134
- option.addEventListener('click', () => {
135
- this.#input.value = option.getAttribute('option_value');
136
- this.#input.setAttribute('value', option.getAttribute('option_value'));
137
- });
138
- option.appendChild(fontSize)
139
- this.#dropdown.appendChild(option);
140
- }
141
- }
142
- addOptionsHeader(...options) {
143
- for (let opt of options) {
144
- let option = document.createElement(`text_editor_selectbox_option`);
145
- let header = document.createElement(`${opt.value.replace("<", "").replace(">", "")}`);
146
- header.innerHTML = opt.name;
147
- header.style.padding = '0px';
148
- header.style.margin = '0px';
149
- option.setAttribute('option_value', opt.value);
150
- option.addEventListener('click', () => {
151
- this.#input.value = option.getAttribute('option_value');
152
- this.#input.setAttribute('value', option.getAttribute('option_value'));
153
- });
154
- option.appendChild(header)
155
- this.#dropdown.appendChild(option);
156
- }
157
- }
158
- addValueChangeListener(listener = () => {}) {
159
- let observer = new MutationObserver((mutations) => {
160
- mutations.forEach(listener);
161
- });
162
- observer.observe(this.#input, {
163
- attributes: true,
164
- childList: false,
165
- subtree: false,
166
- characterData: false,
167
- attributeFilter: ['value']
168
- });
169
- }
170
- set() {
171
- return this.#Select_main;
172
- }
173
- static #setOptionDisplay(element = new HTMLElement()) {
174
- for (let option of element.childNodes) { option.style.display = 'block'; }
175
- }
176
- }
177
-
178
- class TextEditorPanel {
179
- #panel = document.createElement("text_editor_panel")
180
- constructor(text_editor_id = String(), controls = { UNDO_REDO: Boolean() }) {
181
- // Управление
182
- if (controls.UNDO_REDO) {
183
- let button_undo = new TextEditorButtons({
184
- icon: Icons.CONTENT.UNDO,
185
- command: Commands.UNDO
186
- })
187
- let button_redo = new TextEditorButtons({
188
- icon: Icons.CONTENT.REDO,
189
- command: Commands.REDO
190
- })
191
- this.#addBlock(button_undo, button_redo)
192
- }
193
- // formatBlock
194
- if (controls.BLOCK_FORMAT) {
195
- let select_headers = new TextEditorSelects({ icon: new Icon(Icons.EDITOR.TITLE).getHTML() })
196
- select_headers.addOptionsHeader(
197
- { name: "H1", value: "<h1>" },
198
- { name: "H2", value: "<h2>" },
199
- { name: "H3", value: "<h3>" },
200
- { name: "H4", value: "<h4>" },
201
- { name: "H5", value: "<h5>" },
202
- { name: "H6", value: "<h6>" },
203
- { name: "Code", value: "<pre>" },
204
- { name: "Paragraph", value: "<P>" }
205
- )
206
- select_headers.addValueChangeListener((e) => {
207
- document.execCommand('formatBlock', false, e.target.value);
208
- })
209
- this.#addBlock(select_headers)
210
- let button_format_quote = new TextEditorButtons({
211
- icon: Icons.EDITOR.FORMAT_QUOTE,
212
- command: Commands.FORMAT_BLOCK,
213
- value: "<BLOCKQUOTE>"
214
- })
215
- this.#addBlock(button_format_quote)
216
- }
217
- if (controls.FONT_SIZE) {
218
- let select_font_size = new TextEditorSelects({ icon: new Icon(Icons.EDITOR.FORMAT_SIZE).getHTML() })
219
- select_font_size.addOptionsFontSize(
220
- { name: "xx_small", value: "1" },
221
- { name: "x_small", value: "2" },
222
- { name: "small", value: "3" },
223
- { name: "medium", value: "4" },
224
- { name: "large", value: "5" },
225
- { name: "x_large", value: "6" },
226
- { name: "xx_large", value: "7" },
227
- )
228
- select_font_size.addValueChangeListener((e) => {
229
- document.execCommand('fontSize', false, e.target.value);
230
- })
231
- this.#addBlock(select_font_size)
232
- }
233
- if (controls.REMOVE_FORMAT) {
234
- let button_removeFormat = new TextEditorButtons({
235
- icon: Icons.EDITOR.FORMAT_CLEAR,
236
- command: Commands.REMOVE_FORMAT
237
- })
238
- this.#addBlock(button_removeFormat)
239
- }
240
- // FORMAT
241
- if (controls.BOLD) {
242
- let button_bold_text = new TextEditorButtons({
243
- icon: Icons.EDITOR.FORMAT_BOLD,
244
- command: Commands.BOLD
245
- })
246
- this.#addBlock(button_bold_text)
247
- }
248
- if (controls.ITALIC) {
249
- let button_italic_text = new TextEditorButtons({
250
- icon: Icons.EDITOR.FORMAT_ITALIC,
251
- command: Commands.ITALIC
252
- })
253
- this.#addBlock(button_italic_text)
254
- }
255
- if (controls.STRIKE_THROUGH) {
256
- let button_strikeThrough = new TextEditorButtons({
257
- icon: Icons.EDITOR.FORMAT_STRIKETHROUGH,
258
- command: Commands.STRIKE_THROUGH
259
- })
260
- this.#addBlock(button_strikeThrough)
261
- }
262
- if (controls.UNDERLINE) {
263
- let button_underline = new TextEditorButtons({
264
- icon: Icons.EDITOR.FORMAT_UNDERLINED,
265
- command: Commands.UNDERLINE
266
- })
267
- this.#addBlock(button_underline)
268
- }
269
- //
270
- if (controls.SUPERSCRIPT) {
271
- let button_superscript = new TextEditorButtons({
272
- icon: Icons.EDITOR.SUPERSCRIPT,
273
- command: Commands.SUPER_SCRIPT
274
- })
275
- this.#addBlock(button_superscript)
276
- }
277
- if (controls.SUBSCRIPT) {
278
- let button_subscript = new TextEditorButtons({
279
- icon: Icons.EDITOR.SUBSCRIPT,
280
- command: Commands.SUB_SCRIPT
281
- })
282
- this.#addBlock(button_subscript)
283
- }
284
- //
285
- if (controls.JUSTIFY_LEFT) {
286
- let button_justifyLeft = new TextEditorButtons({
287
- icon: Icons.EDITOR.FORMAT_ALIGN_LEFT,
288
- command: Commands.JUSTIFY_LEFT
289
- })
290
- this.#addBlock(button_justifyLeft)
291
- }
292
- if (controls.JUSTIFY_CENTER) {
293
- let button_justifyCenter = new TextEditorButtons({
294
- icon: Icons.EDITOR.FORMAT_ALIGN_CENTER,
295
- command: Commands.JUSTIFY_CENTER
296
- })
297
- this.#addBlock(button_justifyCenter)
298
- }
299
- if (controls.JUSTIFY_RIGHT) {
300
- let button_justifyRight = new TextEditorButtons({
301
- icon: Icons.EDITOR.FORMAT_ALIGN_RIGHT,
302
- command: Commands.JUSTIFY_RIGHT
303
- })
304
- this.#addBlock(button_justifyRight)
305
- }
306
- if (controls.JUSTIFY_FULL) {
307
- let button_justifyFull = new TextEditorButtons({
308
- icon: Icons.EDITOR.FORMAT_ALIGN_JUSTIFY,
309
- command: Commands.JUSTIFY_FULL
310
- })
311
- this.#addBlock(button_justifyFull)
312
- }
313
- //
314
- if (controls.LISTS) {
315
- let button_list_one = new TextEditorButtons({
316
- icon: Icons.EDITOR.FORMAT_LIST_NUMBERED,
317
- command: Commands.INSERT_ORDERED_LIST
318
- })
319
- let button_list_two = new TextEditorButtons({
320
- icon: Icons.EDITOR.FORMAT_LIST_BULLETED,
321
- command: Commands.INSERT_UNORDERED_LIST
322
- })
323
- this.#addBlock(button_list_one, button_list_two)
324
-
325
- }
326
- //
327
- // Создание ссылки
328
- if (controls.INSERT_LINK) {
329
- let button_unlink = new TextEditorButtons({
330
- icon: Icons.CONTENT.LINK_OFF,
331
- command: Commands.UNLINK
332
- })
333
- let content_link = new ContentBlock({
334
- direction: "column", wrap: "wrap", align: "center", justify: "flex-end"
335
- })
336
- content_link.setWidth("-webkit-fill-available")
337
- let content_link_header = new ContentBlock({
338
- direction: "row", wrap: "wrap", align: "center", justify: "space-between", disableMarginChild: true
339
- })
340
- content_link_header.setWidth("-webkit-fill-available")
341
- let dialog_link = new Dialog({ width: "500px", height: "max-content", closeOutSideClick: true })
342
- let input_link_text = new TextInput({ title: "Наименование", placeholder: "Наименование", width: "-webkit-fill-available", disableFocus: false })
343
- let input_link = new TextInput({ title: "Ссылка", placeholder: "https://", width: "-webkit-fill-available", value: "https://example.ru", disableFocus: false })
344
- content_link.add(input_link_text, input_link)
345
- dialog_link.addToBody(content_link)
346
- content_link_header.add(
347
- new Button({
348
- icon: Icons.NAVIGATION.CLOSE,
349
- clickEvent: () => {
350
- document.getElementById(text_editor_id).focus()
351
- dialog_link.close()
352
- }
353
- }),
354
- new Label({ text: "Добавить ссылку" }),
355
- new Button({
356
- icon: Icons.CONTENT.ADD,
357
- clickEvent: () => {
358
- document.getElementById(text_editor_id).focus()
359
- document.getSelection().removeAllRanges();
360
- document.getSelection().addRange(range_link);
361
- if (selection_link.toString() === "") document.execCommand('insertHTML', false, `<a href="${input_link.getValue()}">${input_link_text.getValue()}</a>`);
362
- else document.execCommand(Commands.CREATE_LINK, false, input_link.getValue())
363
- dialog_link.close()
364
- }
365
- }),
366
- )
367
- dialog_link.addToHeader(content_link_header)
368
- let selection_link = undefined;
369
- let range_link = undefined;
370
- let button_link = new TextEditorButtons({
371
- icon: Icons.CONTENT.LINK,
372
- disableFocus: true,
373
- listener: () => {
374
- document.getElementById(text_editor_id).focus()
375
- selection_link = document.getSelection();
376
- range_link = selection_link.getRangeAt(0)
377
- input_link_text.setValue(selection_link.toString())
378
- if (selection_link.toString() === "") input_link_text.setDisabled(false);
379
- else input_link_text.setDisabled(true);
380
- dialog_link.open()
381
- }
382
- })
383
- this.#addBlock(button_unlink, button_link, dialog_link)
384
- }
385
- // ================
386
- // Создание таблицы
387
- if (controls.INSERT_TABLE) {
388
- let content_table_header = new ContentBlock({
389
- direction: "row", wrap: "wrap", align: "center", justify: "space-between", disableMarginChild: true
390
- })
391
- content_table_header.setWidth("-webkit-fill-available")
392
- let content_table_2 = new ContentBlock({
393
- direction: "row", wrap: "wrap", align: "center", justify: "space-around"
394
- })
395
- content_table_2.setWidth("-webkit-fill-available")
396
- let content_table = new ContentBlock({
397
- direction: "row", wrap: "wrap", align: "center", justify: "space-around"
398
- })
399
- content_table.setWidth("-webkit-fill-available")
400
- let content_table_main = new ContentBlock({
401
- direction: "column", wrap: "wrap", align: "center", justify: "space-around"
402
- })
403
- content_table_main.setWidth("-webkit-fill-available")
404
- let checkBox_header = new CheckBox({ title: "Добавить THEAD" })
405
- content_table_2.add(checkBox_header)
406
- let table_rows = new NumberInput({ title:'Количество строк' });
407
- let table_cols = new NumberInput({ title:'Количество столбцов' });
408
- content_table.add(table_rows, new Label("X"), table_cols)
409
-
410
- content_table_header.add(
411
- new Button({
412
- icon: Icons.NAVIGATION.CLOSE,
413
- clickEvent: () => {
414
- dialog_table.close()
415
- }
416
- }),
417
- new Label({ text: "Добавить таблицу" }),
418
- new Button({
419
- icon: Icons.CONTENT.ADD,
420
- clickEvent: () => {
421
- let error = false;
422
- if (Number(table_rows.getValue()) === 0 && Number(table_cols.getValue()) === 0) {
423
- new Notification(`Установите количество столбцов и строк`, Notification.STYLE.ERROR).show();
424
- error = true;
425
- } else if (Number(table_cols.getValue()) === 0) {
426
- new Notification(`Установите количество столбцов`, Notification.STYLE.ERROR).show();
427
- error = true;
428
- } else if (Number(table_rows.getValue()) === 0) {
429
- new Notification(`Установите количество строк`, Notification.STYLE.ERROR).show();
430
- error = true;
431
- }
432
- if (!error) {
433
- let table = document.createElement("table")
434
- table.classList.add("text_editor_table")
435
- // шапка
436
- if (checkBox_header.getValue()) {
437
- let head_table = table.createTHead()
438
- head_table.classList.add("text_editor_table_body")
439
- let head_row = head_table.insertRow(0)
440
- head_row.classList.add("text_editor_table_row")
441
- for (let j = 0; j < table_cols.getValue(); j++) {
442
- let cell = head_row.insertCell(j)
443
- cell.classList.add("text_editor_table_cell")
444
- cell.innerText = `TH`
445
- }
446
- }
447
- // тело таблицы
448
- let body_table = table.createTBody()
449
- body_table.classList.add("text_editor_table_body")
450
- for (let i = 0; i < table_rows.getValue(); i++) {
451
- let row = body_table.insertRow(i)
452
- row.classList.add("text_editor_table_row")
453
- for (let j = 0; j < table_cols.getValue(); j++) {
454
- let cell = row.insertCell(j)
455
- cell.classList.add("text_editor_table_cell")
456
- cell.innerText = `TB`
457
- }
458
- }
459
- document.getElementById(text_editor_id).focus()
460
- document.execCommand(Commands.INSERT_HTML, false, table.outerHTML)
461
- dialog_table.close()
462
- }
463
- }
464
- })
465
- )
466
-
467
- let dialog_table = new Dialog({ width: "500px", height: "max-content", closeOutSideClick: true })
468
- dialog_table.addToHeader(content_table_header)
469
- content_table_main.add(content_table_2, content_table)
470
- dialog_table.addToBody(content_table_main)
471
- let button_table = new TextEditorButtons({
472
- icon: Icons.EDITOR.TABLE_CHART,
473
- listener: () => {
474
- document.getElementById(text_editor_id).focus()
475
- dialog_table.open()
476
- }
477
- })
478
- this.#addBlock(button_table, dialog_table)
479
- }
480
- // ================
481
- // Добавление изображения
482
- if (controls.INSERT_IMAGE) {
483
- let content_image_header = new ContentBlock({
484
- direction: "row", wrap: "wrap", align: "center", justify: "space-between", disableMarginChild: true
485
- })
486
- content_image_header.setWidth("-webkit-fill-available")
487
- let file = new FileInput({
488
- title: "Выберите изображение",
489
- multiple: false,
490
- accept: [
491
- AcceptTypes.ALL_IMAGE
492
- ]
493
- })
494
- content_image_header.add(
495
- new Button({
496
- icon: Icons.NAVIGATION.CLOSE,
497
- clickEvent: () => dialog_image.close()
498
- }),
499
- new Label({ text: "Добавить изображение" }),
500
- new Button({
501
- icon: Icons.CONTENT.ADD,
502
- clickEvent: () => {
503
- document.getElementById(text_editor_id).focus()
504
- let image = file.getFile(0)
505
- let reader = new FileReader();
506
- reader.addEventListener("load", () => {
507
- document.execCommand('insertImage', false, reader.result);
508
- }, false);
509
- if (image) reader.readAsDataURL(image);
510
- dialog_image.close()
511
- }
512
- })
513
- )
514
-
515
- let content_image = new ContentBlock({
516
- direction: "column", wrap: "wrap", align: "center", justify: "flex-end"
517
- })
518
- content_image.setWidth("-webkit-fill-available")
519
- content_image.add(file)
520
- let dialog_image = new Dialog({ width: "500px", height: "max-content", closeOutSideClick: true })
521
- dialog_image.addToHeader(content_image_header)
522
- dialog_image.addToBody(content_image)
523
-
524
- let button_image = new TextEditorButtons({
525
- icon: Icons.EDITOR.INSERT_PHOTO,
526
- listener: () => {
527
- document.getElementById(text_editor_id).focus()
528
- dialog_image.open()
529
- }
530
- })
531
- this.#addBlock(button_image, dialog_image)
532
- }
533
- // ======================
534
- if (controls.LINE_BREAK) {
535
- let button_line_break = new TextEditorButtons({
536
- icon: Icons.EDITOR.INSERT_PAGE_BREAK,
537
- command: Commands.INSERT_LINE_BREAK
538
- })
539
- this.#addBlock(button_line_break)
540
- }
541
- //
542
- if (controls.CONTENT_CONTROLS) {
543
- let button_COPY = new TextEditorButtons({
544
- icon: Icons.CONTENT.CONTENT_COPY,
545
- command: Commands.COPY
546
- })
547
- let button_CUT = new TextEditorButtons({
548
- icon: Icons.CONTENT.CONTENT_CUT,
549
- command: Commands.CUT
550
- })
551
- let button_PASTE = new TextEditorButtons({
552
- icon: Icons.CONTENT.CONTENT_PASTE,
553
- command: Commands.PASTE
554
- })
555
- this.#addBlock(button_COPY, button_CUT, button_PASTE)
556
- }
557
- }
558
- #addBlock(...childs) {
559
- let elem = document.createElement("text_editor_block")
560
- for (let child of childs) elem.appendChild(child.set())
561
- this.#panel.appendChild(elem)
562
- }
563
- set() {
564
- return this.#panel;
565
- }
566
- }
567
-
568
- exports.TextEditorPanel = TextEditorPanel;
1
+ const {Icon, Icons} = require("../chui_icons/icons");
2
+ const {Animation} = require("../../modules/chui_animations/animations");
3
+ const {Dialog} = require("../chui_modal/modal");
4
+ const {Button} = require("../chui_button/button");
5
+ const {TextInput} = require("../chui_inputs/chui_text/text");
6
+ const {Label} = require("../chui_label/label");
7
+ const {ContentBlock} = require("../chui_content_block/content_block");
8
+ const {Notification} = require("../chui_notification/notification");
9
+ const {NumberInput} = require("../chui_inputs/chui_number/number");
10
+ const {CheckBox} = require("../chui_inputs/chui_check_box/check_box");
11
+ const {FileInput, AcceptTypes} = require("../chui_inputs/chui_file/file");
12
+
13
+
14
+
15
+ class Commands {
16
+ static COPY = "copy"
17
+ static CUT = "cut"
18
+ static PASTE = "paste"
19
+ static DELETE = "delete"
20
+ static UNDO = "undo"
21
+ static REDO = "redo"
22
+ //
23
+ static BOLD = "bold"
24
+ static ITALIC = "italic"
25
+ static STRIKE_THROUGH = "strikeThrough"
26
+ static UNDERLINE = "underline"
27
+ //
28
+ static REMOVE_FORMAT = "removeFormat"
29
+ //
30
+ static SUPER_SCRIPT = "superscript"
31
+ static SUB_SCRIPT = "subscript"
32
+ //
33
+ static JUSTIFY_LEFT = "justifyLeft"
34
+ static JUSTIFY_RIGHT = "justifyRight"
35
+ static JUSTIFY_CENTER = "justifyCenter"
36
+ static JUSTIFY_FULL = "justifyFull"
37
+ //
38
+ static FORMAT_BLOCK = "formatBlock"
39
+ static NONE = "none"
40
+ // ITEMS
41
+ static CREATE_LINK = "createLink"
42
+ static UNLINK = "unlink"
43
+ static INSERT_IMAGE = "insertImage"
44
+ static INSERT_LINE_BREAK = "insertLineBreak"
45
+ static INSERT_HTML = "insertHTML"
46
+ // LIST
47
+ static INSERT_ORDERED_LIST = "insertOrderedList"
48
+ static INSERT_UNORDERED_LIST = "insertUnorderedList"
49
+ }
50
+
51
+ class TextEditorButtons {
52
+ #button = undefined;
53
+ constructor(options = { icon: undefined, command: undefined, value: undefined, disableFocus: false, listener: () => {} }) {
54
+ this.#button = document.createElement('chui_button_format');
55
+ this.#button.innerHTML = new Icon(options.icon).getHTML();
56
+ if (options.disableFocus) {
57
+ this.#button.addEventListener("mousedown", () => {
58
+ return false
59
+ })
60
+ }
61
+ if (options.listener !== undefined) {
62
+ this.#button.addEventListener("click", options.listener)
63
+ } else {
64
+ this.#button.addEventListener("click", () => {
65
+ if (options.value !== undefined) {
66
+ document.execCommand(options.command, false, options.value);
67
+ } else {
68
+ document.execCommand(options.command, false);
69
+ }
70
+ })
71
+ }
72
+ }
73
+ set() {
74
+ return this.#button;
75
+ }
76
+ }
77
+
78
+ class TextEditorSelects {
79
+ #id = require("randomstring").generate();
80
+ #id_sb = require("randomstring").generate();
81
+ #Select_main = document.createElement('chui_text_editor_select_box');
82
+ #Select_second = document.createElement('text_editor_select_box');
83
+ #input = document.createElement('input');
84
+ #div_value = document.createElement("text_editor_div_value")
85
+ #button_open = document.createElement('text_editor_select_button_open');
86
+ #dropdown = document.createElement('text_editor_selectbox_dropdown');
87
+ constructor(options = { icon: String() }) {
88
+ if (options.icon !== undefined) {
89
+ this.#div_value.innerHTML = options.icon;
90
+ }
91
+ this.#input.setAttribute('id', this.#id_sb);
92
+ this.#input.classList.add('text_editor_selectbox_input');
93
+ this.#input.type = 'text';
94
+ this.#input.disabled = true
95
+ this.#input.style.display = 'none'
96
+ this.#button_open.innerHTML = new Icon(Icons.HARDWARE.KEYBOARD_ARROW_DOWN, undefined, "var(--blue_prime_background)").getHTML();
97
+ this.#dropdown.setAttribute('id', this.#id);
98
+ this.#Select_second.appendChild(this.#input)
99
+ this.#Select_second.appendChild(this.#div_value)
100
+ this.#Select_second.appendChild(this.#button_open)
101
+ this.#Select_second.appendChild(this.#dropdown)
102
+ //LISTENERS
103
+ this.#Select_second.addEventListener('click', (event) => {
104
+ if (event.target.parentNode === this.#Select_second) {
105
+ this.#input.focus()
106
+ new Animation(this.#dropdown).fadeIn();
107
+ TextEditorSelects.#setOptionDisplay(document.getElementById(this.#id));
108
+ }
109
+ });
110
+ window.addEventListener('click', (event) => {
111
+ if (event.target.parentNode !== this.#Select_second) {
112
+ new Animation(this.#dropdown).fadeOut();
113
+ }
114
+ });
115
+ this.#input.addEventListener('input', (event) => {
116
+ let dropdown = document.getElementById(this.#id);
117
+ for (let option of dropdown.childNodes) {
118
+ if (!option.getAttribute('option_value').includes(event.target.value)) {
119
+ option.style.display = 'none'
120
+ } else {
121
+ option.style.display = 'block'
122
+ }
123
+ }
124
+ });
125
+ this.#Select_main.appendChild(this.#Select_second)
126
+ }
127
+ addOptionsFontSize(...options) {
128
+ for (let opt of options) {
129
+ let option = document.createElement(`text_editor_selectbox_option`);
130
+ let fontSize = document.createElement("font");
131
+ fontSize.setAttribute("size", opt.value)
132
+ fontSize.innerHTML = opt.name;
133
+ option.setAttribute('option_value', opt.value);
134
+ option.addEventListener('click', () => {
135
+ this.#input.value = option.getAttribute('option_value');
136
+ this.#input.setAttribute('value', option.getAttribute('option_value'));
137
+ });
138
+ option.appendChild(fontSize)
139
+ this.#dropdown.appendChild(option);
140
+ }
141
+ }
142
+ addOptionsHeader(...options) {
143
+ for (let opt of options) {
144
+ let option = document.createElement(`text_editor_selectbox_option`);
145
+ let header = document.createElement(`${opt.value.replace("<", "").replace(">", "")}`);
146
+ header.innerHTML = opt.name;
147
+ header.style.padding = '0px';
148
+ header.style.margin = '0px';
149
+ option.setAttribute('option_value', opt.value);
150
+ option.addEventListener('click', () => {
151
+ this.#input.value = option.getAttribute('option_value');
152
+ this.#input.setAttribute('value', option.getAttribute('option_value'));
153
+ });
154
+ option.appendChild(header)
155
+ this.#dropdown.appendChild(option);
156
+ }
157
+ }
158
+ addValueChangeListener(listener = () => {}) {
159
+ let observer = new MutationObserver((mutations) => {
160
+ mutations.forEach(listener);
161
+ });
162
+ observer.observe(this.#input, {
163
+ attributes: true,
164
+ childList: false,
165
+ subtree: false,
166
+ characterData: false,
167
+ attributeFilter: ['value']
168
+ });
169
+ }
170
+ set() {
171
+ return this.#Select_main;
172
+ }
173
+ static #setOptionDisplay(element = new HTMLElement()) {
174
+ for (let option of element.childNodes) { option.style.display = 'block'; }
175
+ }
176
+ }
177
+
178
+ class TextEditorPanel {
179
+ #panel = document.createElement("text_editor_panel")
180
+ constructor(text_editor_id = String(), controls = { UNDO_REDO: Boolean() }) {
181
+ // Управление
182
+ if (controls.UNDO_REDO) {
183
+ let button_undo = new TextEditorButtons({
184
+ icon: Icons.CONTENT.UNDO,
185
+ command: Commands.UNDO
186
+ })
187
+ let button_redo = new TextEditorButtons({
188
+ icon: Icons.CONTENT.REDO,
189
+ command: Commands.REDO
190
+ })
191
+ this.#addBlock(button_undo, button_redo)
192
+ }
193
+ // formatBlock
194
+ if (controls.BLOCK_FORMAT) {
195
+ let select_headers = new TextEditorSelects({ icon: new Icon(Icons.EDITOR.TITLE).getHTML() })
196
+ select_headers.addOptionsHeader(
197
+ { name: "H1", value: "<h1>" },
198
+ { name: "H2", value: "<h2>" },
199
+ { name: "H3", value: "<h3>" },
200
+ { name: "H4", value: "<h4>" },
201
+ { name: "H5", value: "<h5>" },
202
+ { name: "H6", value: "<h6>" },
203
+ { name: "Code", value: "<pre>" },
204
+ { name: "Paragraph", value: "<P>" }
205
+ )
206
+ select_headers.addValueChangeListener((e) => {
207
+ document.execCommand('formatBlock', false, e.target.value);
208
+ })
209
+ this.#addBlock(select_headers)
210
+ let button_format_quote = new TextEditorButtons({
211
+ icon: Icons.EDITOR.FORMAT_QUOTE,
212
+ command: Commands.FORMAT_BLOCK,
213
+ value: "<BLOCKQUOTE>"
214
+ })
215
+ this.#addBlock(button_format_quote)
216
+ }
217
+ if (controls.FONT_SIZE) {
218
+ let select_font_size = new TextEditorSelects({ icon: new Icon(Icons.EDITOR.FORMAT_SIZE).getHTML() })
219
+ select_font_size.addOptionsFontSize(
220
+ { name: "xx_small", value: "1" },
221
+ { name: "x_small", value: "2" },
222
+ { name: "small", value: "3" },
223
+ { name: "medium", value: "4" },
224
+ { name: "large", value: "5" },
225
+ { name: "x_large", value: "6" },
226
+ { name: "xx_large", value: "7" },
227
+ )
228
+ select_font_size.addValueChangeListener((e) => {
229
+ document.execCommand('fontSize', false, e.target.value);
230
+ })
231
+ this.#addBlock(select_font_size)
232
+ }
233
+ if (controls.REMOVE_FORMAT) {
234
+ let button_removeFormat = new TextEditorButtons({
235
+ icon: Icons.EDITOR.FORMAT_CLEAR,
236
+ command: Commands.REMOVE_FORMAT
237
+ })
238
+ this.#addBlock(button_removeFormat)
239
+ }
240
+ // FORMAT
241
+ if (controls.BOLD) {
242
+ let button_bold_text = new TextEditorButtons({
243
+ icon: Icons.EDITOR.FORMAT_BOLD,
244
+ command: Commands.BOLD
245
+ })
246
+ this.#addBlock(button_bold_text)
247
+ }
248
+ if (controls.ITALIC) {
249
+ let button_italic_text = new TextEditorButtons({
250
+ icon: Icons.EDITOR.FORMAT_ITALIC,
251
+ command: Commands.ITALIC
252
+ })
253
+ this.#addBlock(button_italic_text)
254
+ }
255
+ if (controls.STRIKE_THROUGH) {
256
+ let button_strikeThrough = new TextEditorButtons({
257
+ icon: Icons.EDITOR.FORMAT_STRIKETHROUGH,
258
+ command: Commands.STRIKE_THROUGH
259
+ })
260
+ this.#addBlock(button_strikeThrough)
261
+ }
262
+ if (controls.UNDERLINE) {
263
+ let button_underline = new TextEditorButtons({
264
+ icon: Icons.EDITOR.FORMAT_UNDERLINED,
265
+ command: Commands.UNDERLINE
266
+ })
267
+ this.#addBlock(button_underline)
268
+ }
269
+ //
270
+ if (controls.SUPERSCRIPT) {
271
+ let button_superscript = new TextEditorButtons({
272
+ icon: Icons.EDITOR.SUPERSCRIPT,
273
+ command: Commands.SUPER_SCRIPT
274
+ })
275
+ this.#addBlock(button_superscript)
276
+ }
277
+ if (controls.SUBSCRIPT) {
278
+ let button_subscript = new TextEditorButtons({
279
+ icon: Icons.EDITOR.SUBSCRIPT,
280
+ command: Commands.SUB_SCRIPT
281
+ })
282
+ this.#addBlock(button_subscript)
283
+ }
284
+ //
285
+ if (controls.JUSTIFY_LEFT) {
286
+ let button_justifyLeft = new TextEditorButtons({
287
+ icon: Icons.EDITOR.FORMAT_ALIGN_LEFT,
288
+ command: Commands.JUSTIFY_LEFT
289
+ })
290
+ this.#addBlock(button_justifyLeft)
291
+ }
292
+ if (controls.JUSTIFY_CENTER) {
293
+ let button_justifyCenter = new TextEditorButtons({
294
+ icon: Icons.EDITOR.FORMAT_ALIGN_CENTER,
295
+ command: Commands.JUSTIFY_CENTER
296
+ })
297
+ this.#addBlock(button_justifyCenter)
298
+ }
299
+ if (controls.JUSTIFY_RIGHT) {
300
+ let button_justifyRight = new TextEditorButtons({
301
+ icon: Icons.EDITOR.FORMAT_ALIGN_RIGHT,
302
+ command: Commands.JUSTIFY_RIGHT
303
+ })
304
+ this.#addBlock(button_justifyRight)
305
+ }
306
+ if (controls.JUSTIFY_FULL) {
307
+ let button_justifyFull = new TextEditorButtons({
308
+ icon: Icons.EDITOR.FORMAT_ALIGN_JUSTIFY,
309
+ command: Commands.JUSTIFY_FULL
310
+ })
311
+ this.#addBlock(button_justifyFull)
312
+ }
313
+ //
314
+ if (controls.LISTS) {
315
+ let button_list_one = new TextEditorButtons({
316
+ icon: Icons.EDITOR.FORMAT_LIST_NUMBERED,
317
+ command: Commands.INSERT_ORDERED_LIST
318
+ })
319
+ let button_list_two = new TextEditorButtons({
320
+ icon: Icons.EDITOR.FORMAT_LIST_BULLETED,
321
+ command: Commands.INSERT_UNORDERED_LIST
322
+ })
323
+ this.#addBlock(button_list_one, button_list_two)
324
+
325
+ }
326
+ //
327
+ // Создание ссылки
328
+ if (controls.INSERT_LINK) {
329
+ let button_unlink = new TextEditorButtons({
330
+ icon: Icons.CONTENT.LINK_OFF,
331
+ command: Commands.UNLINK
332
+ })
333
+ let content_link = new ContentBlock({
334
+ direction: "column", wrap: "wrap", align: "center", justify: "flex-end"
335
+ })
336
+ content_link.setWidth("-webkit-fill-available")
337
+ let content_link_header = new ContentBlock({
338
+ direction: "row", wrap: "wrap", align: "center", justify: "space-between", disableMarginChild: true
339
+ })
340
+ content_link_header.setWidth("-webkit-fill-available")
341
+ let dialog_link = new Dialog({ width: "500px", height: "max-content", closeOutSideClick: true })
342
+ let input_link_text = new TextInput({ title: "Наименование", placeholder: "Наименование", width: "-webkit-fill-available", disableFocus: false })
343
+ let input_link = new TextInput({ title: "Ссылка", placeholder: "https://", width: "-webkit-fill-available", value: "https://example.ru", disableFocus: false })
344
+ content_link.add(input_link_text, input_link)
345
+ dialog_link.addToBody(content_link)
346
+ content_link_header.add(
347
+ new Button({
348
+ icon: Icons.NAVIGATION.CLOSE,
349
+ clickEvent: () => {
350
+ document.getElementById(text_editor_id).focus()
351
+ dialog_link.close()
352
+ }
353
+ }),
354
+ new Label({ text: "Добавить ссылку" }),
355
+ new Button({
356
+ icon: Icons.CONTENT.ADD,
357
+ clickEvent: () => {
358
+ document.getElementById(text_editor_id).focus()
359
+ document.getSelection().removeAllRanges();
360
+ document.getSelection().addRange(range_link);
361
+ if (selection_link.toString() === "") document.execCommand('insertHTML', false, `<a href="${input_link.getValue()}">${input_link_text.getValue()}</a>`);
362
+ else document.execCommand(Commands.CREATE_LINK, false, input_link.getValue())
363
+ dialog_link.close()
364
+ }
365
+ }),
366
+ )
367
+ dialog_link.addToHeader(content_link_header)
368
+ let selection_link = undefined;
369
+ let range_link = undefined;
370
+ let button_link = new TextEditorButtons({
371
+ icon: Icons.CONTENT.LINK,
372
+ disableFocus: true,
373
+ listener: () => {
374
+ document.getElementById(text_editor_id).focus()
375
+ selection_link = document.getSelection();
376
+ range_link = selection_link.getRangeAt(0)
377
+ input_link_text.setValue(selection_link.toString())
378
+ if (selection_link.toString() === "") input_link_text.setDisabled(false);
379
+ else input_link_text.setDisabled(true);
380
+ dialog_link.open()
381
+ }
382
+ })
383
+ this.#addBlock(button_unlink, button_link, dialog_link)
384
+ }
385
+ // ================
386
+ // Создание таблицы
387
+ if (controls.INSERT_TABLE) {
388
+ let content_table_header = new ContentBlock({
389
+ direction: "row", wrap: "wrap", align: "center", justify: "space-between", disableMarginChild: true
390
+ })
391
+ content_table_header.setWidth("-webkit-fill-available")
392
+ let content_table_2 = new ContentBlock({
393
+ direction: "row", wrap: "wrap", align: "center", justify: "space-around"
394
+ })
395
+ content_table_2.setWidth("-webkit-fill-available")
396
+ let content_table = new ContentBlock({
397
+ direction: "row", wrap: "wrap", align: "center", justify: "space-around"
398
+ })
399
+ content_table.setWidth("-webkit-fill-available")
400
+ let content_table_main = new ContentBlock({
401
+ direction: "column", wrap: "wrap", align: "center", justify: "space-around"
402
+ })
403
+ content_table_main.setWidth("-webkit-fill-available")
404
+ let checkBox_header = new CheckBox({ title: "Добавить THEAD" })
405
+ content_table_2.add(checkBox_header)
406
+ let table_rows = new NumberInput({ title:'Количество строк' });
407
+ let table_cols = new NumberInput({ title:'Количество столбцов' });
408
+ content_table.add(table_rows, new Label("X"), table_cols)
409
+
410
+ content_table_header.add(
411
+ new Button({
412
+ icon: Icons.NAVIGATION.CLOSE,
413
+ clickEvent: () => {
414
+ dialog_table.close()
415
+ }
416
+ }),
417
+ new Label({ text: "Добавить таблицу" }),
418
+ new Button({
419
+ icon: Icons.CONTENT.ADD,
420
+ clickEvent: () => {
421
+ let error = false;
422
+ if (Number(table_rows.getValue()) === 0 && Number(table_cols.getValue()) === 0) {
423
+ new Notification(`Установите количество столбцов и строк`, Notification.STYLE.ERROR).show();
424
+ error = true;
425
+ } else if (Number(table_cols.getValue()) === 0) {
426
+ new Notification(`Установите количество столбцов`, Notification.STYLE.ERROR).show();
427
+ error = true;
428
+ } else if (Number(table_rows.getValue()) === 0) {
429
+ new Notification(`Установите количество строк`, Notification.STYLE.ERROR).show();
430
+ error = true;
431
+ }
432
+ if (!error) {
433
+ let table = document.createElement("table")
434
+ table.classList.add("text_editor_table")
435
+ // шапка
436
+ if (checkBox_header.getValue()) {
437
+ let head_table = table.createTHead()
438
+ head_table.classList.add("text_editor_table_body")
439
+ let head_row = head_table.insertRow(0)
440
+ head_row.classList.add("text_editor_table_row")
441
+ for (let j = 0; j < table_cols.getValue(); j++) {
442
+ let cell = head_row.insertCell(j)
443
+ cell.classList.add("text_editor_table_cell")
444
+ cell.innerText = `TH`
445
+ }
446
+ }
447
+ // тело таблицы
448
+ let body_table = table.createTBody()
449
+ body_table.classList.add("text_editor_table_body")
450
+ for (let i = 0; i < table_rows.getValue(); i++) {
451
+ let row = body_table.insertRow(i)
452
+ row.classList.add("text_editor_table_row")
453
+ for (let j = 0; j < table_cols.getValue(); j++) {
454
+ let cell = row.insertCell(j)
455
+ cell.classList.add("text_editor_table_cell")
456
+ cell.innerText = `TB`
457
+ }
458
+ }
459
+ document.getElementById(text_editor_id).focus()
460
+ document.execCommand(Commands.INSERT_HTML, false, table.outerHTML)
461
+ dialog_table.close()
462
+ }
463
+ }
464
+ })
465
+ )
466
+
467
+ let dialog_table = new Dialog({ width: "500px", height: "max-content", closeOutSideClick: true })
468
+ dialog_table.addToHeader(content_table_header)
469
+ content_table_main.add(content_table_2, content_table)
470
+ dialog_table.addToBody(content_table_main)
471
+ let button_table = new TextEditorButtons({
472
+ icon: Icons.EDITOR.TABLE_CHART,
473
+ listener: () => {
474
+ document.getElementById(text_editor_id).focus()
475
+ dialog_table.open()
476
+ }
477
+ })
478
+ this.#addBlock(button_table, dialog_table)
479
+ }
480
+ // ================
481
+ // Добавление изображения
482
+ if (controls.INSERT_IMAGE) {
483
+ let content_image_header = new ContentBlock({
484
+ direction: "row", wrap: "wrap", align: "center", justify: "space-between", disableMarginChild: true
485
+ })
486
+ content_image_header.setWidth("-webkit-fill-available")
487
+ let file = new FileInput({
488
+ title: "Выберите изображение",
489
+ multiple: false,
490
+ accept: [
491
+ AcceptTypes.ALL_IMAGE
492
+ ]
493
+ })
494
+ content_image_header.add(
495
+ new Button({
496
+ icon: Icons.NAVIGATION.CLOSE,
497
+ clickEvent: () => dialog_image.close()
498
+ }),
499
+ new Label({ text: "Добавить изображение" }),
500
+ new Button({
501
+ icon: Icons.CONTENT.ADD,
502
+ clickEvent: () => {
503
+ document.getElementById(text_editor_id).focus()
504
+ let image = file.getFile(0)
505
+ let reader = new FileReader();
506
+ reader.addEventListener("load", () => {
507
+ document.execCommand('insertImage', false, reader.result);
508
+ }, false);
509
+ if (image) reader.readAsDataURL(image);
510
+ dialog_image.close()
511
+ }
512
+ })
513
+ )
514
+
515
+ let content_image = new ContentBlock({
516
+ direction: "column", wrap: "wrap", align: "center", justify: "flex-end"
517
+ })
518
+ content_image.setWidth("-webkit-fill-available")
519
+ content_image.add(file)
520
+ let dialog_image = new Dialog({ width: "500px", height: "max-content", closeOutSideClick: true })
521
+ dialog_image.addToHeader(content_image_header)
522
+ dialog_image.addToBody(content_image)
523
+
524
+ let button_image = new TextEditorButtons({
525
+ icon: Icons.EDITOR.INSERT_PHOTO,
526
+ listener: () => {
527
+ document.getElementById(text_editor_id).focus()
528
+ dialog_image.open()
529
+ }
530
+ })
531
+ this.#addBlock(button_image, dialog_image)
532
+ }
533
+ // ======================
534
+ if (controls.LINE_BREAK) {
535
+ let button_line_break = new TextEditorButtons({
536
+ icon: Icons.EDITOR.INSERT_PAGE_BREAK,
537
+ command: Commands.INSERT_LINE_BREAK
538
+ })
539
+ this.#addBlock(button_line_break)
540
+ }
541
+ //
542
+ if (controls.CONTENT_CONTROLS) {
543
+ let button_COPY = new TextEditorButtons({
544
+ icon: Icons.CONTENT.CONTENT_COPY,
545
+ command: Commands.COPY
546
+ })
547
+ let button_CUT = new TextEditorButtons({
548
+ icon: Icons.CONTENT.CONTENT_CUT,
549
+ command: Commands.CUT
550
+ })
551
+ let button_PASTE = new TextEditorButtons({
552
+ icon: Icons.CONTENT.CONTENT_PASTE,
553
+ command: Commands.PASTE
554
+ })
555
+ this.#addBlock(button_COPY, button_CUT, button_PASTE)
556
+ }
557
+ }
558
+ #addBlock(...childs) {
559
+ let elem = document.createElement("text_editor_block")
560
+ for (let child of childs) elem.appendChild(child.set())
561
+ this.#panel.appendChild(elem)
562
+ }
563
+ set() {
564
+ return this.#panel;
565
+ }
566
+ }
567
+
568
+ exports.TextEditorPanel = TextEditorPanel;
569
569
  exports.Commands = Commands;