@alexsab-ru/scripts 0.11.0 → 0.13.0

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,345 +1,346 @@
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
- if (!phone.value.length) {
27
- showErrorMes(form, ".phone", "Телефон является обязательным полем");
28
- return false;
29
- } else {
30
- const phoneRe = new RegExp(/^\+7 [0-9]{3} [0-9]{3}-[0-9]{2}-[0-9]{2}$/);
31
- if (!phoneRe.test(phone.value) || noValidPhone(phone.value)) {
32
- showErrorMes(form, ".phone", "Введен некорректный номер телефона");
33
- return false;
34
- }
35
- }
36
- showErrorMes(form, ".phone", "");
37
- return true;
38
- };
39
-
40
- // TEXTAREA
41
- const minLengthTextareaField = 10; // минимальное кол-во символов
42
- // проверка на минимальное кол-во символов и скрытие ошибки
43
- const checkTextareaLength = (textarea, minLength) => {
44
- if (textarea.value.length >= minLength) {
45
- textarea.nextSibling.nextElementSibling.classList.add("hidden");
46
- }
47
- };
48
-
49
- // BUTTON
50
- // Состояние кнопки
51
- const stateBtn = (btn, value, disable = false) => {
52
- if (btn.tagName == 'INPUT') {
53
- btn.value = value;
54
- btn.disabled = disable;
55
- } else {
56
- btn.innerText = value;
57
- if (disable) {
58
- btn.setAttribute('disabled', true);
59
- } else {
60
- btn.removeAttribute('disabled');
61
- }
62
- }
63
- };
64
-
65
- export const showErrorMes = (form, el, text) => {
66
- let field = form.querySelector(el);
67
- field.innerText = text;
68
- field.classList.remove("hidden");
69
- };
70
-
71
- export const showMessageModal = (messageModal, icon, message) => {
72
- document.querySelectorAll(".modal-overlay").forEach((el) => {
73
- el.classList.add("hidden");
74
- });
75
- if(messageModal){
76
- messageModal.querySelector("#icon").innerHTML = icon;
77
- messageModal.querySelector("p").innerHTML = message;
78
- messageModal.classList.remove("hidden");
79
- }
80
- };
81
-
82
- const propsParams = {
83
- callback: null,
84
- callback_error: null,
85
- validation: null,
86
- ct_routeKey: '',
87
- confirmModalText: '',
88
- verbose: false,
89
- agreeSelector: "agree",
90
- sendMailCookie: "SEND_MAIL",
91
- }
92
-
93
- export const errorIcon = '<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>';
94
- export const successIcon = '<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>';
95
- export const errorText = '<b class="text-bold block text-2xl mb-4">Упс!</b> Что-то пошло не так. Перезагрузите страницу и попробуйте снова. ';
96
- export const successText = '<b class="text-bold block text-2xl mb-4">Спасибо!</b> В скором времени мы свяжемся с Вами!';
97
- export const messageModal = document.getElementById("message-modal");
98
-
99
- export const connectForms = (url, props = propsParams) => {
100
- props = {...propsParams, ...props};
101
-
102
- document.querySelectorAll("input[name=phone]").forEach(function (element) {
103
- // element.addEventListener("focus", maskphone);
104
- element.addEventListener("input", maskphone);
105
- element.addEventListener("change", () => phoneChecker(element));
106
- });
107
-
108
- // AGREE CHECKBOX
109
- // Проверка на состояние чекбокса, показ/скрытие ошибки
110
- document.querySelectorAll("input[name=" + props.agreeSelector + "]").forEach(function (element) {
111
- let errorMes = element.parentElement.querySelector("." + props.agreeSelector);
112
- element.addEventListener("change", (e) => {
113
- if (!e.target.checked) {
114
- errorMes.classList.remove("hidden");
115
- } else {
116
- errorMes.classList.add("hidden");
117
- }
118
- });
119
- });
120
-
121
- // CHANGE textarea для всез браузеров
122
- document.querySelectorAll("textarea").forEach(function (textarea) {
123
- if (textarea.addEventListener) {
124
- textarea.addEventListener(
125
- "input",
126
- function () {
127
- // event handling code for sane browsers
128
- checkTextareaLength(textarea, minLengthTextareaField);
129
- },
130
- false
131
- );
132
- } else if (textarea.attachEvent) {
133
- textarea.attachEvent("onpropertychange", function () {
134
- // IE-specific event handling code
135
- checkTextareaLength(textarea, minLengthTextareaField);
136
- });
137
- }
138
- });
139
-
140
- async function submitForm(form){
141
- const btn = form.querySelector('[type="submit"]');
142
- const btnText = btn.value || btn.innerText;
143
- const agree = form.querySelector('[name="' + props.agreeSelector + '"]');
144
- const phone = form.querySelector('[name="phone"]');
145
- const dealer = form.querySelector('[name="dealer"]');
146
-
147
- if (!phoneChecker(phone)) {
148
- return;
149
- }
150
-
151
- if(dealer && dealer.hasAttribute('required')){
152
- if(!dealer.value){
153
- showErrorMes(form, '.dealer', 'Выберите дилерский центр');
154
- return;
155
- }
156
- }
157
-
158
- if (props.validation && typeof props.validation === 'function') {
159
- props.validation(form);
160
- }
161
-
162
- // если флажок не установлен - фронт
163
- if (!agree.checked) {
164
- showErrorMes(form, "." + props.agreeSelector, "Чтобы продолжить, установите флажок");
165
- return;
166
- }
167
-
168
- stateBtn(btn, "Отправляем...", true);
169
-
170
- // Отпрвка цели что форма submit только после всех проверок
171
- reachGoal("form_submit");
172
-
173
- let formData = new FormData(form);
174
- let sendMailCookie = props.sendMailCookie;
175
- if(formData.get('dealer')) {
176
- sendMailCookie += "_" + formData.get('dealer');
177
- }
178
- if(getCookie('fta')) {
179
- formData.append("fta", true);
180
- }
181
- if(getCookie('__gtm_campaign_url')) {
182
- let source = new URL(getCookie('__gtm_campaign_url'));
183
- source.search.slice(1).split("&").forEach(function(pair) {
184
- let param = pair.split("=");
185
- formData.append(param[0], param[1]);
186
- });
187
- }
188
- formData.append(
189
- "page_url",
190
- window.location.origin + window.location.pathname
191
- );
192
-
193
- if(typeof window.re != 'undefined') {
194
- formData.append("re", window.re);
195
- }
196
-
197
- window.location.search
198
- .slice(1)
199
- .split("&")
200
- .forEach(function (pair) {
201
- let param = pair.split("=");
202
- if(formData.get(param[0])){
203
- formData.set(param[0], decodeURIComponent(param[1]));
204
- } else {
205
- formData.append(param[0], decodeURIComponent(param[1]));
206
- }
207
- });
208
-
209
- let formDataObj = {};
210
- try {
211
- // Отправка заявки на обратный возов в CallTouch
212
- if(props.ct_routeKey != '') {
213
- const requestData = await createRequest(props.ct_routeKey, phone.value, props.verbose);
214
- formData.append("ct_callback", true);
215
- formData.append("ctw_createRequest", JSON.stringify(requestData));
216
- } else {
217
- throw new Error('Empty ct_routeKey');
218
- }
219
- } catch (error) {
220
- if(props.ct_routeKey != '') {
221
- formData.append("ctw_createRequest", error);
222
- }
223
- props.verbose && console.error("Error during request Calltouch callback:", error);
224
- formDataObj = getFormDataObject(formData, form.id);
225
- }
226
-
227
- const params = new URLSearchParams([...formData]);
228
-
229
- await fetch(url, {
230
- method: "POST",
231
- mode: "cors",
232
- cache: "no-cache",
233
- credentials: "same-origin",
234
- headers: {
235
- "Content-Type": "application/x-www-form-urlencoded",
236
- },
237
- body: params,
238
- })
239
- .then((res) => res.json())
240
- .then((data) => {
241
- props.verbose && console.log(data);
242
- stateBtn(btn, btnText);
243
- if (data.answer == "required") {
244
- reachGoal("form_required");
245
- showErrorMes(form, data.field, data.message);
246
- return;
247
- } else if (data.answer == "error") {
248
- reachGoal("form_error");
249
-
250
- // Вызов callback_error при ошибке
251
- if (props.callback_error && typeof props.callback_error === 'function') {
252
- props.callback_error(data);
253
- } else if (messageModal) {
254
- showMessageModal(messageModal, errorIcon, errorText + "<br>" + data.error);
255
- }
256
- return;
257
- } else {
258
- if(data.attention != true) {
259
- reachGoal("form_success", formDataObj);
260
- }
261
- setCookie(sendMailCookie, true, {'domain': window.location.hostname,'path':'/','expires':600});
262
- // Вызов callback при успехе
263
- if (props.callback && typeof props.callback === 'function') {
264
- props.callback(data);
265
- } else if (messageModal) {
266
- showMessageModal(messageModal, successIcon, successText);
267
- }
268
- }
269
- form.reset();
270
- })
271
- .catch((error) => {
272
- reachGoal("form_error");
273
- console.error("Ошибка отправки данных формы: " + error);
274
- deleteCookie(sendMailCookie);
275
- // Вызов callback_error при ошибке
276
- if (props.callback_error && typeof props.callback_error === 'function') {
277
- props.callback_error(data);
278
- } else if (messageModal) {
279
- showMessageModal(messageModal, errorIcon, errorText + "<br>" + error);
280
- }
281
- stateBtn(btn, btnText);
282
- });
283
- return false;
284
- }
285
-
286
- async function sendForm(form) {
287
- let formData = new FormData(form);
288
- let sendMailCookie = props.sendMailCookie;
289
- if(formData.get('dealer')) {
290
- sendMailCookie += "_" + formData.get('dealer');
291
- }
292
- if (getCookie(sendMailCookie)) {
293
- const confirmModal = document.getElementById('confirm-modal');
294
- if (confirmModal) {
295
- 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>';
296
- confirmModal.classList.remove("hidden");
297
-
298
- const accept = confirmModal.querySelector('#accept-confirm');
299
- const acceptClose = confirmModal.querySelector('#accept-close');
300
-
301
- // Проверка на уже добавленный обработчик
302
- if (!accept.dataset.listenerAdded) {
303
- accept.dataset.listenerAdded = 'true';
304
- accept.addEventListener('click', async () => {
305
- // Закрываем модальное окно
306
- confirmModal.classList.add("hidden");
307
- // Удаляем куку
308
- deleteCookie(sendMailCookie);
309
- // Повторно отправляем форму
310
- await submitForm(form);
311
- return;
312
- });
313
- }
314
-
315
- // Проверка на уже добавленный обработчик
316
- if (!acceptClose.dataset.listenerAdded) {
317
- acceptClose.dataset.listenerAdded = 'true';
318
- acceptClose.addEventListener('click', () => {
319
- // Закрываем модальное окно
320
- const modals = document.querySelectorAll('.modal-overlay');
321
- form.reset();
322
- if (modals.length) {
323
- modals.forEach((modal) => modal.classList.add("hidden"));
324
- }
325
- confirmModal.classList.add("hidden");
326
- return;
327
- });
328
- }
329
- return;
330
- }
331
- }else{
332
- // Если куки нет, просто отправляем форму
333
- await submitForm(form);
334
- return;
335
- }
336
- }
337
-
338
- // Отправка всех форм
339
- document.querySelectorAll("form:not(.vue-form)").forEach((form) => {
340
- form.addEventListener('submit', async (event) => {
341
- event.preventDefault();
342
- await sendForm(form);
343
- })
344
- });
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
+ if (!phone.value.length) {
27
+ showErrorMes(form, ".phone", "Телефон является обязательным полем");
28
+ return false;
29
+ } else {
30
+ const phoneRe = new RegExp(/^\+7 [0-9]{3} [0-9]{3}-[0-9]{2}-[0-9]{2}$/);
31
+ if (!phoneRe.test(phone.value) || noValidPhone(phone.value)) {
32
+ showErrorMes(form, ".phone", "Введен некорректный номер телефона");
33
+ return false;
34
+ }
35
+ }
36
+ showErrorMes(form, ".phone", "");
37
+ return true;
38
+ };
39
+
40
+ // TEXTAREA
41
+ const minLengthTextareaField = 10; // минимальное кол-во символов
42
+ // проверка на минимальное кол-во символов и скрытие ошибки
43
+ const checkTextareaLength = (textarea, minLength) => {
44
+ if (textarea.value.length >= minLength) {
45
+ textarea.nextSibling.nextElementSibling.classList.add("hidden");
46
+ }
47
+ };
48
+
49
+ // BUTTON
50
+ // Состояние кнопки
51
+ const stateBtn = (btn, value, disable = false) => {
52
+ if (btn.tagName == 'INPUT') {
53
+ btn.value = value;
54
+ btn.disabled = disable;
55
+ } else {
56
+ btn.innerText = value;
57
+ if (disable) {
58
+ btn.setAttribute('disabled', true);
59
+ } else {
60
+ btn.removeAttribute('disabled');
61
+ }
62
+ }
63
+ };
64
+
65
+ export const showErrorMes = (form, el, text) => {
66
+ let field = form.querySelector(el);
67
+ field.innerText = text;
68
+ field.classList.remove("hidden");
69
+ };
70
+
71
+ export const showMessageModal = (messageModal, icon, message) => {
72
+ document.querySelectorAll(".modal-overlay").forEach((el) => {
73
+ el.classList.add("hidden");
74
+ });
75
+ if(messageModal){
76
+ messageModal.querySelector("#icon").innerHTML = icon;
77
+ messageModal.querySelector("p").innerHTML = message;
78
+ messageModal.classList.remove("hidden");
79
+ }
80
+ };
81
+
82
+ const propsParams = {
83
+ callback: null,
84
+ callback_error: null,
85
+ validation: null,
86
+ ct_routeKey: '',
87
+ confirmModalText: '',
88
+ verbose: false,
89
+ agreeSelector: "agree",
90
+ sendMailCookie: "SEND_MAIL",
91
+ }
92
+
93
+ export const errorIcon = '<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>';
94
+ export const successIcon = '<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>';
95
+ export const errorText = '<b class="text-bold block text-2xl mb-4">Упс!</b> Что-то пошло не так. Перезагрузите страницу и попробуйте снова. ';
96
+ export const successText = '<b class="text-bold block text-2xl mb-4">Спасибо!</b> В скором времени мы свяжемся с Вами!';
97
+ export const messageModal = document.getElementById("message-modal");
98
+
99
+ export const connectForms = (url, props = propsParams) => {
100
+ props = {...propsParams, ...props};
101
+
102
+ document.querySelectorAll("input[name=phone]").forEach(function (element) {
103
+ // element.addEventListener("focus", maskphone);
104
+ element.addEventListener("input", maskphone);
105
+ element.addEventListener("change", () => phoneChecker(element));
106
+ });
107
+
108
+ // AGREE CHECKBOX
109
+ // Проверка на состояние чекбокса, показ/скрытие ошибки
110
+ document.querySelectorAll("input[name=" + props.agreeSelector + "]").forEach(function (element) {
111
+ let errorMes = element.parentElement.querySelector("." + props.agreeSelector);
112
+ element.addEventListener("change", (e) => {
113
+ if (!e.target.checked) {
114
+ errorMes.classList.remove("hidden");
115
+ } else {
116
+ errorMes.classList.add("hidden");
117
+ }
118
+ });
119
+ });
120
+
121
+ // CHANGE textarea для всез браузеров
122
+ document.querySelectorAll("textarea").forEach(function (textarea) {
123
+ if (textarea.addEventListener) {
124
+ textarea.addEventListener(
125
+ "input",
126
+ function () {
127
+ // event handling code for sane browsers
128
+ checkTextareaLength(textarea, minLengthTextareaField);
129
+ },
130
+ false
131
+ );
132
+ } else if (textarea.attachEvent) {
133
+ textarea.attachEvent("onpropertychange", function () {
134
+ // IE-specific event handling code
135
+ checkTextareaLength(textarea, minLengthTextareaField);
136
+ });
137
+ }
138
+ });
139
+
140
+ async function submitForm(form){
141
+ const btn = form.querySelector('[type="submit"]');
142
+ const btnText = btn.value || btn.innerText;
143
+ const agree = form.querySelector('[name="' + props.agreeSelector + '"]');
144
+ const phone = form.querySelector('[name="phone"]');
145
+ const name = form.querySelector('[name="name"]');
146
+ const dealer = form.querySelector('[name="dealer"]');
147
+
148
+ if (!phoneChecker(phone)) {
149
+ return;
150
+ }
151
+
152
+ if(dealer && dealer.hasAttribute('required')){
153
+ if(!dealer.value){
154
+ showErrorMes(form, '.dealer', 'Выберите дилерский центр');
155
+ return;
156
+ }
157
+ }
158
+
159
+ if (props.validation && typeof props.validation === 'function') {
160
+ props.validation(form);
161
+ }
162
+
163
+ // если флажок не установлен - фронт
164
+ if (!agree.checked) {
165
+ showErrorMes(form, "." + props.agreeSelector, "Чтобы продолжить, установите флажок");
166
+ return;
167
+ }
168
+
169
+ stateBtn(btn, "Отправляем...", true);
170
+
171
+ // Отпрвка цели что форма submit только после всех проверок
172
+ reachGoal("form_submit");
173
+
174
+ let formData = new FormData(form);
175
+ let sendMailCookie = props.sendMailCookie;
176
+ if(formData.get('dealer')) {
177
+ sendMailCookie += "_" + formData.get('dealer');
178
+ }
179
+ if(getCookie('fta')) {
180
+ formData.append("fta", true);
181
+ }
182
+ if(getCookie('__gtm_campaign_url')) {
183
+ let source = new URL(getCookie('__gtm_campaign_url'));
184
+ source.search.slice(1).split("&").forEach(function(pair) {
185
+ let param = pair.split("=");
186
+ formData.append(param[0], param[1]);
187
+ });
188
+ }
189
+ formData.append(
190
+ "page_url",
191
+ window.location.origin + window.location.pathname
192
+ );
193
+
194
+ if(typeof window.re != 'undefined') {
195
+ formData.append("re", window.re);
196
+ }
197
+
198
+ window.location.search
199
+ .slice(1)
200
+ .split("&")
201
+ .forEach(function (pair) {
202
+ let param = pair.split("=");
203
+ if(formData.get(param[0])){
204
+ formData.set(param[0], decodeURIComponent(param[1]));
205
+ } else {
206
+ formData.append(param[0], decodeURIComponent(param[1]));
207
+ }
208
+ });
209
+
210
+ let formDataObj = {};
211
+ try {
212
+ // Отправка заявки на обратный возов в CallTouch
213
+ if(props.ct_routeKey != '') {
214
+ const requestData = await createRequest(props.ct_routeKey, phone.value, name.value, props.verbose);
215
+ formData.append("ct_callback", true);
216
+ formData.append("ctw_createRequest", JSON.stringify(requestData));
217
+ } else {
218
+ throw new Error('Empty ct_routeKey');
219
+ }
220
+ } catch (error) {
221
+ if(props.ct_routeKey != '') {
222
+ formData.append("ctw_createRequest", error);
223
+ }
224
+ props.verbose && console.error("Error during request Calltouch callback:", error);
225
+ formDataObj = getFormDataObject(formData, form.id);
226
+ }
227
+
228
+ const params = new URLSearchParams([...formData]);
229
+
230
+ await fetch(url, {
231
+ method: "POST",
232
+ mode: "cors",
233
+ cache: "no-cache",
234
+ credentials: "same-origin",
235
+ headers: {
236
+ "Content-Type": "application/x-www-form-urlencoded",
237
+ },
238
+ body: params,
239
+ })
240
+ .then((res) => res.json())
241
+ .then((data) => {
242
+ props.verbose && console.log(data);
243
+ stateBtn(btn, btnText);
244
+ if (data.answer == "required") {
245
+ reachGoal("form_required");
246
+ showErrorMes(form, data.field, data.message);
247
+ return;
248
+ } else if (data.answer == "error") {
249
+ reachGoal("form_error");
250
+
251
+ // Вызов callback_error при ошибке
252
+ if (props.callback_error && typeof props.callback_error === 'function') {
253
+ props.callback_error(data);
254
+ } else if (messageModal) {
255
+ showMessageModal(messageModal, errorIcon, errorText + "<br>" + data.error);
256
+ }
257
+ return;
258
+ } else {
259
+ if(data.attention != true) {
260
+ reachGoal("form_success", formDataObj);
261
+ }
262
+ setCookie(sendMailCookie, true, {'domain': window.location.hostname,'path':'/','expires':600});
263
+ // Вызов callback при успехе
264
+ if (props.callback && typeof props.callback === 'function') {
265
+ props.callback(data);
266
+ } else if (messageModal) {
267
+ showMessageModal(messageModal, successIcon, successText);
268
+ }
269
+ }
270
+ form.reset();
271
+ })
272
+ .catch((error) => {
273
+ reachGoal("form_error");
274
+ console.error("Ошибка отправки данных формы: " + error);
275
+ deleteCookie(sendMailCookie);
276
+ // Вызов callback_error при ошибке
277
+ if (props.callback_error && typeof props.callback_error === 'function') {
278
+ props.callback_error(data);
279
+ } else if (messageModal) {
280
+ showMessageModal(messageModal, errorIcon, errorText + "<br>" + error);
281
+ }
282
+ stateBtn(btn, btnText);
283
+ });
284
+ return false;
285
+ }
286
+
287
+ async function sendForm(form) {
288
+ let formData = new FormData(form);
289
+ let sendMailCookie = props.sendMailCookie;
290
+ if(formData.get('dealer')) {
291
+ sendMailCookie += "_" + formData.get('dealer');
292
+ }
293
+ if (getCookie(sendMailCookie)) {
294
+ const confirmModal = document.getElementById('confirm-modal');
295
+ if (confirmModal) {
296
+ 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>';
297
+ confirmModal.classList.remove("hidden");
298
+
299
+ const accept = confirmModal.querySelector('#accept-confirm');
300
+ const acceptClose = confirmModal.querySelector('#accept-close');
301
+
302
+ // Проверка на уже добавленный обработчик
303
+ if (!accept.dataset.listenerAdded) {
304
+ accept.dataset.listenerAdded = 'true';
305
+ accept.addEventListener('click', async () => {
306
+ // Закрываем модальное окно
307
+ confirmModal.classList.add("hidden");
308
+ // Удаляем куку
309
+ deleteCookie(sendMailCookie);
310
+ // Повторно отправляем форму
311
+ await submitForm(form);
312
+ return;
313
+ });
314
+ }
315
+
316
+ // Проверка на уже добавленный обработчик
317
+ if (!acceptClose.dataset.listenerAdded) {
318
+ acceptClose.dataset.listenerAdded = 'true';
319
+ acceptClose.addEventListener('click', () => {
320
+ // Закрываем модальное окно
321
+ const modals = document.querySelectorAll('.modal-overlay');
322
+ form.reset();
323
+ if (modals.length) {
324
+ modals.forEach((modal) => modal.classList.add("hidden"));
325
+ }
326
+ confirmModal.classList.add("hidden");
327
+ return;
328
+ });
329
+ }
330
+ return;
331
+ }
332
+ }else{
333
+ // Если куки нет, просто отправляем форму
334
+ await submitForm(form);
335
+ return;
336
+ }
337
+ }
338
+
339
+ // Отправка всех форм
340
+ document.querySelectorAll("form:not(.vue-form)").forEach((form) => {
341
+ form.addEventListener('submit', async (event) => {
342
+ event.preventDefault();
343
+ await sendForm(form);
344
+ })
345
+ });
345
346
  }