1/* GonzoProxy landing â vanilla-ÑанÑайм вмеÑÑо jQuery + webflow.js. 2 * ÐомпоненÑÑ: Webflow.push-Ñим, w-nav (бÑÑгеÑ), w-dropdown, w-tabs, 3 * ÑоÑÐ¼Ñ (Webflow Forms API, на localhost â имиÑаÑÐ¸Ñ ÑÑÐ¿ÐµÑ Ð°), маÑкизÑ, 4 * days-select, плавнÑй ÑкÑолл к ÑкоÑÑм, плаваÑÑÐ°Ñ ÐºÐ½Ð¾Ð¿ÐºÐ° Telegram. */ 5(function () { 6 'use strict'; 7 8 var IS_LOCAL = /^(localhost|127\.|0\.0\.0\.0|192\.168\.)/.test(location.hostname) || location.hostname === ''; 9 var SITE_ID = '67b33c32bd5b234beac4a108'; 10 var MEDIUM = window.matchMedia('(max-width: 991px)'); 11 12 function ready(fn) { 13 if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', fn); 14 else fn(); 15 } 16 17 /* ---------- Webflow.push Ñим (инлайн-ÑкÑипÑÑ ÑайÑа пÑÑÐ°Ñ ÐºÐ¾Ð»Ð±Ñки) ---------- */ 18 var pushed = Array.isArray(window.Webflow) ? window.Webflow.slice() : []; 19 window.Webflow = { 20 push: function (fn) { ready(fn); }, 21 destroy: function () {}, ready: function () {}, require: function () { return null; } 22 }; 23 24 /* ---------- w-nav: мобилÑнÑй бÑÑÐ³ÐµÑ ---------- */ 25 function initNav() { 26 document.querySelectorAll('.w-nav').forEach(function (nav) { 27 var button = nav.querySelector('.w-nav-button'); 28 var menu = nav.querySelector('.w-nav-menu'); 29 if (!button || !menu) return; 30 var overlay = document.createElement('div'); 31 overlay.className = 'w-nav-overlay'; 32 overlay.setAttribute('data-wf-ignore', ''); 33 overlay.style.display = 'none'; 34 nav.appendChild(overlay); 35 var home = { parent: menu.parentNode, next: menu.nextSibling }; 36 var open = false; 37 38 function setOpen(state) { 39 if (state === open) return; 40 open = state; 41 if (open) { 42 overlay.appendChild(menu); 43 menu.setAttribute('data-nav-menu-open', ''); 44 overlay.style.display = 'block'; 45 button.classList.add('w--open'); 46 button.setAttribute('aria-expanded', 'true'); 47 } else { 48 menu.removeAttribute('data-nav-menu-open'); 49 home.parent.insertBefore(menu, home.next); 50 overlay.style.display = 'none'; 51 button.classList.remove('w--open'); 52 button.setAttribute('aria-expanded', 'false'); 53 } 54 } 55 56 button.setAttribute('role', 'button'); 57 button.setAttribute('aria-expanded', 'false'); 58 button.addEventListener('click', function () { setOpen(!open); }); 59 document.addEventListener('click', function (e) { 60 if (open && !nav.contains(e.target)) setOpen(false); 61 }); 62 document.addEventListener('keydown', function (e) { 63 if (e.key === 'Escape') setOpen(false); 64 }); 65 MEDIUM.addEventListener('change', function (e) { 66 if (!e.matches) setOpen(false); 67 }); 68 nav._navClose = function () { setOpen(false); }; 69 }); 70 } 71 72 /* ---------- w-dropdown: менÑ, ÑзÑк, FAQ и гео-аккоÑÐ´ÐµÐ¾Ð½Ñ ---------- */ 73 function initDropdowns() { 74 var dropdowns = Array.prototype.slice.call(document.querySelectorAll('.w-dropdown')); 75 // live (webflow.js) веÑÐ°ÐµÑ w--open ÑолÑко на toggle и list, коÑÐµÐ½Ñ Ð½Ðµ ÑÑÐ¾Ð³Ð°ÐµÑ 76 function isOpen(dd) { 77 var t = dd.querySelector('.w-dropdown-toggle'); 78 return !!(t && t.classList.contains('w--open')); 79 } 80 function close(dd) { 81 if (!isOpen(dd)) return; 82 var t = dd.querySelector('.w-dropdown-toggle'); 83 var l = dd.querySelector('.w-dropdown-list'); 84 if (t) { t.classList.remove('w--open'); t.setAttribute('aria-expanded', 'false'); } 85 if (l) l.classList.remove('w--open'); 86 dd.style.zIndex = ''; 87 if (window.GonzoIX2) window.GonzoIX2.notify('DROPDOWN_CLOSE', dd); 88 } 89 function openDd(dd) { 90 var t = dd.querySelector('.w-dropdown-toggle'); 91 var l = dd.querySelector('.w-dropdown-list'); 92 if (t) { t.classList.add('w--open'); t.setAttribute('aria-expanded', 'true'); } 93 if (l) l.classList.add('w--open'); 94 dd.style.zIndex = '901'; // как webflow.js на live 95 if (window.GonzoIX2) window.GonzoIX2.notify('DROPDOWN_OPEN', dd); 96 } 97 dropdowns.forEach(function (dd) { 98 var toggle = dd.querySelector('.w-dropdown-toggle'); 99 var list = dd.querySelector('.w-dropdown-list'); 100 if (!toggle || !list) return; 101 var hover = dd.getAttribute('data-hover') === 'true'; 102 toggle.setAttribute('aria-expanded', 'false'); 103 toggle.setAttribute('tabindex', '0'); 104 105 toggle.addEventListener('click', function () { 106 if (isOpen(dd)) close(dd); else openDd(dd); 107 }); 108 toggle.addEventListener('keydown', function (e) { 109 if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); toggle.click(); } 110 }); 111 if (hover) { 112 dd.addEventListener('mouseenter', function () { 113 if (!MEDIUM.matches) openDd(dd); 114 }); 115 dd.addEventListener('mouseleave', function () { 116 if (!MEDIUM.matches) close(dd); 117 }); 118 } 119 }); 120 document.addEventListener('click', function (e) { 121 dropdowns.forEach(function (dd) { 122 if (isOpen(dd) && !dd.contains(e.target)) close(dd); 123 }); 124 }); 125 document.addEventListener('keydown', function (e) { 126 if (e.key === 'Escape') dropdowns.forEach(close); 127 }); 128 } 129 130 /* ---------- w-tabs ---------- */ 131 function initTabs() { 132 document.querySelectorAll('.w-tabs').forEach(function (tabs) { 133 var links = tabs.querySelectorAll('.w-tab-link'); 134 var panes = tabs.querySelectorAll(':scope .w-tab-pane'); 135 // live (webflow.js): fade-out ÑекÑÑей панели (data-duration-out, деÑ. 100мÑ), 136 // заÑем Ñвап и fade-in новой (data-duration-in, деÑ. 300мÑ) 137 var durIn = parseInt(tabs.getAttribute('data-duration-in') || '300', 10); 138 var durOut = parseInt(tabs.getAttribute('data-duration-out') || '100', 10); 139 links.forEach(function (link) { 140 link.addEventListener('click', function (e) { 141 e.preventDefault(); 142 if (link.classList.contains('w--current')) return; 143 var name = link.getAttribute('data-w-tab'); 144 var prev = null; 145 links.forEach(function (l) { 146 if (l.classList.contains('w--current')) prev = l; 147 var cur = l === link; 148 l.classList.toggle('w--current', cur); 149 l.setAttribute('aria-selected', cur ? 'true' : 'false'); 150 }); 151 if (window.GonzoIX2) { 152 if (prev) window.GonzoIX2.notify('TAB_INACTIVE', prev); 153 window.GonzoIX2.notify('TAB_ACTIVE', link); 154 } 155 var current = null;
156 panes.forEach(function (p) { 157 if (p.classList.contains('w--tab-active')) current = p; 158 }); 159 function fadeInNew() { 160 panes.forEach(function (p) { 161 var active = p.getAttribute('data-w-tab') === name; 162 if (active) { 163 p.style.opacity = '0'; 164 p.classList.add('w--tab-active'); 165 requestAnimationFrame(function () { 166 p.style.transition = 'opacity ' + durIn + 'ms ease'; 167 p.style.opacity = '1'; 168 setTimeout(function () { p.style.transition = ''; p.style.opacity = ''; }, durIn + 30); 169 }); 170 } else { 171 p.classList.remove('w--tab-active'); 172 p.style.opacity = ''; 173 p.style.transition = ''; 174 } 175 }); 176 } 177 if (current && durOut > 0) { 178 current.style.transition = 'opacity ' + durOut + 'ms ease'; 179 current.style.opacity = '0'; 180 setTimeout(fadeInNew, durOut); 181 } else { 182 fadeInNew(); 183 } 184 }); 185 }); 186 }); 187 } 188 189 /* ---------- ФоÑмÑ: Webflow Forms API; на localhost â имиÑаÑÐ¸Ñ ÑÑÐ¿ÐµÑ Ð° ---------- */ 190 function initForms() { 191 document.querySelectorAll('.w-form form').forEach(function (form) { 192 form.addEventListener('submit', function (e) { 193 e.preventDefault(); 194 var wrap = form.closest('.w-form'); 195 var done = wrap.querySelector('.w-form-done'); 196 var fail = wrap.querySelector('.w-form-fail'); 197 function show(ok) { 198 if (ok) { 199 form.style.display = 'none'; 200 if (done) done.style.display = 'block'; 201 if (fail) fail.style.display = 'none'; 202 } else if (fail) { 203 fail.style.display = 'block'; 204 } 205 } 206 if (IS_LOCAL) { show(true); return; } 207 var params = new URLSearchParams(); 208 new FormData(form).forEach(function (v, k) { params.append('fields[' + k + ']', v); }); 209 params.append('name', form.getAttribute('data-name') || form.name || 'Form'); 210 params.append('pageId', form.getAttribute('data-wf-page-id') || ''); 211 params.append('elementId', form.getAttribute('data-wf-element-id') || ''); 212 params.append('source', location.href); 213 params.append('test', 'false'); 214 params.append('dolphin', 'false'); 215 fetch('https://webflow.com/api/v1/form/' + SITE_ID, { 216 method: 'POST', 217 headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, 218 body: params.toString() 219 }).then(function (r) { show(r.ok); }) 220 .catch(function () { show(false); }); 221 }); 222 }); 223 } 224 225 /* ---------- ÐаÑÐºÐ¸Ð·Ñ Ð»Ð¾Ð³Ð¾Ñипов (замена jquery.marquee) ---------- 226 * Ðивой ÑайÑ: wrapper 100000px, 2 копии float, margin-right 20px 227 * (rem-знаÑÐµÐ½Ð¸Ñ Ð¸Ð· конÑига плагин не паÑÑÐ¸Ñ -> деÑÐ¾Ð»Ñ 20px). 228 * Ðлип Ð´ÐµÐ»Ð°ÐµÑ Ð¡ÐÐЦÐЯ (overflow-hidden), не .logo-row â не ÑÑогаем overflow. */ 229 function initMarquee(selector, direction) { 230 document.querySelectorAll(selector).forEach(function (el) { 231 if (el._marqueeDone) return; 232 el._marqueeDone = true; 233 var inner = el.innerHTML; 234 el.innerHTML = ''; 235 var track = document.createElement('div'); 236 // ÑÑÑÑкÑÑÑа и клаÑÑÑ ÐºÐ°Ðº Ñ jquery.marquee: wrapper 100000px, копии .js-marquee float:left 237 track.className = 'js-marquee-wrapper gp-marquee-track gp-marquee-' + direction; 238 for (var i = 0; i < 2; i++) { 239 var part = document.createElement('div'); 240 part.className = 'js-marquee'; 241 part.style.marginRight = '20px'; 242 part.style.cssFloat = 'left'; 243 part.innerHTML = inner; 244 track.appendChild(part); 245 } 246 el.appendChild(track); 247 // как Ñ jquery.marquee: инлайновÑй transform-Ð±Ð°Ð·Ð¸Ñ (важно Ð´Ð»Ñ ÑаÑÑеÑизаÑии), 248 // duration = ÑиÑина_копии / ÑиÑина_конÑейнеÑа * 70.5s, задеÑжка 190Ð¼Ñ 249 track.style.transform = 'translateX(0px)'; 250 // jquery.marquee меÑÑÐµÑ ÐРзагÑÑзки каÑÑинок (ÑиÑÐ¸Ð½Ñ ÐºÐ°ÑÑоÑек ÑикÑиÑÐ¾Ð²Ð°Ð½Ñ CSS); 251 // повÑоÑнÑй Ð·Ð°Ð¼ÐµÑ Ð½Ð° window.load Ð·Ð°Ð½Ð¸Ð¶Ð°ÐµÑ ÑкоÑоÑÑÑ â меÑÑем один Ñаз, на rAF 252 var measure = function () { 253 var w = track.children[0].getBoundingClientRect().width + 20; 254 var cw = el.getBoundingClientRect().width; 255 if (!w || !cw) { requestAnimationFrame(measure); return; } 256 track.style.setProperty('--gp-shift', w + 'px'); 257 // ÑоÑмÑла jquery.marquee (ÑвеÑено Ñ live на 1280/1440): 258 // duration = 70.5s * (копиÑ+margin+конÑейнеÑ) / (2*конÑейнеÑ) 259 track.style.animationDuration = (((w + cw) / (2 * cw)) * 70.5).toFixed(3) + 's'; 260 track.style.animationDelay = '0.19s'; 261 }; 262 requestAnimationFrame(measure); 263 }); 264 } 265 266 function injectMarqueeCss() { 267 var style = document.createElement('style'); 268 style.textContent = 269 '.gp-marquee-track{width:100000px;' + 270 'animation:gp-marquee-left 70.5s linear infinite}' + 271 '.gp-marquee-track::after{content:"";display:table;clear:both}' + 272 '.gp-marquee-right{animation-name:gp-marquee-right}' + 273 '@keyframes gp-marquee-left{from{transform:translateX(0)}to{transform:translateX(calc(-1 * var(--gp-shift,50%)))}}' + 274 '@keyframes gp-marquee-right{from{transform:translateX(calc(-1 * var(--gp-shift,50%)))}to{transform:translateX(0)}}'; 275 document.head.appendChild(style); 276 } 277 278 /* ---------- days-select (доÑловно Ñ Ð¶Ð¸Ð²Ð¾Ð³Ð¾ ÑайÑа) ---------- */ 279 function initDaysSelect() { 280 var selectElements = document.querySelectorAll('.days-select');
281 selectElements.forEach(function (select) { 282 var targetId = select.getAttribute('data-target'); 283 var outputElement = document.getElementById(targetId); 284 if (!outputElement) return; 285 var lastOption = select.options[select.options.length - 1]; 286 select.value = lastOption.value; 287 updateOutput(outputElement, lastOption.value); 288 select.addEventListener('change', function () { 289 updateOutput(outputElement, this.value); 290 }); 291 }); 292 function updateOutput(el, value) { 293 if ('value' in el) el.value = value; 294 else el.textContent = value; 295 } 296 } 297 298 /* ---------- ÐлавнÑй ÑкÑолл к ÑкоÑÑм (ÑвеÑено Ñ live: Ñинал = ÑкоÑÑ â Ñ ÐµÐ´ÐµÑ, 299 длиÑелÑноÑÑÑ = диÑÑанÑÐ¸Ñ Ã 0.25мÑ, кÑÐ¸Ð²Ð°Ñ ~inOutCubic) ---------- */ 300 function initSmoothScroll() { 301 function easeInOutCubic(t) { 302 return t < 0.5 ? 4 * t * t * t : 1 - Math.pow(-2 * t + 2, 3) / 2; 303 } 304 document.addEventListener('click', function (e) { 305 var a = e.target.closest('a[href]'); 306 if (!a) return; 307 var href = a.getAttribute('href') || ''; 308 if (href.indexOf('#') === -1) return; 309 var url; 310 try { url = new URL(href, location.href); } catch (err) { return; } 311 if (url.origin !== location.origin) return; 312 var samePath = url.pathname.replace(/\/$/, '') === location.pathname.replace(/\/$/, ''); 313 if (!samePath || !url.hash) return; 314 var target = document.getElementById(url.hash.slice(1)); 315 if (!target) return; 316 e.preventDefault(); 317 var header = document.querySelector('.header'); 318 var offset = header ? header.offsetHeight : 0; 319 var from = window.scrollY; 320 var to = Math.max(0, target.getBoundingClientRect().top + window.scrollY - offset); 321 var dist = to - from; 322 var dur = Math.max(300, Math.abs(dist) * 0.25); 323 var t0 = performance.now(); 324 function stepFrame(now) { 325 var p = Math.min(1, (now - t0) / dur); 326 window.scrollTo(0, from + dist * easeInOutCubic(p)); 327 if (p < 1) requestAnimationFrame(stepFrame); 328 } 329 requestAnimationFrame(stepFrame); 330 history.replaceState(null, '', url.hash); 331 }); 332 } 333 334 /* ---------- ÐлаваÑÑÐ°Ñ ÐºÐ½Ð¾Ð¿ÐºÐ° Telegram (замена ÑаÑа SendPulse) ---------- */ 335 function initChatWidget() { 336 var s = document.createElement('script'); 337 s.async = true; 338 s.src = '/js/tg-fab.js?v=45dc9459'; 339 s.setAttribute('data-tg', 'GonzoProxy_bot'); 340 document.body.appendChild(s); 341 } 342 343 /* ---------- Cookiebot â ÑолÑко на боевом домене ---------- */ 344 function initCookiebot() { 345 if (IS_LOCAL) return; 346 var s = document.createElement('script'); 347 s.id = 'Cookiebot'; 348 s.src = 'https://consent.cookiebot.com/uc.js'; 349 s.setAttribute('data-cbid', 'f8ac1db1-c1c1-477d-a4fc-71a10aab62bb'); 350 s.setAttribute('data-blockingmode', 'auto'); 351 s.type = 'text/javascript'; 352 document.head.appendChild(s); 353 } 354 355 ready(function () { 356 injectMarqueeCss(); 357 if (window.GonzoIX2) window.GonzoIX2.init(); 358 initNav(); 359 initDropdowns(); 360 initTabs(); 361 initForms(); 362 initMarquee('.js-marquee', 'left'); 363 initMarquee('.js-marquee2', 'right'); 364 initDaysSelect(); 365 initSmoothScroll(); 366 initChatWidget(); 367 initCookiebot(); 368 pushed.forEach(function (fn) { try { fn(); } catch (err) { console.error(err); } }); 369 }); 370})();
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.