chuijs 3.6.3 → 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.
- package/LICENSE +21 -21
- package/README.md +1203 -162
- package/framework/appLayout/default/chui_app_layout.js +747 -747
- package/framework/appLayout/default/global_style.css +592 -570
- package/framework/appLayout/default/main_theme_style.css +118 -101
- package/framework/components/chui_accordion/accordion.js +63 -63
- package/framework/components/chui_accordion/styles.css +79 -75
- package/framework/components/chui_badge/badge.js +55 -55
- package/framework/components/chui_badge/styles.css +29 -29
- package/framework/components/chui_button/button.js +48 -48
- package/framework/components/chui_button/styles.css +75 -70
- package/framework/components/chui_calendar/calendar.js +97 -97
- package/framework/components/chui_card/card.js +87 -0
- package/framework/components/chui_card/styles.css +72 -0
- package/framework/components/chui_code/code.js +18 -18
- package/framework/components/chui_code/styles.css +9 -9
- package/framework/components/chui_console/console.js +27 -27
- package/framework/components/chui_console/styles.css +31 -31
- package/framework/components/chui_content_block/content_block.js +51 -51
- package/framework/components/chui_content_block/styles.css +2 -2
- package/framework/components/chui_context_menu/context_menu.js +230 -0
- package/framework/components/chui_context_menu/styles.css +136 -0
- package/framework/components/chui_custom_element/custom_element.js +24 -24
- package/framework/components/chui_details/details.js +85 -85
- package/framework/components/chui_details/styles.css +70 -66
- package/framework/components/chui_fieldset/fieldset.js +40 -40
- package/framework/components/chui_fieldset/styles.css +24 -24
- package/framework/components/chui_form/form.js +40 -40
- package/framework/components/chui_form/styles.css +21 -21
- package/framework/components/chui_graphs/graphs.js +234 -190
- package/framework/components/chui_graphs/styles.css +37 -32
- package/framework/components/chui_hero/hero.js +98 -0
- package/framework/components/chui_hero/styles.css +91 -0
- package/framework/components/chui_html_block/html_block.js +16 -16
- package/framework/components/chui_html_block/styles.css +5 -5
- package/framework/components/chui_hx/hx.js +15 -15
- package/framework/components/chui_hx/styles.css +38 -38
- package/framework/components/chui_icons/icons.js +2144 -2144
- package/framework/components/chui_icons/styles.css +13 -13
- package/framework/components/chui_inputs/chui_check_box/check_box.js +32 -32
- package/framework/components/chui_inputs/chui_check_box/styles.css +91 -86
- package/framework/components/chui_inputs/chui_combo_box/combo_box.js +166 -150
- package/framework/components/chui_inputs/chui_combo_box/styles.css +113 -107
- package/framework/components/chui_inputs/chui_date/date.js +177 -174
- package/framework/components/chui_inputs/chui_date/styles.css +163 -128
- package/framework/components/chui_inputs/chui_email/email.js +61 -61
- package/framework/components/chui_inputs/chui_email/styles.css +69 -71
- package/framework/components/chui_inputs/chui_file/file.js +76 -76
- package/framework/components/chui_inputs/chui_file/styles.css +99 -99
- package/framework/components/chui_inputs/chui_multi_combo_box/multi_combo_box.js +295 -295
- package/framework/components/chui_inputs/chui_multi_combo_box/styles.css +212 -235
- package/framework/components/chui_inputs/chui_number/number.js +108 -108
- package/framework/components/chui_inputs/chui_number/styles.css +84 -84
- package/framework/components/chui_inputs/chui_password/password.js +99 -99
- package/framework/components/chui_inputs/chui_password/styles.css +97 -97
- package/framework/components/chui_inputs/chui_radio_button/radio_button.js +45 -45
- package/framework/components/chui_inputs/chui_radio_button/styles.css +76 -73
- package/framework/components/chui_inputs/chui_select_box/select_box.js +187 -170
- package/framework/components/chui_inputs/chui_select_box/styles.css +123 -117
- package/framework/components/chui_inputs/chui_text/styles.css +83 -84
- package/framework/components/chui_inputs/chui_text/text.js +91 -91
- package/framework/components/chui_inputs/chui_text_area/styles.css +57 -57
- package/framework/components/chui_inputs/chui_text_area/text_area.js +61 -61
- package/framework/components/chui_inputs/chui_toggle/styles.css +66 -61
- package/framework/components/chui_inputs/chui_toggle/toggle.js +36 -36
- package/framework/components/chui_label/label.js +54 -54
- package/framework/components/chui_label/styles.css +11 -11
- package/framework/components/chui_media/audio.js +908 -908
- package/framework/components/chui_media/audio_styles.css +458 -458
- package/framework/components/chui_media/image.js +105 -105
- package/framework/components/chui_media/image_styles.css +61 -61
- package/framework/components/chui_media/video.js +248 -248
- package/framework/components/chui_media/video_styles.css +160 -160
- package/framework/components/chui_menu_bar/menu_bar.js +66 -74
- package/framework/components/chui_menu_bar/styles.css +114 -76
- package/framework/components/chui_modal/modal.js +142 -135
- package/framework/components/chui_modal/styles.css +36 -36
- package/framework/components/chui_notification/notification.js +72 -72
- package/framework/components/chui_notification/notification_download.js +78 -78
- package/framework/components/chui_notification/notification_download_progress.css +119 -123
- package/framework/components/chui_notification/notification_download_progress.js +105 -105
- package/framework/components/chui_notification/notification_update.js +54 -54
- package/framework/components/chui_notification/styles.css +91 -91
- package/framework/components/chui_notification/styles_download.css +85 -85
- package/framework/components/chui_notification/styles_update.css +73 -73
- package/framework/components/chui_paragraph/paragraph.js +14 -14
- package/framework/components/chui_paragraph/styles.css +6 -6
- package/framework/components/chui_popups/popups.js +250 -250
- package/framework/components/chui_popups/styles.css +129 -115
- package/framework/components/chui_progress_bar/progress_bar.js +28 -28
- package/framework/components/chui_progress_bar/styles.css +28 -28
- package/framework/components/chui_radio_group/radio_group.js +57 -57
- package/framework/components/chui_radio_group/styles.css +3 -3
- package/framework/components/chui_slideshow/slideshow.js +75 -75
- package/framework/components/chui_slideshow/styles.css +94 -85
- package/framework/components/chui_spinner/spinner.js +45 -45
- package/framework/components/chui_spinner/styles.css +23 -23
- package/framework/components/chui_table/styles.css +42 -42
- package/framework/components/chui_table/table.js +234 -234
- package/framework/components/chui_tabs/chui_tabs.js +77 -77
- package/framework/components/chui_tabs/styles.css +54 -48
- package/framework/components/chui_text_editor/styles.css +217 -217
- package/framework/components/chui_text_editor/text_editor.js +144 -144
- package/framework/components/chui_text_editor/text_editor_panel.js +568 -568
- package/framework/components/chui_tree_view/styles.css +81 -75
- package/framework/components/chui_tree_view/tree_view.js +90 -90
- package/framework/components/chui_webview/styles.css +27 -27
- package/framework/components/chui_webview/webview.js +103 -103
- package/framework/components/telegram_bot/chui_telegram_bot.js +183 -183
- package/framework/modules/chui_animations/animations.js +121 -121
- package/framework/modules/chui_animations/styles.css +79 -79
- package/framework/modules/chui_fonts.js +7128 -7128
- package/framework/modules/chui_functions.js +106 -78
- package/framework/modules/chui_logger/chui_logger.js +53 -53
- package/framework/modules/chui_page/page.js +86 -86
- package/framework/modules/chui_page/styles.css +9 -9
- package/framework/tray_bar/chui_menu_items.js +48 -48
- package/index.js +570 -555
- 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;
|