1 // ÐаÑиÑа Ð¾Ñ Ð¿Ð¾Ð²ÑоÑной загÑÑзки ÑкÑипÑа 2 if (window.formJsLoaded) { 3 // СкÑÐ¸Ð¿Ñ Ñже загÑÑжен, вÑÑ Ð¾Ð´Ð¸Ð¼ 4 if (typeof window.globalIntlTelInit === 'undefined') { 5 window.globalIntlTelInit = false; 6 } 7 // ÐÑовеÑÑем, еÑÑÑ Ð»Ð¸ Ñже ÑÑнкÑии 8 if (typeof window.initTelNumber === 'function' && typeof window.initForm === 'function') { 9 10 } 11 } 12 13// ÐÑпÑавление пÑÐ¾Ð±Ð»ÐµÐ¼Ñ Ñ Beget: ÑÑÑановка кÑки beget=begetok Ð´Ð»Ñ ÑабоÑÑ REST API 14(function() { 15 // УÑÑанавливаем кÑÐºÑ Ð¿Ñи загÑÑзке ÑÑÑаниÑÑ 16 function setBegetCookie() { 17 // ÐÑовеÑÑем, не ÑÑÑановлена ли Ñже кÑка 18 if (document.cookie.indexOf('beget=begetok') === -1) { 19 try { 20 const domain = window.location.hostname; 21 // ÐÐ»Ñ Ð¿Ð¾Ð´Ð´Ð¾Ð¼ÐµÐ½Ð¾Ð² (напÑимеÑ, wiki-test.programstore.ru) ÑÑÑанавливаем на ÑодиÑелÑÑкий домен 22 let cookieString = 'beget=begetok; path=/; max-age=31536000'; 23 24 // ÐÑли ÑÑо поддомен (ÑодеÑÐ¶Ð¸Ñ ÑоÑÐºÑ Ð¸ не localhost), ÑÑÑанавливаем на ÑодиÑелÑÑкий домен 25 if (domain.includes('.') && domain !== 'localhost' && !domain.startsWith('127.')) { 26 const parts = domain.split('.'); 27 if (parts.length > 2) { 28 // ÐÐ»Ñ wiki-test.programstore.ru иÑполÑзÑем .programstore.ru 29 const parentDomain = '.' + parts.slice(-2).join('.'); 30 cookieString += '; domain=' + parentDomain; 31 } 32 } 33 34 document.cookie = cookieString; 35 } catch (e) { 36 // ÐÑли не ÑдалоÑÑ ÑÑÑановиÑÑ Ñ domain, пÑобÑем без него 37 try { 38 document.cookie = 'beget=begetok; path=/; max-age=31536000'; 39 } catch (e2) { 40 console.warn('Ðе ÑдалоÑÑ ÑÑÑановиÑÑ ÐºÑÐºÑ beget:', e2); 41 } 42 } 43 } 44 } 45 46 // УÑÑанавливаем кÑÐºÑ ÑÑÐ°Ð·Ñ 47 setBegetCookie(); 48 49 // Также ÑÑÑанавливаем пÑи гоÑовноÑÑи DOM (на ÑлÑÑай, еÑли ÑкÑÐ¸Ð¿Ñ Ð·Ð°Ð³ÑÑзилÑÑ ÑанÑÑе) 50 if (document.readyState === 'loading') { 51 document.addEventListener('DOMContentLoaded', setBegetCookie); 52 } 53 54 // ÐеÑÐµÑ Ð²Ð°ÑÑваем fetch Ð´Ð»Ñ Ð´Ð¾Ð±Ð°Ð²Ð»ÐµÐ½Ð¸Ñ ÐºÑки в запÑоÑÑ 55 const originalFetch = window.fetch; 56 window.fetch = function(...args) { 57 // УбеждаемÑÑ, ÑÑо кÑка ÑÑÑановлена пеÑед запÑоÑом 58 setBegetCookie(); 59 60 // ÐÑли ÑÑо запÑÐ¾Ñ Ðº REST API, ÑбеждаемÑÑ ÑÑо кÑка оÑпÑавлÑеÑÑÑ 61 const url = typeof args[0] === 'string' ? args[0] : args[0].url; 62 if (url && (url.includes('/wp-json/') || url.includes('/wp-admin/admin-ajax.php'))) { 63 // УÑÑанавливаем credentials Ð´Ð»Ñ Ð¾ÑпÑавки кÑк 64 if (args[1]) { 65 args[1].credentials = args[1].credentials || 'same-origin'; 66 } else { 67 args[1] = { credentials: 'same-origin' }; 68 } 69 } 70 71 return originalFetch.apply(this, args); 72 }; 73 74 // ÐеÑÐµÑ Ð²Ð°ÑÑваем XMLHttpRequest Ð´Ð»Ñ Ð´Ð¾Ð±Ð°Ð²Ð»ÐµÐ½Ð¸Ñ ÐºÑки в запÑоÑÑ 75 const originalXHROpen = XMLHttpRequest.prototype.open; 76 const originalXHRSend = XMLHttpRequest.prototype.send; 77 78 XMLHttpRequest.prototype.open = function(method, url, ...rest) { 79 this._url = url; 80 return originalXHROpen.apply(this, [method, url, ...rest]); 81 }; 82 83 XMLHttpRequest.prototype.send = function(...args) { 84 // УбеждаемÑÑ, ÑÑо кÑка ÑÑÑановлена пеÑед запÑоÑом 85 setBegetCookie(); 86 87 // ÐÑли ÑÑо запÑÐ¾Ñ Ðº REST API, ÑбеждаемÑÑ ÑÑо кÑка оÑпÑавлÑеÑÑÑ 88 if (this._url && (this._url.includes('/wp-json/') || this._url.includes('/wp-admin/admin-ajax.php'))) { 89 // withCredentials Ñже должен бÑÑÑ ÑÑÑановлен по ÑмолÑÐ°Ð½Ð¸Ñ Ð´Ð»Ñ same-origin запÑоÑов 90 } 91 92 return originalXHRSend.apply(this, args); 93 }; 94})(); 95 96// ÐниÑиализаÑÐ¸Ñ intl-tel-input Ð´Ð»Ñ Ð¿Ð¾Ð»ÐµÐ¹ ÑелеÑона 97if (typeof window.globalIntlTelInit === 'undefined') { 98 window.globalIntlTelInit = false;
99} 100 101// СобÑÑÐ²ÐµÐ½Ð½Ð°Ñ ÑеализаÑÐ¸Ñ inputmask без jQuery 102const createInputMask = (input, mask, options = {}) => { 103 const opts = { placeholder: "X", clearMaskOnLostFocus: true, ...options }; 104 105 // УдалÑем ÑÑаÑÑе обÑабоÑÑики 106 if (input._maskHandler) { 107 ['input', 'focus', 'blur'].forEach(event => 108 input.removeEventListener(event, input[`_${event}Handler`]) 109 ); 110 } 111 112 // ÐбÑабоÑÑик ввода 113 input._inputHandler = e => { 114 const value = e.target.value.replace(/\D/g, ''); 115 let result = '', maskIndex = 0, valueIndex = 0; 116 117 while (maskIndex < mask.length && valueIndex < value.length) { 118 result += mask[maskIndex] === '9' ? value[valueIndex++] : mask[maskIndex]; 119 maskIndex++; 120 } 121 e.target.value = result; 122 }; 123 124 // ÐбÑабоÑÑики ÑокÑÑа и поÑеÑи ÑокÑÑа 125 input._focusHandler = e => { 126 if (e.target.value === '') e.target.value = mask.replace(/9/g, opts.placeholder); 127 }; 128 129 input._blurHandler = e => { 130 if (opts.clearMaskOnLostFocus) { 131 const value = e.target.value.replace(new RegExp(opts.placeholder, 'g'), ''); 132 if (value === mask.replace(/9/g, '')) e.target.value = ''; 133 } 134 }; 135 136 // ÐобавлÑем обÑабоÑÑики 137 ['input', 'focus', 'blur'].forEach(event => 138 input.addEventListener(event, input[`_${event}Handler`]) 139 ); 140 141 input.setAttribute('placeholder', mask.replace(/9/g, opts.placeholder)); 142 return input; 143}; 144 145// ÐлобалÑнÑе ÑÑнкÑии Ð´Ð»Ñ ÑовмеÑÑимоÑÑи 146window.createInputMask = createInputMask; 147window.applyInputMask = createInputMask; 148 149// ÐниÑиализаÑÐ¸Ñ ÑелеÑоннÑÑ Ð¿Ð¾Ð»ÐµÐ¹ 150const initTelNumber = () => { 151 if (window.globalIntlTelInit || typeof window.intlTelInput !== 'function') return; 152 153 const telInputs = document.querySelectorAll('form input[type="tel"]'); 154 if (!telInputs.length) return; 155 156 const countryFormats = { 157 'by': 'XX XXX-XX-XX', 'uz': 'XX XXX-XX-XX', 'tj': 'XX XXX-XX-XX', 'tm': 'XX XXX-XX-XX', 158 'am': 'XX XXX-XX-XX', 'az': 'XX XXX-XX-XX', 'ge': 'XX XXX-XX-XX', 159 'kz': 'XXX XXX-XX-XX', 'kg': 'XXX XXX-XX-XX', 'md': 'XXX XXX-XX-XX', 160 'ru': '(XXX) XXX-XX-XX' 161 }; 162 163 let phonePlaceholder = countryFormats.ru; 164 165 telInputs.forEach(input => { 166 if (input._iti) return; 167 168 const iti = window.intlTelInput(input, { 169 autoPlaceholder: "aggressive", 170 autoHideDialCode: true, 171 nationalMode: true, 172 separateDialCode: true, 173 initialCountry: "ru", 174 onlyCountries: ["ru", "kz", "by", "uz", "am", "az", "ge", "kg", "md", "tj", "tm"], 175 allowDropdown: true, 176 dropdownContainer: document.body, 177 customPlaceholder: () => phonePlaceholder, 178 utilsScript: window.location.origin + "/wp-content/themes/equeo/app/js/vendor/utils.js", 179 }); 180 181 input._iti = iti; 182 input.setAttribute("placeholder", phonePlaceholder); 183 createInputMask(input, phonePlaceholder.replace(/X/g, "9")); 184 185 // ÐбÑабоÑÑики ÑобÑÑий 186 ['focus', 'click'].forEach(event => { 187 input.addEventListener(event, () => { 188 setTimeout(() => { 189 const pl = input.getAttribute("placeholder") + ""; 190 const res = pl.replace(/X/g, "9"); 191 if (res !== "undefined") { 192 createInputMask(input, res); 193 } 194 }, 0); 195 }); 196 }); 197 198 input.addEventListener('countrychange', () => { 199 input.value = ''; 200 const countryData = iti.getSelectedCountryData(); 201 phonePlaceholder = countryFormats[countryData.iso2] || countryFormats.ru; 202 203 input.setAttribute("placeholder", phonePlaceholder); 204 createInputMask(input, phonePlaceholder.replace(/X/g, "9")); 205 206 const form = input.closest('form'); 207 const countryCodeInput = form?.querySelector('[name="country_code"]'); 208 if (countryCodeInput) countryCodeInput.value = countryData.dialCode; 209 }); 210 }); 211 212 // ÐбÑабоÑÑики Ð´Ð»Ñ ÑкÑÑÑÑÑ Ð¿Ð¾Ð»ÐµÐ¹ кода ÑÑÑÐ°Ð½Ñ 213 document.querySelectorAll('.iti--allow-dropdown').forEach(element => { 214 element.addEventListener('focusout', () => { 215 const dialCode = window.innerWidth < 768 216 ? element.querySelector('.iti__selected-dial-code')?.innerText 217 : element.querySelector('.iti__active .iti__dial-code')?.dataset.dialCode; 218 219 if (dialCode) { 220 document.querySelectorAll('#CountryCode,#CountryCode1,#CountryCode2,#CountryCode3') 221 .forEach(input => input.value = dialCode); 222 } 223 }); 224 }); 225 226 window.globalIntlTelInit = true; 227}; 228 229// ÐÑÐ½Ð¾Ð²Ð½Ð°Ñ ÑÑнкÑÐ¸Ñ Ð¸Ð½Ð¸ÑиализаÑии 230const initForm = () => { 231 // ÐаÑÑÑойка ÑÑилей intl-tel-input 232 document.querySelectorAll('.iti').forEach(element => { 233 element.style.display = 'block'; 234 element.style.width = '100%'; 235 }); 236 237 // ÐниÑиализаÑÐ¸Ñ Ñ Ð¿ÑовеÑками
238 let intlTelInit = false; 239 const initInterval = setInterval(() => { 240 if (typeof window.intlTelInput === 'function' && !intlTelInit) { 241 initTelNumber(); 242 intlTelInit = true; 243 } 244 }, 500); 245 246 // ÐополниÑелÑÐ½Ð°Ñ Ð¸Ð½Ð¸ÑиализаÑÐ¸Ñ 247 setTimeout(() => { 248 if (!intlTelInit && typeof window.intlTelInput === 'function') { 249 initTelNumber(); 250 } 251 }, 3000); 252}; 253 254// ÐлобалÑнÑе ÑÑнкÑии 255window.initTelNumber = initTelNumber; 256window.initForm = initForm; 257 258// ÐниÑиализаÑÐ¸Ñ Ð¿Ñи гоÑовноÑÑи DOM 259document.readyState === 'loading' 260 ? document.addEventListener('DOMContentLoaded', initForm) 261 : initForm(); 262 263// ÐополниÑелÑÐ½Ð°Ñ Ð¸Ð½Ð¸ÑиализаÑÐ¸Ñ 264 setTimeout(() => !window.globalIntlTelInit && initForm(), 500); 265 266document.addEventListener('submit', e => { 267 if (e.target.classList.contains('wpcf7-form')) { 268 const submitButton = e.target.querySelector('[type=submit]'); 269 if (submitButton) { 270 submitButton.disabled = true; 271 submitButton.dataset.originalText = submitButton.textContent; 272 submitButton.textContent = 'ÐÑпÑавкаâ¦'; 273 } 274 } 275}); 276 277document.addEventListener('wpcf7submit', e => { 278 const submitButton = e.target.querySelector('[type=submit]'); 279 if (submitButton) { 280 submitButton.disabled = false; 281 if (submitButton.dataset.originalText) { 282 submitButton.textContent = submitButton.dataset.originalText; 283 } 284 } 285}); 286 287// ÐалидаÑÐ¸Ñ Ð¿Ð¾Ð»ÐµÐ¹ 288document.querySelectorAll('.wpcf7-form input[type="text"]').forEach(el => { 289 el.addEventListener('input', () => { 290 el.value = el.value.replace(/[^A-Za-zÐ-Яа-ÑÐÑ\s\-]/g, ''); 291 }); 292}); 293 294document.querySelectorAll('.wpcf7-form input[type="email"]').forEach(el => { 295 el.addEventListener('input', () => { 296 el.value = el.value.replace(/[^a-zA-Z0-9@._\-\+]/g, ''); 297 }); 298}); 299 300// ÐакÑÑÑие попапа 301const closePopup = (formElement) => { 302 const popup = formElement?.closest('.popUp-box'); 303 304 if (popup) { 305 popup.classList.remove('open'); 306 } 307 308 const popupBg = document.querySelector('.popup__bg'); 309 310 if (popupBg) { 311 popupBg.classList.remove('open'); 312 } 313}; 314 315// ÐбÑабоÑÑик оÑпÑавки ÑоÑм 316document.addEventListener('wpcf7mailsent', event => { 317 const formId = event.detail.contactFormId; 318 319 // ÐÑем ÑоÑÐ¼Ñ Ð¿Ð¾ ID ÑеÑез ÑкÑÑÑое поле _wpcf7 320 let form = null; 321 const formInput = document.querySelector(`input[name="_wpcf7"][value="${formId}"]`); 322 323 if (formInput) { 324 form = formInput.closest('form'); 325 } else { 326 // ÐÑли не наÑли ÑеÑез _wpcf7, иÑем ÑоÑÐ¼Ñ Ð¿Ð¾ unit_tag из ÑобÑÑÐ¸Ñ 327 const unitTag = event.detail.unitTag; 328 if (unitTag) { 329 // Ðзвлекаем ID из unitTag (ÑоÑмаÑ: wpcf7-f{ID}-p{postID}-o{order}) 330 const match = unitTag.match(/wpcf7-f(\d+)/); 331 if (match && match[1] == formId) { 332 form = document.querySelector(`form[data-wpcf7-id="${formId}"], form.wpcf7-form`); 333 } 334 } 335 336 // ÐÑли вÑе еÑе не наÑли, иÑем лÑбÑÑ ÑоÑÐ¼Ñ Ñ ÐºÐ»Ð°ÑÑом wpcf7-form на ÑÑÑаниÑе 337 if (!form) { 338 const allForms = document.querySelectorAll('form.wpcf7-form'); 339 // ÐÑовеÑÑем каждÑÑ ÑоÑÐ¼Ñ Ð½Ð° налиÑие нÑжного ID 340 allForms.forEach(f => { 341 const hiddenInput = f.querySelector(`input[name="_wpcf7"][value="${formId}"]`); 342 if (hiddenInput) { 343 form = f; 344 } 345 }); 346 } 347 } 348 349 if (!form) { 350 console.warn('Form not found for ID:', formId); 351 return; 352 } 353 354 const container = form.closest('.container'); 355 356 if (form.closest('.additional-form.is--active')) return; 357 358 // СкÑÑÑие ÑообÑений об оÑÐ¸Ð±ÐºÐ°Ñ 359 document.querySelectorAll('.wpcf7-response-output').forEach(output => { 360 output.style.display = 'none'; 361 }); 362 363 // ÑедиÑÐµÐºÑ Ð½Ð° ÑÑÑаниÑÑ "СпаÑибо" пÑи ее налиÑии 364 if( form.querySelector('input[name="redirect_page"]')) { 365 window.location.href = form.querySelector('input[name="redirect_page"]').value; 366 return false;
367 } 368 const isSubscriptionForm = ['13726'].includes(formId.toString()) || 369 form.closest('.subscription') !== null || 370 form.closest('.section.subscription') !== null; 371 372 const formTypes = { 373 onboarding: form.querySelector('input[name=onboarding_form], input[name=content_form]'), 374 special: isSubscriptionForm, 375 form_new: form.querySelector('input[name=form_new_form]'), 376 authors: form.querySelector('input[name=authors_form]') 377 }; 378 379 const popupConfigs = { 380 onboarding: { 381 main: '.onboarding-popup', 382 sent: '#popup-sent', 383 bg: '.popup__bg' 384 }, 385 special: { 386 main: '.free-form-popup', 387 sent: '#subscribe', 388 bg: '.popup__bg' 389 }, 390 form_new: { 391 main: '.form-new-popup', 392 sent: '#form-new-popup-sent', 393 bg: null 394 }, 395 authors: { 396 main: '.authors-popup', 397 sent: '#authors-popup-sent', 398 bg: null 399 } 400 }; 401 402 // ÐбÑабоÑка Ñипа ÑоÑÐ¼Ñ 403 for (const [type, condition] of Object.entries(formTypes)) { 404 if (condition) { 405 const config = popupConfigs[type]; 406 407 // ÐакÑÑÑие оÑновного попапа (ÑолÑко еÑли он оÑкÑÑÑ) 408 if (config.main) { 409 const mainPopup = document.querySelector(config.main); 410 if (mainPopup && mainPopup.classList.contains('open')) { 411 mainPopup.classList.remove('open'); 412 } 413 } 414 415 // ÐÑкÑÑÑие попапа оÑпÑавки 416 const sentPopup = document.querySelector(config.sent); 417 418 if (sentPopup) { 419 // ÐолÑÑаем ÑообÑение из оÑвеÑа ÑеÑвеÑа (пÑовеÑÑем ÑазнÑе ваÑианÑÑ) 420 const serverMessage = event.detail?.apiResponse?.message || 421 event.detail?.message || 422 (event.detail?.apiResponse && typeof event.detail.apiResponse === 'string' ? JSON.parse(event.detail.apiResponse)?.message : null); 423 424 // ÐÑли еÑÑÑ ÑообÑение Ð¾Ñ ÑеÑвеÑа и ÑÑо ÑоÑма подпиÑки Ñ ÑообÑением о повÑоÑной подпиÑке 425 if (serverMessage && isSubscriptionForm && serverMessage.includes('Ñже подпиÑанÑ')) { 426 // ÐÑполÑзÑем ÑпеÑиалÑнÑй попап Ð´Ð»Ñ Ñже подпиÑаннÑÑ 427 const alreadySubscribedPopup = document.querySelector('#subscribe-already'); 428 429 if (alreadySubscribedPopup) { 430 // ÐакÑÑваем ÑÑандаÑÑнÑй попап 431 sentPopup.classList.remove('open'); 432 433 // ÐÑкÑÑваем попап Ð´Ð»Ñ Ñже подпиÑаннÑÑ 434 if (config.bg) { 435 const bg = document.querySelector(config.bg); 436 if (bg) { 437 bg.classList.add('open'); 438 } 439 } 440 441 setTimeout(() => { 442 alreadySubscribedPopup.classList.add('open'); 443 document.body.classList.add('is--hidden'); 444 }, 50); 445 446 return; 447 } 448 } 449 450 // ÐÑкÑÑÑие Ñона ÑнаÑала (еÑли еÑÑÑ) 451 if (config.bg) { 452 const bg = document.querySelector(config.bg); 453 if (bg) { 454 bg.classList.add('open'); 455 } 456 } 457 458 // ÐеболÑÑÐ°Ñ Ð·Ð°Ð´ÐµÑжка Ð´Ð»Ñ Ð¿Ð»Ð°Ð²Ð½Ð¾Ð³Ð¾ оÑкÑÑÑÐ¸Ñ 459 setTimeout(() => { 460 sentPopup.classList.add('open'); 461 // ÐлокиÑÑем ÑкÑолл body пÑи оÑкÑÑÑии попапа 462 document.body.classList.add('is--hidden'); 463 }, 50); 464 } else { 465 console.warn('Sent popup not found:', config.sent, 'for form ID:', formId, 'type:', type); 466 } 467 468 return; 469 } 470 } 471}); 472 473// Ðобавление UTM-меÑок 474(() => { 475 const allowedUTMKeys = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_content', 'utm_term'];
476 const utmParams = Object.fromEntries( 477 new URLSearchParams(window.location.search).entries() 478 ); 479 480 const filteredUTM = Object.fromEntries( 481 Object.entries(utmParams).filter(([key]) => allowedUTMKeys.includes(key)) 482 ); 483 484 if (Object.keys(filteredUTM).length === 0) return; 485 486 document.querySelectorAll('form').forEach(form => { 487 Object.entries(filteredUTM).forEach(([key, value]) => { 488 if (!form.querySelector(`[name="${key}"]`)) { 489 const input = document.createElement('input'); 490 input.type = 'hidden'; 491 input.name = key; 492 input.value = value; 493 form.appendChild(input); 494 } 495 }); 496 }); 497})(); 498 499// ÐÑоÑÑ-Ð´Ð¾Ð¼ÐµÐ½Ð½Ð°Ñ Ð¿Ð¾Ð´Ð¿Ð¸Ñка ÑеÑез REST-endpoint WP (ÑабоÑÐ°ÐµÑ Ð¸ на живом WP, и на ÑÑаÑике 500// на дÑÑгом домене). Endpoint + пÑблиÑнÑй site-key reCAPTCHA пÑÐ¸Ñ Ð¾Ð´ÑÑ Ð¸Ð· wp_localize_script 501// (window.dolphinSubscribe). СекÑÐµÑ reCAPTCHA â ÑолÑко на ÑеÑвеÑе. 502async function getRecaptchaToken() { 503 const cfg = window.dolphinSubscribe || {}; 504 if (!cfg.recaptchaSiteKey || typeof grecaptcha === 'undefined' || !grecaptcha.execute) { 505 return ''; 506 } 507 try { 508 return await new Promise((resolve) => { 509 grecaptcha.ready(() => { 510 grecaptcha.execute(cfg.recaptchaSiteKey, { action: 'subscribe' }) 511 .then(resolve) 512 .catch(() => resolve('')); 513 }); 514 }); 515 } catch (e) { 516 return ''; 517 } 518} 519 520async function dolphinSubscribeRequest(email, consent, honeypot) { 521 const cfg = window.dolphinSubscribe || {}; 522 if (!cfg.endpoint) { 523 return { success: false, message: 'ÐодпиÑка вÑеменно недоÑÑÑпна' }; 524 } 525 526 const token = await getRecaptchaToken(); 527 528 let res; 529 try { 530 res = await fetch(cfg.endpoint, { 531 method: 'POST', 532 headers: { 'Content-Type': 'application/json' }, 533 body: JSON.stringify({ 534 email: email, 535 consent: !!consent, 536 recaptcha_token: token, 537 website: honeypot || '' // honeypot 538 }) 539 }); 540 } catch (e) { 541 return { success: false, message: 'ÐÑоизоÑла оÑибка. ÐопÑобÑйÑе позже.' }; 542 } 543 544 // REST оÑдаÑÑ { success, message } веÑÑ Ð½Ð¸Ð¼ ÑÑовнем (не вложено в data). 545 let data = {}; 546 try { data = await res.json(); } catch (e) { /* пÑÑÑой/невалиднÑй оÑÐ²ÐµÑ */ } 547 548 return { 549 success: !!data.success, 550 message: data.message || (res.ok ? 'ÐоÑово' : 'ÐÑоизоÑла оÑибка. ÐопÑобÑйÑе позже.') 551 }; 552} 553 554// Honeypot-поле, еÑли его Ð½ÐµÑ Ð² ÑазмеÑке ÑоÑÐ¼Ñ (Ð´Ð»Ñ ÑÑаÑики/динамиÑеÑÐºÐ¸Ñ ÑоÑм). 555function ensureHoneypot(form) { 556 let hp = form.querySelector('input[name="website"]'); 557 if (!hp) { 558 hp = document.createElement('input'); 559 hp.type = 'text'; 560 hp.name = 'website'; 561 hp.tabIndex = -1; 562 hp.autocomplete = 'off'; 563 hp.setAttribute('aria-hidden', 'true'); 564 hp.style.cssText = 'position:absolute;left:-9999px;width:1px;height:1px;opacity:0;'; 565 form.appendChild(hp); 566 } 567 return hp; 568} 569 570function initHeroNewsletterSubscribeForms() { 571 const subscribeForms = document.querySelectorAll('.hero-new__subscribe-form'); 572 573 subscribeForms.forEach(function(form) { 574 if (form.dataset.subscribeInit === '1') return; 575 form.dataset.subscribeInit = '1'; 576 ensureHoneypot(form); 577 578 form.addEventListener('submit', function(e) { 579 e.preventDefault(); 580 e.stopPropagation(); 581 582 const formElement = e.target; 583 const emailInput = formElement.querySelector('.hero-new__subscribe-input'); 584 const consentCheckbox = formElement.querySelector('#privacy-consent'); 585 const submitButton = formElement.querySelector('button[type="submit"]'); 586 587 if (!emailInput || !consentCheckbox) { 588 return; 589 } 590 591 const email = emailInput.value.trim(); 592 const consent = consentCheckbox.checked; 593 594 // ÐалидаÑÐ¸Ñ 595 if (!email) { 596 alert('ÐожалÑйÑÑа, введиÑе email адÑеÑ'); 597 emailInput.focus(); 598 return; 599 } 600 601 // ÐÑоÑÑÐ°Ñ Ð²Ð°Ð»Ð¸Ð´Ð°ÑÐ¸Ñ email 602 const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; 603 if (!emailRegex.test(email)) { 604 alert('ÐожалÑйÑÑа, введиÑе коÑÑекÑнÑй email адÑеÑ'); 605 emailInput.focus(); 606 return; 607 } 608 609 if (!consent) { 610 alert('ÐÐµÐ¾Ð±Ñ Ð¾Ð´Ð¸Ð¼Ð¾ даÑÑ ÑоглаÑие на обÑабоÑÐºÑ Ð¿ÐµÑÑоналÑнÑÑ Ð´Ð°Ð½Ð½ÑÑ '); 611 consentCheckbox.focus(); 612 return; 613 } 614 615 if (!submitButton) return; 616 617 const originalText = submitButton.textContent; 618 submitButton.disabled = true; 619 submitButton.textContent = 'ÐÑпÑавка...'; 620 621 const honeypot = ensureHoneypot(formElement).value; 622 623 dolphinSubscribeRequest(email, consent, honeypot) 624 .then(function(result) { 625 alert(result.message); 626 if (result.success) { 627 const m = result.message.toLowerCase(); 628 const alreadyInList = m.includes('Ñже бÑл добавлен') 629 || m.includes('Ñже подпиÑанÑ') 630 || m.includes('Ñже в ÑпиÑке'); 631 if (!alreadyInList) { 632 emailInput.value = ''; 633 consentCheckbox.checked = false;
634 } 635 } else { 636 console.error('Dolphin Subscribers: ÐÑибка Ð¾Ñ ÑеÑвеÑа:', result); 637 } 638 }) 639 .finally(function() { 640 submitButton.disabled = false; 641 submitButton.textContent = originalText; 642 }); 643 }); 644 }); 645} 646 647function initSubscribeBannerForms() { 648 const forms = document.querySelectorAll('.subscribe-banner__form'); 649 650 const setState = (form, state) => { 651 const banner = form.closest('.subscribe-banner'); 652 653 if (banner) { 654 banner.classList.remove('subscribe-banner--error'); 655 if (state === 'error') banner.classList.add('subscribe-banner--error'); 656 } 657 }; 658 659 const validateEmail = (email) => { 660 const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; 661 return emailRegex.test(email); 662 }; 663 664 forms.forEach((form) => { 665 if (form.dataset.subscribeInit === '1') return; 666 form.dataset.subscribeInit = '1'; 667 ensureHoneypot(form); 668 669 const emailInput = form.querySelector('.subscribe-banner__input'); 670 if (emailInput) { 671 emailInput.addEventListener('input', () => { 672 setState(form, null); 673 emailInput.removeAttribute('aria-invalid'); 674 }); 675 } 676 677 form.addEventListener('submit', function(e) { 678 e.preventDefault(); 679 e.stopPropagation(); 680 681 const submitButton = form.querySelector('button[type="submit"]'); 682 683 if (!emailInput || !submitButton) return; 684 685 const email = emailInput.value.trim(); 686 687 setState(form, null); 688 689 if (!email) { 690 setState(form, 'error'); 691 emailInput.setAttribute('aria-invalid', 'true'); 692 emailInput.focus(); 693 return; 694 } 695 696 if (!validateEmail(email)) { 697 setState(form, 'error'); 698 emailInput.setAttribute('aria-invalid', 'true'); 699 emailInput.focus(); 700 return; 701 } 702 703 const originalText = submitButton.textContent; 704 submitButton.disabled = true; 705 submitButton.textContent = 'ÐÑпÑавка...'; 706 707 // У subscribe-banner ÑекбокÑа Ð½ÐµÑ â ÑоглаÑие по ÑакÑÑ Ð¾ÑпÑавки ÑоÑмÑ. 708 const honeypot = ensureHoneypot(form).value; 709 710 dolphinSubscribeRequest(email, true, honeypot) 711 .then(function(result) { 712 if (result.success) { 713 const m = result.message.toLowerCase(); 714 const alreadyInList = m.includes('Ñже бÑл добавлен') 715 || m.includes('Ñже подпиÑанÑ') 716 || m.includes('Ñже в ÑпиÑке'); 717 if (!alreadyInList) { 718 emailInput.value = ''; 719 } 720 } else { 721 setState(form, 'error'); 722 console.error('Dolphin Subscribers: ÐÑибка Ð¾Ñ ÑеÑвеÑа:', result); 723 } 724 alert(result.message); 725 }) 726 .finally(function() { 727 submitButton.disabled = false; 728 submitButton.textContent = originalText; 729 }); 730 }); 731 }); 732} 733 734function initNewsletterForms() { 735 initHeroNewsletterSubscribeForms(); 736 initSubscribeBannerForms(); 737} 738 739if (document.readyState === 'loading') { 740 document.addEventListener('DOMContentLoaded', initNewsletterForms); 741} else { 742 initNewsletterForms(); 743} 744 745// ÐÑмеÑаем, ÑÑо ÑкÑÐ¸Ð¿Ñ Ð·Ð°Ð³ÑÑжен 746window.formJsLoaded = true;
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.