PageSourceSearch

https://altesa.ru/local/templates/altesa/js/orderform.js?17618135077841

js altesa.ru collected 2026-10-08 13:42:43 UTC 7,841 bytes, 215 lines download raw bytes

1document.addEventListener('DOMContentLoaded', function () {
2  // reCAPTCHA ключ (v3). Замените на свой:
3  const siteKey = '6LfsZr4qAAAAAKkDvpFQaP5qsRrp4nJOENhnpX6l';
4
5  function showFormMessage(form, message, isSuccess = false) {
6    let resultBlock = form.querySelector('.cf-result');
7    if (!resultBlock) {
8      resultBlock = document.createElement('div');
9      resultBlock.classList.add('cf-result');
10      form.appendChild(resultBlock);
11    }
12    resultBlock.innerHTML = '';
13
14    const msgDiv = document.createElement('div');
15    msgDiv.classList.add('cf-notification');
16    msgDiv.classList.add(isSuccess ? 'cf-notification--success' : 'cf-notification--error');
17    msgDiv.textContent = message;
18
19    resultBlock.appendChild(msgDiv);
20  }
21
22  function getCookie(name) {
23    const matches = document.cookie.match(new RegExp(
24      "(?:^|; )" + name.replace(/([\.$?*|{}\(\)\[\]\\+^])/g, '\\$1') + "=([^;]*)"
25    ));
26    return matches ? decodeURIComponent(matches[1]) : "";
27  }
28
29  function getUrlParams() {
30    const params = {};
31    const query = window.location.search.substring(1);
32    if (!query) return params;
33    query.split('&').forEach(part => {
34      const [key, val] = part.split('=');
35      if (key) params[decodeURIComponent(key)] = decodeURIComponent(val || '');
36    });
37    return params;
38  }
39
40  function saveUTMToSessionStorage(params) {
41    ['utm_source', 'utm_medium', 'utm_campaign', 'utm_content', 'utm_term'].forEach(param => {
42      if (params[param]) {
43        sessionStorage.setItem(param, params[param]);
44      }
45    });
46  }
47
48  function getUTMFromSessionStorage() {
49    return {
50      utm_source: sessionStorage.getItem('utm_source') || '',
51      utm_medium: sessionStorage.getItem('utm_medium') || '',
52      utm_campaign: sessionStorage.getItem('utm_campaign') || '',
53      utm_content: sessionStorage.getItem('utm_content') || '',
54      utm_term: sessionStorage.getItem('utm_term') || '',
55    };
56  }
57
58
59  // Сохраняем UTM-метки в sessionStorage при первом визите
60  const urlParams = getUrlParams();
61  saveUTMToSessionStorage(urlParams);
62
63  // Получаем UTM-метки из sessionStorage
64  const utmParams = getUTMFromSessionStorage();
65
66  const forms = document.querySelectorAll('.cf-form');
67  if (!forms.length) return;
68
69  forms.forEach((form, formIndex) => {
70    console.log(`Инициализация формы #${formIndex + 1}`);
71
72    const phoneInputs = form.querySelectorAll('.cf-phone');
73    const nameInput = form.querySelector('[name="name"]');
74    const emailInput = form.querySelector('[name="email"]');
75    const msgInput = form.querySelector('[name="obr"]');
76
77    const metrikaFields = form.querySelectorAll('.metrika_client_id');
78    const roistatFields = form.querySelectorAll('.roistat');
79    const utmSourceFields = form.querySelectorAll('.utm_source');
80    const utmMediumFields = form.querySelectorAll('.utm_medium');
81    const utmCampaignFields = form.querySelectorAll('.utm_campaign');
82    const utmContentFields = form.querySelectorAll('.utm_content');
83    const utmTermFields = form.querySelectorAll('.utm_term');
84
85    const honeypotInput = form.querySelector('.nbf');
86    const recaptchaInput = form.querySelector('.recaptcha-token');
87
88    // Маски телефона
89    let imInstances = [];
90    if (phoneInputs.length && typeof Inputmask !== 'undefined') {
91      phoneInputs.forEach(phoneInput => {
92        const im = new Inputmask("+7 (999) 999-99-99");
93        im.mask(phoneInput);
94        imInstances.push(im);
95      });
96    }
97
98    // Заполняем поля UTM из sessionStorage
99    if (utmParams.utm_source) {
100      utmSourceFields.forEach(f => f.value = utmParams.utm_source);
101    }
102    if (utmParams.utm_medium) {
103      utmMediumFields.forEach(f => f.value = utmParams.utm_medium);
104    }
105    if (utmParams.utm_campaign) {
106      utmCampaignFields.forEach(f => f.value = utmParams.utm_campaign);
107    }
108    if (utmParams.utm_content) {
109      utmContentFields.forEach(f => f.value = utmParams.utm_content);
110    }
111    if (utmParams.utm_term) {
112      utmTermFields.forEach(f =>
112 f.value = utmParams.utm_term);
113    }
114
115    // Обработка отправки формы
116    form.addEventListener('submit', function (e) {
117      e.preventDefault();
118
119      // Проверка honeypot
120      if (honeypotInput && honeypotInput.value.trim() !== '') {
121        showFormMessage(form, 'Ошибка: подозрительная активность!', false);
122        return;
123      }
124
125      // Заполнение полей roistat / metrika
126      roistatFields.forEach(f => {
127        if (!f.value) f.value = getCookie('roistat_visit') || '';
128      });
129      metrikaFields.forEach(f => {
130        if (!f.value) f.value = getCookie('_ym_uid') || '';
131      });
132
133      // Проверяем обязательные поля
134      phoneInputs.forEach(inp => inp.classList.remove('error'));
135      if (nameInput) nameInput.classList.remove('error');
136      if (emailInput) emailInput.classList.remove('error');
137
138      let hasError = false;
139      phoneInputs.forEach((inp, i) => {
140        const val = inp.value.trim();
141        if (!val) {
142          showFormMessage(form, 'Поле "Телефон" обязательное.', false);
143          inp.classList.add('error');
144          hasError = true;
145        } else {
146          const im = imInstances[i];
147          if (im && inp.inputmask && !inp.inputmask.isComplete()) {
148            showFormMessage(form, 'Пожалуйста, введите полный номер телефона.', false);
149            inp.classList.add('error');
150            hasError = true;
151          }
152        }
153      });
154      if (hasError) return;
155
156      const formData = new FormData(form);
157
158      // Добавляем UTM-метки в formData
159      Object.entries(utmParams).forEach(([key, value]) => {
160        if (value) {
161          formData.set(key, value);
162        }
163      });
164
165      // Блокируем поля
166      form.classList.add('cf-form--loading');
167      const allFields = form.querySelectorAll('input, button, select, textarea:not([name="sessid"])');
168      allFields.forEach(fld => fld.disabled = true);
169
170      grecaptcha.ready(() => {
171        grecaptcha.execute(siteKey, { action: 'submit' }).then(token => {
172          formData.set('g_recaptcha_token', token);
173
174          fetch('/local/ajax/orderform_handler.php', {
175            method: 'POST',
176            body: formData
177          })
178            .then(resp => resp.json())
179            .then(data => {
180              if (data.status === 'success') {
181                  // Цель Я.Метрики
182              const goalName = form.dataset.ymGoal; 
183              if (goalName && typeof ym !== 'undefined') {
184                ym(83439094, 'reachGoal', goalName);
185              }
186                showFormMessage(form, data.message, true);
187                form.reset();
188
189                // Сброс масок
190                phoneInputs.forEach(inp => {
191                  if (inp.inputmask) inp.inputmask.remove();
192                });
193                imInstances = [];
194                phoneInputs.forEach(inp => {
195                  const newIM = new Inputmask("+7 (999) 999-99-99");
196                  newIM.mask(inp);
197                  imInstances.push(newIM);
198                });
199              } else {
200                showFormMessage(form, data.message, false);
201              }
202            })
203            .catch(err => {
204              console.error('Fetch error:', err);
205              showFormMessage(form, 'Произошла ошибка при отправке. Попробуйте позже.', false);
206            })
207            .finally(() => {
208              form.classList.remove('cf-form--loading');
209              allFields.forEach(fld => fld.disabled = false);
210            });
211        });
212      });
213    });
214  });
215});

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.