@alexsab-ru/scripts 0.6.0 → 0.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/form.js CHANGED
@@ -1,323 +1,321 @@
1
- import { getCookie, setCookie, deleteCookie } from './cookie';
2
- import { createRequest } from './calltouch';
3
- import { reachGoal, getFormDataObject } from './analytics';
4
-
5
- export const noValidPhone = (phoneValue) => {
6
- return ([...new Set(phoneValue.replace(/^(\+7)/g, "").replace(/\D/g, ""))].length === 1);
7
- };
8
-
9
- export function maskphone(e) {
10
- let num = this.value.replace(/^(\+7|8|7)/g, "").replace(/\D/g, "").split(/(?=.)/),
11
- i = num.length;
12
-
13
- if(this.value != "" && this.value != "+") {
14
- if (0 <= i) num.unshift("+7");
15
- if (1 <= i) num.splice(1, 0, " ");
16
- if (4 <= i) num.splice(5, 0, " ");
17
- if (7 <= i) num.splice(9, 0, "-");
18
- if (9 <= i) num.splice(12, 0, "-");
19
- this.value = num.join("");
20
- }
21
- }
22
-
23
-
24
- export const phoneChecker = (phone) => {
25
- let form = phone.closest("form"),
26
- btn = form.querySelector('[type="submit"]');
27
- if (!phone.value.length) {
28
- showErrorMes(form, ".phone", "Телефон является обязательным полем");
29
- stateBtn(btn, "Отправить");
30
- return false;
31
- } else {
32
- const phoneRe = new RegExp(/^\+7 [0-9]{3} [0-9]{3}-[0-9]{2}-[0-9]{2}$/);
33
- if (!phoneRe.test(phone.value) || noValidPhone(phone.value)) {
34
- showErrorMes(form, ".phone", "Введен некорректный номер телефона");
35
- stateBtn(btn, "Отправить");
36
- return false;
37
- }
38
- }
39
- showErrorMes(form, ".phone", "");
40
- return true;
41
- };
42
-
43
- document.querySelectorAll("input[name=phone]").forEach(function (element) {
44
- // element.addEventListener("focus", maskphone);
45
- element.addEventListener("input", maskphone);
46
- element.addEventListener("change", () => phoneChecker(element));
47
- });
48
-
49
- // AGREE CHECKBOX
50
- // Проверка на состояние чекбокса, показ/скрытие ошибки
51
- document.querySelectorAll("input[name=agree]").forEach(function (element) {
52
- let errorMes = element.parentElement.querySelector(".agree");
53
- element.addEventListener("change", (e) => {
54
- if (!e.target.checked) {
55
- errorMes.classList.remove("hidden");
56
- } else {
57
- errorMes.classList.add("hidden");
58
- }
59
- });
60
- });
61
-
62
- // TEXTAREA
63
- const minLengthTextareaField = 10; // минимальное кол-во символов
64
- // проверка на минимальное кол-во символов и скрытие ошибки
65
- const checkTextareaLength = (textarea, minLength) => {
66
- if (textarea.value.length >= minLength) {
67
- textarea.nextSibling.nextElementSibling.classList.add("hidden");
68
- }
69
- };
70
-
71
- // CHANGE textarea для всез браузеров
72
- document.querySelectorAll("textarea").forEach(function (textarea) {
73
- if (textarea.addEventListener) {
74
- textarea.addEventListener(
75
- "input",
76
- function () {
77
- // event handling code for sane browsers
78
- checkTextareaLength(textarea, minLengthTextareaField);
79
- },
80
- false
81
- );
82
- } else if (textarea.attachEvent) {
83
- textarea.attachEvent("onpropertychange", function () {
84
- // IE-specific event handling code
85
- checkTextareaLength(textarea, minLengthTextareaField);
86
- });
87
- }
88
- });
89
-
90
- // BUTTON
91
- // Состояние кнопки
92
- const stateBtn = (btn, value, disable = false) => {
93
- if (btn.tagName == 'INPUT') {
94
- btn.value = value;
95
- btn.disabled = disable;
96
- } else {
97
- btn.innerText = value;
98
- if (disable) {
99
- btn.setAttribute('disabled', true);
100
- } else {
101
- btn.removeAttribute('disabled');
102
- }
103
- }
104
- };
105
-
106
- const showErrorMes = (form, el, text) => {
107
- let field = form.querySelector(el);
108
- field.innerText = text;
109
- field.classList.remove("hidden");
110
- };
111
-
112
- const showMessageModal = (messageModal, icon, message) => {
113
- document.querySelectorAll(".modal-overlay").forEach((el) => {
114
- el.classList.add("hidden");
115
- });
116
- messageModal.querySelector("#icon").innerHTML = icon;
117
- messageModal.querySelector("p").innerHTML = message;
118
- messageModal.classList.remove("hidden");
119
- };
120
-
121
- const propsParams = {
122
- callback: null,
123
- callback_error: null,
124
- ct_routeKey: '',
125
- confirmModalText: '',
126
- verbose: false,
127
- }
128
-
129
- export const connectForms = (url, props = propsParams) => {
130
- props = {...propsParams, ...props};
131
-
132
- async function submitForm(form){
133
- const btn = form.querySelector('[type="submit"]');
134
- stateBtn(btn, "Отправляем...", true);
135
- const agree = form.querySelector('[name="agree"]');
136
- const phone = form.querySelector('[name="phone"]');
137
- const errorIcon =
138
- '<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 52 52"><path fill="#ed1c24" d="M26,0A26,26,0,1,0,52,26,26,26,0,0,0,26,0Zm9.6,17.5a1.94,1.94,0,0,1,2,2,2,2,0,1,1-2-2Zm-19.2,0a1.94,1.94,0,0,1,2,2,2,2,0,1,1-2-2ZM39.65,40.69a.93.93,0,0,1-.45.11,1,1,0,0,1-.89-.55,13.81,13.81,0,0,0-24.62,0,1,1,0,1,1-1.78-.9,15.8,15.8,0,0,1,28.18,0A1,1,0,0,1,39.65,40.69Z"></path></svg>';
139
- const successIcon =
140
- '<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 52 52"><path fill="#279548" d="M26,0A26,26,0,1,0,52,26,26,26,0,0,0,26,0Zm9.6,17.5a1.94,1.94,0,0,1,2,2,2,2,0,1,1-2-2Zm-19.2,0a2,2,0,1,1-2,2A2,2,0,0,1,16.4,17.5ZM40.09,32.15a15.8,15.8,0,0,1-28.18,0,1,1,0,0,1,1.78-.9,13.81,13.81,0,0,0,24.62,0,1,1,0,1,1,1.78.9Z"></path></svg>';
141
- const errorText =
142
- '<b class="text-bold block text-2xl mb-4">Упс!</b> Что-то пошло не так. Перезагрузите страницу и попробуйте снова. ';
143
- const successText = '<b class="text-bold block text-2xl mb-4">Спасибо!</b> В скором времени мы свяжемся с Вами!';
144
- const messageModal = document.getElementById("message-modal");
145
-
146
- if (!phoneChecker(phone)) {
147
- return;
148
- }
149
-
150
- // если флажок не установлен - фронт
151
- if (!agree.checked) {
152
- showErrorMes(form, ".agree", "Чтобы продолжить, установите флажок");
153
- stateBtn(btn, "Отправить");
154
- return;
155
- }
156
-
157
- // Отпрвка цели что форма submit только после всех проверок
158
- reachGoal("form_submit");
159
-
160
- let formData = new FormData(form);
161
- if(getCookie('fta')) {
162
- formData.append("fta", true);
163
- }
164
- if(getCookie('__gtm_campaign_url')) {
165
- let source = new URL(getCookie('__gtm_campaign_url'));
166
- source.search.slice(1).split("&").forEach(function(pair) {
167
- let param = pair.split("=");
168
- formData.append(param[0], param[1]);
169
- });
170
- }
171
- formData.append(
172
- "page_url",
173
- window.location.origin + window.location.pathname
174
- );
175
-
176
- if(typeof window.re != 'undefined') {
177
- formData.append("re", window.re);
178
- }
179
-
180
- window.location.search
181
- .slice(1)
182
- .split("&")
183
- .forEach(function (pair) {
184
- let param = pair.split("=");
185
- if(formData.get(param[0])){
186
- formData.set(param[0], decodeURIComponent(param[1]));
187
- } else {
188
- formData.append(param[0], decodeURIComponent(param[1]));
189
- }
190
- });
191
-
192
- let formDataObj = {};
193
- try {
194
- // Отправка заявки на обратный возов в CallTouch
195
- if(props.ct_routeKey != '') {
196
- const requestData = await createRequest(props.ct_routeKey, phone.value, props.verbose);
197
- formData.append("ct_callback", true);
198
- formData.append("ctw_createRequest", JSON.stringify(requestData));
199
- } else {
200
- throw new Error('Empty ct_routeKey');
201
- }
202
- } catch (error) {
203
- if(props.ct_routeKey != '') {
204
- formData.append("ctw_createRequest", error);
205
- }
206
- props.verbose && console.error("Error during request Calltouch callback:", error);
207
- formDataObj = getFormDataObject(formData, form.id);
208
- }
209
-
210
- const params = new URLSearchParams([...formData]);
211
-
212
- await fetch(url, {
213
- method: "POST",
214
- mode: "cors",
215
- cache: "no-cache",
216
- credentials: "same-origin",
217
- headers: {
218
- "Content-Type": "application/x-www-form-urlencoded",
219
- },
220
- body: params,
221
- })
222
- .then((res) => res.json())
223
- .then((data) => {
224
- props.verbose && console.log(data);
225
- stateBtn(btn, "Отправить");
226
- if (data.answer == "required") {
227
- reachGoal("form_required");
228
- showErrorMes(form, data.field, data.message);
229
- return;
230
- } else if (data.answer == "error") {
231
- reachGoal("form_error");
232
-
233
- // Вызов callback_error при ошибке
234
- if (props.callback_error && typeof props.callback_error === 'function') {
235
- props.callback_error();
236
- } else if (messageModal) {
237
- setCookie('SEND_MAIL', true, {'domain': window.location.hostname,'path':'/','expires':600});
238
- showMessageModal(messageModal, errorIcon, errorText + "<br>" + data.error);
239
- }
240
- return;
241
- } else {
242
- reachGoal("form_success", formDataObj);
243
-
244
- // Вызов callback при успехе
245
- if (props.callback && typeof props.callback === 'function') {
246
- props.callback();
247
- } else if (messageModal) {
248
- setCookie('SEND_MAIL', true, {'domain': window.location.hostname,'path':'/','expires':600});
249
- showMessageModal(messageModal, successIcon, successText);
250
- }
251
- }
252
- form.reset();
253
- })
254
- .catch((error) => {
255
- reachGoal("form_error");
256
- console.error("Ошибка отправки данных формы: " + error);
257
- deleteCookie('SEND_MAIL');
258
- // Вызов callback_error при ошибке
259
- if (props.callback_error && typeof props.callback_error === 'function') {
260
- props.callback_error();
261
- } else if (messageModal) {
262
- showMessageModal(messageModal, errorIcon, errorText + "<br>" + error);
263
- }
264
- stateBtn(btn, "Отправить");
265
- });
266
- return false;
267
- }
268
-
269
- async function sendForm(form) {
270
- if (getCookie('SEND_MAIL')) {
271
- const confirmModal = document.getElementById('confirm-modal');
272
- if (confirmModal) {
273
- confirmModal.querySelector('p').innerHTML = props.confirmModalText || '<span style="color: tomato; font-weight: bold">ПЕРЕДАЙ ТЕКСТ В ОБЪЕКТЕ <br><pre style="color: black; font-weight: 400">props = {confirmModalText: <i>"text"</i>}</pre></span>';
274
- confirmModal.classList.remove("hidden");
275
-
276
- const accept = confirmModal.querySelector('#accept-confirm');
277
- const acceptClose = confirmModal.querySelector('#accept-close');
278
-
279
- // Проверка на уже добавленный обработчик
280
- if (!accept.dataset.listenerAdded) {
281
- accept.dataset.listenerAdded = 'true';
282
- accept.addEventListener('click', async () => {
283
- // Закрываем модальное окно
284
- confirmModal.classList.add("hidden");
285
- // Удаляем куку
286
- deleteCookie('SEND_MAIL');
287
- // Повторно отправляем форму
288
- await submitForm(form);
289
- return;
290
- });
291
- }
292
-
293
- // Проверка на уже добавленный обработчик
294
- if (!acceptClose.dataset.listenerAdded) {
295
- acceptClose.dataset.listenerAdded = 'true';
296
- acceptClose.addEventListener('click', () => {
297
- // Закрываем модальное окно
298
- const modals = document.querySelectorAll('.modal-overlay');
299
- form.reset();
300
- if (modals.length) {
301
- modals.forEach((modal) => modal.classList.add("hidden"));
302
- }
303
- confirmModal.classList.add("hidden");
304
- return;
305
- });
306
- }
307
- return;
308
- }
309
- }else{
310
- // Если куки нет, просто отправляем форму
311
- await submitForm(form);
312
- return;
313
- }
314
- }
315
-
316
- // Отправка всех форм
317
- document.querySelectorAll("form").forEach((form) => {
318
- form.addEventListener('submit', async (event) => {
319
- event.preventDefault();
320
- await sendForm(form);
321
- })
322
- });
1
+ import { getCookie, setCookie, deleteCookie } from './cookie';
2
+ import { createRequest } from './calltouch';
3
+ import { reachGoal, getFormDataObject } from './analytics';
4
+
5
+ export const noValidPhone = (phoneValue) => {
6
+ return ([...new Set(phoneValue.replace(/^(\+7)/g, "").replace(/\D/g, ""))].length === 1);
7
+ };
8
+
9
+ export function maskphone(e) {
10
+ let num = this.value.replace(/^(\+7|8|7)/g, "").replace(/\D/g, "").split(/(?=.)/),
11
+ i = num.length;
12
+
13
+ if(this.value != "" && this.value != "+") {
14
+ if (0 <= i) num.unshift("+7");
15
+ if (1 <= i) num.splice(1, 0, " ");
16
+ if (4 <= i) num.splice(5, 0, " ");
17
+ if (7 <= i) num.splice(9, 0, "-");
18
+ if (9 <= i) num.splice(12, 0, "-");
19
+ this.value = num.join("");
20
+ }
21
+ }
22
+
23
+
24
+ export const phoneChecker = (phone) => {
25
+ let form = phone.closest("form"),
26
+ btn = form.querySelector('[type="submit"]');
27
+ if (!phone.value.length) {
28
+ showErrorMes(form, ".phone", "Телефон является обязательным полем");
29
+ stateBtn(btn, "Отправить");
30
+ return false;
31
+ } else {
32
+ const phoneRe = new RegExp(/^\+7 [0-9]{3} [0-9]{3}-[0-9]{2}-[0-9]{2}$/);
33
+ if (!phoneRe.test(phone.value) || noValidPhone(phone.value)) {
34
+ showErrorMes(form, ".phone", "Введен некорректный номер телефона");
35
+ stateBtn(btn, "Отправить");
36
+ return false;
37
+ }
38
+ }
39
+ showErrorMes(form, ".phone", "");
40
+ return true;
41
+ };
42
+
43
+ document.querySelectorAll("input[name=phone]").forEach(function (element) {
44
+ // element.addEventListener("focus", maskphone);
45
+ element.addEventListener("input", maskphone);
46
+ element.addEventListener("change", () => phoneChecker(element));
47
+ });
48
+
49
+ // AGREE CHECKBOX
50
+ // Проверка на состояние чекбокса, показ/скрытие ошибки
51
+ document.querySelectorAll("input[name=agree]").forEach(function (element) {
52
+ let errorMes = element.parentElement.querySelector(".agree");
53
+ element.addEventListener("change", (e) => {
54
+ if (!e.target.checked) {
55
+ errorMes.classList.remove("hidden");
56
+ } else {
57
+ errorMes.classList.add("hidden");
58
+ }
59
+ });
60
+ });
61
+
62
+ // TEXTAREA
63
+ const minLengthTextareaField = 10; // минимальное кол-во символов
64
+ // проверка на минимальное кол-во символов и скрытие ошибки
65
+ const checkTextareaLength = (textarea, minLength) => {
66
+ if (textarea.value.length >= minLength) {
67
+ textarea.nextSibling.nextElementSibling.classList.add("hidden");
68
+ }
69
+ };
70
+
71
+ // CHANGE textarea для всез браузеров
72
+ document.querySelectorAll("textarea").forEach(function (textarea) {
73
+ if (textarea.addEventListener) {
74
+ textarea.addEventListener(
75
+ "input",
76
+ function () {
77
+ // event handling code for sane browsers
78
+ checkTextareaLength(textarea, minLengthTextareaField);
79
+ },
80
+ false
81
+ );
82
+ } else if (textarea.attachEvent) {
83
+ textarea.attachEvent("onpropertychange", function () {
84
+ // IE-specific event handling code
85
+ checkTextareaLength(textarea, minLengthTextareaField);
86
+ });
87
+ }
88
+ });
89
+
90
+ // BUTTON
91
+ // Состояние кнопки
92
+ const stateBtn = (btn, value, disable = false) => {
93
+ if (btn.tagName == 'INPUT') {
94
+ btn.value = value;
95
+ btn.disabled = disable;
96
+ } else {
97
+ btn.innerText = value;
98
+ if (disable) {
99
+ btn.setAttribute('disabled', true);
100
+ } else {
101
+ btn.removeAttribute('disabled');
102
+ }
103
+ }
104
+ };
105
+
106
+ const showErrorMes = (form, el, text) => {
107
+ let field = form.querySelector(el);
108
+ field.innerText = text;
109
+ field.classList.remove("hidden");
110
+ };
111
+
112
+ const showMessageModal = (messageModal, icon, message) => {
113
+ document.querySelectorAll(".modal-overlay").forEach((el) => {
114
+ el.classList.add("hidden");
115
+ });
116
+ messageModal.querySelector("#icon").innerHTML = icon;
117
+ messageModal.querySelector("p").innerHTML = message;
118
+ messageModal.classList.remove("hidden");
119
+ };
120
+
121
+ const propsParams = {
122
+ callback: null,
123
+ callback_error: null,
124
+ ct_routeKey: '',
125
+ confirmModalText: '',
126
+ verbose: false,
127
+ }
128
+
129
+ export const connectForms = (url, props = propsParams) => {
130
+ props = {...propsParams, ...props};
131
+
132
+ async function submitForm(form){
133
+ const btn = form.querySelector('[type="submit"]');
134
+ stateBtn(btn, "Отправляем...", true);
135
+ const agree = form.querySelector('[name="agree"]');
136
+ const phone = form.querySelector('[name="phone"]');
137
+ const errorIcon =
138
+ '<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 52 52"><path fill="#ed1c24" d="M26,0A26,26,0,1,0,52,26,26,26,0,0,0,26,0Zm9.6,17.5a1.94,1.94,0,0,1,2,2,2,2,0,1,1-2-2Zm-19.2,0a1.94,1.94,0,0,1,2,2,2,2,0,1,1-2-2ZM39.65,40.69a.93.93,0,0,1-.45.11,1,1,0,0,1-.89-.55,13.81,13.81,0,0,0-24.62,0,1,1,0,1,1-1.78-.9,15.8,15.8,0,0,1,28.18,0A1,1,0,0,1,39.65,40.69Z"></path></svg>';
139
+ const successIcon =
140
+ '<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 52 52"><path fill="#279548" d="M26,0A26,26,0,1,0,52,26,26,26,0,0,0,26,0Zm9.6,17.5a1.94,1.94,0,0,1,2,2,2,2,0,1,1-2-2Zm-19.2,0a2,2,0,1,1-2,2A2,2,0,0,1,16.4,17.5ZM40.09,32.15a15.8,15.8,0,0,1-28.18,0,1,1,0,0,1,1.78-.9,13.81,13.81,0,0,0,24.62,0,1,1,0,1,1,1.78.9Z"></path></svg>';
141
+ const errorText =
142
+ '<b class="text-bold block text-2xl mb-4">Упс!</b> Что-то пошло не так. Перезагрузите страницу и попробуйте снова. ';
143
+ const successText = '<b class="text-bold block text-2xl mb-4">Спасибо!</b> В скором времени мы свяжемся с Вами!';
144
+ const messageModal = document.getElementById("message-modal");
145
+
146
+ if (!phoneChecker(phone)) {
147
+ return;
148
+ }
149
+
150
+ // если флажок не установлен - фронт
151
+ if (!agree.checked) {
152
+ showErrorMes(form, ".agree", "Чтобы продолжить, установите флажок");
153
+ stateBtn(btn, "Отправить");
154
+ return;
155
+ }
156
+
157
+ // Отпрвка цели что форма submit только после всех проверок
158
+ reachGoal("form_submit");
159
+
160
+ let formData = new FormData(form);
161
+ if(getCookie('fta')) {
162
+ formData.append("fta", true);
163
+ }
164
+ if(getCookie('__gtm_campaign_url')) {
165
+ let source = new URL(getCookie('__gtm_campaign_url'));
166
+ source.search.slice(1).split("&").forEach(function(pair) {
167
+ let param = pair.split("=");
168
+ formData.append(param[0], param[1]);
169
+ });
170
+ }
171
+ formData.append(
172
+ "page_url",
173
+ window.location.origin + window.location.pathname
174
+ );
175
+
176
+ if(typeof window.re != 'undefined') {
177
+ formData.append("re", window.re);
178
+ }
179
+
180
+ window.location.search
181
+ .slice(1)
182
+ .split("&")
183
+ .forEach(function (pair) {
184
+ let param = pair.split("=");
185
+ if(formData.get(param[0])){
186
+ formData.set(param[0], decodeURIComponent(param[1]));
187
+ } else {
188
+ formData.append(param[0], decodeURIComponent(param[1]));
189
+ }
190
+ });
191
+
192
+ let formDataObj = {};
193
+ try {
194
+ // Отправка заявки на обратный возов в CallTouch
195
+ if(props.ct_routeKey != '') {
196
+ const requestData = await createRequest(props.ct_routeKey, phone.value, props.verbose);
197
+ formData.append("ct_callback", true);
198
+ formData.append("ctw_createRequest", JSON.stringify(requestData));
199
+ } else {
200
+ throw new Error('Empty ct_routeKey');
201
+ }
202
+ } catch (error) {
203
+ if(props.ct_routeKey != '') {
204
+ formData.append("ctw_createRequest", error);
205
+ }
206
+ props.verbose && console.error("Error during request Calltouch callback:", error);
207
+ formDataObj = getFormDataObject(formData, form.id);
208
+ }
209
+
210
+ const params = new URLSearchParams([...formData]);
211
+
212
+ await fetch(url, {
213
+ method: "POST",
214
+ mode: "cors",
215
+ cache: "no-cache",
216
+ credentials: "same-origin",
217
+ headers: {
218
+ "Content-Type": "application/x-www-form-urlencoded",
219
+ },
220
+ body: params,
221
+ })
222
+ .then((res) => res.json())
223
+ .then((data) => {
224
+ props.verbose && console.log(data);
225
+ stateBtn(btn, "Отправить");
226
+ if (data.answer == "required") {
227
+ reachGoal("form_required");
228
+ showErrorMes(form, data.field, data.message);
229
+ return;
230
+ } else if (data.answer == "error") {
231
+ reachGoal("form_error");
232
+
233
+ // Вызов callback_error при ошибке
234
+ if (props.callback_error && typeof props.callback_error === 'function') {
235
+ props.callback_error();
236
+ } else if (messageModal) {
237
+ showMessageModal(messageModal, errorIcon, errorText + "<br>" + data.error);
238
+ }
239
+ return;
240
+ } else {
241
+ reachGoal("form_success", formDataObj);
242
+ setCookie('SEND_MAIL', true, {'domain': window.location.hostname,'path':'/','expires':600});
243
+ // Вызов callback при успехе
244
+ if (props.callback && typeof props.callback === 'function') {
245
+ props.callback();
246
+ } else if (messageModal) {
247
+ showMessageModal(messageModal, successIcon, successText);
248
+ }
249
+ }
250
+ form.reset();
251
+ })
252
+ .catch((error) => {
253
+ reachGoal("form_error");
254
+ console.error("Ошибка отправки данных формы: " + error);
255
+ deleteCookie('SEND_MAIL');
256
+ // Вызов callback_error при ошибке
257
+ if (props.callback_error && typeof props.callback_error === 'function') {
258
+ props.callback_error();
259
+ } else if (messageModal) {
260
+ showMessageModal(messageModal, errorIcon, errorText + "<br>" + error);
261
+ }
262
+ stateBtn(btn, "Отправить");
263
+ });
264
+ return false;
265
+ }
266
+
267
+ async function sendForm(form) {
268
+ if (getCookie('SEND_MAIL')) {
269
+ const confirmModal = document.getElementById('confirm-modal');
270
+ if (confirmModal) {
271
+ confirmModal.querySelector('p').innerHTML = props.confirmModalText || '<span style="color: tomato; font-weight: bold">ПЕРЕДАЙ ТЕКСТ В ОБЪЕКТЕ <br><pre style="color: black; font-weight: 400">props = {confirmModalText: <i>"text"</i>}</pre></span>';
272
+ confirmModal.classList.remove("hidden");
273
+
274
+ const accept = confirmModal.querySelector('#accept-confirm');
275
+ const acceptClose = confirmModal.querySelector('#accept-close');
276
+
277
+ // Проверка на уже добавленный обработчик
278
+ if (!accept.dataset.listenerAdded) {
279
+ accept.dataset.listenerAdded = 'true';
280
+ accept.addEventListener('click', async () => {
281
+ // Закрываем модальное окно
282
+ confirmModal.classList.add("hidden");
283
+ // Удаляем куку
284
+ deleteCookie('SEND_MAIL');
285
+ // Повторно отправляем форму
286
+ await submitForm(form);
287
+ return;
288
+ });
289
+ }
290
+
291
+ // Проверка на уже добавленный обработчик
292
+ if (!acceptClose.dataset.listenerAdded) {
293
+ acceptClose.dataset.listenerAdded = 'true';
294
+ acceptClose.addEventListener('click', () => {
295
+ // Закрываем модальное окно
296
+ const modals = document.querySelectorAll('.modal-overlay');
297
+ form.reset();
298
+ if (modals.length) {
299
+ modals.forEach((modal) => modal.classList.add("hidden"));
300
+ }
301
+ confirmModal.classList.add("hidden");
302
+ return;
303
+ });
304
+ }
305
+ return;
306
+ }
307
+ }else{
308
+ // Если куки нет, просто отправляем форму
309
+ await submitForm(form);
310
+ return;
311
+ }
312
+ }
313
+
314
+ // Отправка всех форм
315
+ document.querySelectorAll("form").forEach((form) => {
316
+ form.addEventListener('submit', async (event) => {
317
+ event.preventDefault();
318
+ await sendForm(form);
319
+ })
320
+ });
323
321
  }