1(function() { 2 var NOVOFON_SCRIPT_SRC = 'https://widget.novofon.ru/novofon.js?k=05_xeUX36XdX3PbrlMNWhXSFAkADRo7G'; 3 var FDPOPUP_SCRIPT_SRC = 'https://feedback.flagishtoki.ru/js/widgets/popup.js?v=0.0.3'; 4 var THIRD_PARTY_TIMEOUT = 5000; 5 var scriptPromises = {}; 6 7 function hasNovofon() { 8 return Boolean(window.Novofon && typeof window.Novofon.openSiteRequestPanel === 'function'); 9 } 10 11 function hasFDPopup() { 12 return Boolean(window.FDPopup && typeof window.FDPopup.open === 'function'); 13 } 14 15 function waitForCondition(check, timeout) { 16 return new Promise(function(resolve, reject) { 17 var startedAt = Date.now(); 18 19 function step() { 20 if (check()) { 21 resolve(); 22 return; 23 } 24 25 if (Date.now() - startedAt >= timeout) { 26 reject(new Error('Third-party script timed out.')); 27 return; 28 } 29 30 window.setTimeout(step, 50); 31 } 32 33 step(); 34 }); 35 } 36 37 function getExistingScript(src) { 38 return document.querySelector('script[src="' + src + '"]'); 39 } 40 41 function ensureScript(src, readyCheck) { 42 if (readyCheck()) { 43 return Promise.resolve(); 44 } 45 46 if (scriptPromises[src]) { 47 return scriptPromises[src]; 48 } 49 50 scriptPromises[src] = new Promise(function(resolve, reject) { 51 var script = getExistingScript(src); 52 53 function waitForReady() { 54 waitForCondition(readyCheck, THIRD_PARTY_TIMEOUT).then(resolve).catch(reject); 55 } 56 57 if (script) { 58 script.addEventListener('load', waitForReady, { once: true }); 59 script.addEventListener('error', reject, { once: true }); 60 waitForReady(); 61 return; 62 } 63 64 script = document.createElement('script'); 65 script.async = true; 66 script.src = src; 67 script.dataset.flagishtokiLazy = 'true'; 68 script.addEventListener('load', waitForReady, { once: true }); 69 script.addEventListener('error', reject, { once: true }); 70 (document.head || document.documentElement).appendChild(script); 71 }).catch(function(error) { 72 delete scriptPromises[src]; 73 throw error; 74 }); 75 76 return scriptPromises[src]; 77 } 78 79 function ensureNovofonLoaded() { 80 return ensureScript(NOVOFON_SCRIPT_SRC, hasNovofon); 81 } 82 83 function ensureFDPopupLoaded() { 84 return ensureScript(FDPOPUP_SCRIPT_SRC, hasFDPopup); 85 } 86 87 function warmNovofonLoader() { 88 ensureNovofonLoaded().catch(function() { 89 return null; 90 }); 91 } 92 93 function warmFDPopupLoader() { 94 ensureFDPopupLoaded().catch(function() { 95 return null; 96 }); 97 } 98 99 function openCallbackWithFallback(fallbackUrl) { 100 var safeFallback = fallbackUrl || 'kontakty.html'; 101 102 ensureNovofonLoaded().then(function() { 103 try { 104 if (hasNovofon()) { 105 window.Novofon.openSiteRequestPanel(); 106 return; 107 } 108 } catch (error) { 109 // Fall back to the contacts page when the third-party callback widget fails. 110 } 111 112 window.location.href = safeFallback; 113 }).catch(function() { 114 window.location.href = safeFallback; 115 }); 116 117 return false; 118 } 119 120 function openFeedbackPopupWithFallback(element, formId) { 121 var popupId = Number(formId || (element && element.getAttribute('data-feedback-popup-id')) || 0); 122 var fallbackHref = element && element.getAttribute ? element.getAttribute('href') : ''; 123 var overlayOpacity = Number(element && element.getAttribute ? element.getAttribute('data-feedback-popup-overlay-opacity') : '0.1'); 124 var options = { 125 hideCloseBtn: false, 126 host: element && element.getAttribute ? (element.getAttribute('data-feedback-popup-host') || 'feedback.flagishtoki.ru') : 'feedback.flagishtoki.ru', 127 overlay: { 128 background: element && element.getAttribute ? (element.getAttribute('data-feedback-popup-overlay-background') || '#000000') : '#000000', 129 opacity: Number.isFinite(overlayOpacity) ? overlayOpacity : 0.1 130 } 131 }; 132 133 if (!popupId) { 134 return true; 135 } 136 137 ensureFDPopupLoaded().then(function() { 138 if (hasFDPopup()) { 139 window.FDPopup.open(popupId, options); 140 return; 141 } 142 143 if (fallbackHref) { 144 window.location.href = fallbackHref; 145 } 146 }).catch(function() { 147 if (fallbackHref) { 148 window.location.href = fallbackHref; 149 } 150 });
151 152 return false; 153 } 154 155 function bindWarmupTriggers(selector, handler) { 156 var nodes = document.querySelectorAll(selector); 157 158 Array.prototype.forEach.call(nodes, function(node) { 159 if (node.dataset.flagishtokiWarmBound === 'true') { 160 return; 161 } 162 163 node.dataset.flagishtokiWarmBound = 'true'; 164 node.addEventListener('pointerenter', handler, { once: true }); 165 node.addEventListener('focusin', handler, { once: true }); 166 node.addEventListener('touchstart', handler, { once: true, passive: true }); 167 }); 168 } 169 170 function loadDeferredIframe(iframe) { 171 if (!iframe || iframe.dataset.loaded === 'true') { 172 return; 173 } 174 175 var src = iframe.getAttribute('data-src'); 176 if (!src) { 177 return; 178 } 179 180 iframe.src = src; 181 iframe.dataset.loaded = 'true'; 182 } 183 184 function initYandexRatingBadges() { 185 var frames = Array.prototype.slice.call(document.querySelectorAll('.site-footer__ratingFrame[data-src]')); 186 187 if (!frames.length) { 188 return; 189 } 190 191 if ('IntersectionObserver' in window) { 192 var observer = new IntersectionObserver(function(entries) { 193 entries.forEach(function(entry) { 194 if (entry.isIntersecting) { 195 loadDeferredIframe(entry.target); 196 observer.unobserve(entry.target); 197 } 198 }); 199 }, { 200 rootMargin: '220px 0px' 201 }); 202 203 frames.forEach(function(frame) { 204 observer.observe(frame); 205 }); 206 return; 207 } 208 209 window.addEventListener('load', function() { 210 window.setTimeout(function() { 211 frames.forEach(loadDeferredIframe); 212 }, 1200); 213 }, { once: true }); 214 } 215 function ready(callback) { 216 if (document.readyState === 'loading') { 217 document.addEventListener('DOMContentLoaded', callback, { once: true }); 218 return; 219 } 220 221 callback(); 222 } 223 224 ready(function() { 225 window.flagishtokiOpenCallback = openCallbackWithFallback; 226 window.flagishtokiOpenFeedbackPopup = openFeedbackPopupWithFallback; 227 228 bindWarmupTriggers('[data-callback-trigger]', warmNovofonLoader); 229 bindWarmupTriggers('[data-feedback-popup-id]', warmFDPopupLoader); 230 231 var body = document.body; 232 var docEl = document.documentElement; 233 var shell = document.querySelector('.shell'); 234 var toggle; 235 var drawer; 236 var backdrop; 237 var isBound = false; 238 239 if (!body || !shell) { 240 return; 241 } 242 243 function buildMobileLayout() { 244 var existingHeader = document.querySelector('.mobile-header'); 245 var existingBackdrop = document.querySelector('.mobile-drawer-backdrop'); 246 var existingDrawer = document.getElementById('mobileDrawer'); 247 var aside; 248 var header; 249 250 if (!existingBackdrop) { 251 existingBackdrop = document.createElement('div'); 252 existingBackdrop.className = 'mobile-drawer-backdrop'; 253 existingBackdrop.setAttribute('data-mobile-menu-close', 'true'); 254 body.insertBefore(existingBackdrop, body.firstChild); 255 } 256 257 if (!existingDrawer) { 258 aside = document.createElement('aside'); 259 aside.className = 'mobile-drawer'; 260 aside.id = 'mobileDrawer'; 261 aside.setAttribute('aria-hidden', 'true'); 262 aside.innerHTML = '' + 263 '<div class="mobile-drawer__head">' + 264 '<div>' + 265 '<div class="mobile-drawer__title">ÐенÑ</div>' + 266 '<div class="mobile-drawer__subtitle">ÐÑÑÑÑÑй доÑÑÑп к Ñазделам и каÑÐ°Ð»Ð¾Ð³Ñ Ð¿ÑодÑкÑии.</div>' + 267 '</div>' + 268 '<button type="button" class="mobile-drawer__close" data-mobile-menu-close="true" aria-label="ÐакÑÑÑÑ Ð¼ÐµÐ½Ñ">Ã</button>' + 269 '</div>' + 270 '<a class="mobile-drawer__call" href="tel:+74956210144">+7 495 621-01-44<span>СвÑзаÑÑÑÑ Ñ Ð¼ÐµÐ½ÐµÐ´Ð¶ÐµÑом</span></a>' + 271 '<div class="mobile-drawer__section">' + 272 '<strong>ÐÑÑÑÑÑе ÑÑÑлки</strong>' + 273 '<ul class="mobile-drawer__links">' + 274 '<li><a href="produkciya.html">ÐÑодÑкÑиÑ</a></li>' + 275 '<li><a href="galereya.html">ÐалеÑеÑ</a></li>' + 276 '<li><a href="akcii-na-flagshtoki.html">ÐкÑии</a></li>' + 277 '<li><a target="_blank" rel="noopener noreferrer" data-feedback-popup-id="45182" data-feedback-popup-host="feedback.flagishtoki.ru" data-feedback-popup-overlay-background="#000000" data-feedback-popup-overlay-opacity="0.1" onclick="return window.flagishtokiOpenFeedbackPopup ? window.flagishtokiOpenFeedbackPopup(this, 45182) : true;" href="https://feedback.flagishtoki.ru/form/view/45182">ÐÑÑавиÑÑ Ð·Ð°ÑвкÑ</a></li>' + 278 '</ul>' + 279 '</div>' + 280 '<div class="mobile-drawer__section">' + 281 '<strong>ÐаÑалог</strong>' + 282 '<ul class="mobile-drawer__catalog">' + 283 '<li><a href="flagshtoki.html">ФлагÑÑоки</a></li>' + 284 '<li><a href="mobilnye-flagshtoki.html">ÐобилÑнÑе ÑлагÑÑоки</a></li>' + 285 '<li>
285<a href="kronshteyny-dlya-flagov.html">ÐÑонÑÑÐµÐ¹Ð½Ñ Ð´Ð»Ñ Ñлагов</a></li>' + 286 '<li><a href="pechat-flagov.html">ÐеÑаÑÑ Ñлагов</a></li>' + 287 '<li><a href="znamyona-i-gerby.html">Ðнамена, геÑбÑ</a></li>' + 288 '<li><a href="aksessuary-dlya-flagshtokov.html">ÐкÑеÑÑÑаÑÑ</a></li>' + 289 '<li><a href="ceny-na-flagshtoki-i-flagi.html">ЦенÑ</a></li>' + 290 '<li><a href="dostavka-flagshtokov.html">ÐоÑÑавка</a></li>' + 291 '<li><a href="ustanovka-flagshtokov.html">УÑÑановка</a></li>' + 292 '<li><a href="garantiya-na-flagshtoki.html">ÐаÑанÑиÑ</a></li>' + 293 '<li><a href="obsluzhivanie-i-remont-flagshtokov.html">ÐбÑлÑживание, ÑемонÑ</a></li>' + 294 '<li><a href="tehnicheskaya-dokumentaciya-na-flagshtoki.html">ÐокÑменÑаÑиÑ</a></li>' + 295 '<li><a href="arenda-flagshtokov.html">ÐÑенда</a></li>' + 296 '<li><a href="predlozhenie-o-sotrudnichestve.html">СоÑÑÑдниÑеÑÑво</a></li>' + 297 '<li><a href="o-kompanii.html">Ркомпании</a></li>' + 298 '</ul>' + 299 '</div>'; 300 body.insertBefore(aside, shell); 301 } 302 303 if (!existingHeader) { 304 header = document.createElement('div'); 305 header.className = 'mobile-header'; 306 header.innerHTML = '' + 307 '<div class="mobile-header__bar">' + 308 '<div class="mobile-header__left">' + 309 '<button type="button" class="mobile-menu-toggle" id="mobileMenuToggle" data-mobile-menu-toggle="true" aria-controls="mobileDrawer" aria-expanded="false" aria-label="ÐÑкÑÑÑÑ Ð¼ÐµÐ½Ñ">' + 310 '<span></span>' + 311 '<span></span>' + 312 '<span></span>' + 313 '</button>' + 314 '<a class="mobile-brand" href="/">' + 315 '<strong>Флаги и ШÑоки</strong>' + 316 '<span>ФлагÑÑоки и Ñлаги Ñ Ð´Ð¾ÑÑавкой по РоÑÑии</span>' + 317 '</a>' + 318 '</div>' + 319 '<div class="mobile-header__right">' + 320 '<a class="mobile-phone-cta" href="tel:+74956210144">+7 495 621-01-44</a>' + 321 '</div>' + 322 '</div>' + 323 '<div class="mobile-header__utility">' + 324 '<div class="mobile-header__search">' + 325 '<div class="home-search home-search--mobile" data-home-search>' + 326 '<form class="home-search__form" action="search.html" method="get" role="search" novalidate>' + 327 '<label class="page-title-hidden" for="mobile-search-query">ÐоиÑк по каÑалогÑ</label>' + 328 '<input class="home-search__field" id="mobile-search-query" type="search" name="q" value="" placeholder="ÐапÑимеÑ: ÑлагÑÑок, Ñлаг, кÑонÑÑейн" autocomplete="off">' + 329 '<button class="home-search__button" type="submit" aria-label="ÐайÑи"></button>' + 330 '</form>' + 331 '<ul class="home-search__results" data-home-search-results></ul>' + 332 '</div>' + 333 '</div>' + 334 '<button type="button" class="mobile-callback-cta" data-callback-trigger="true" data-callback-fallback="kontakty.html">ÐаказаÑÑ Ð·Ð²Ð¾Ð½Ð¾Ðº</button>' + 335 '</div>'; 336 shell.insertBefore(header, shell.firstChild); 337 } 338 } 339 340 function syncElements() { 341 toggle = document.getElementById('mobileMenuToggle'); 342 drawer = document.getElementById('mobileDrawer'); 343 backdrop = document.querySelector('.mobile-drawer-backdrop'); 344 Array.prototype.forEach.call(document.querySelectorAll('.mobile-callback-cta'), function(button) { 345 var fallbackUrl = button.getAttribute('data-callback-fallback') || 'kontakty.html'; 346 347 button.setAttribute('data-callback-fallback', fallbackUrl); 348 button.setAttribute('data-callback-trigger', 'true'); 349 button.removeAttribute('onclick'); 350 351 if (button.dataset.callbackBound === 'true') { 352 return; 353 } 354 355 button.addEventListener('click', function(event) { 356 event.preventDefault(); 357 openCallbackWithFallback(fallbackUrl); 358 }); 359 button.dataset.callbackBound = 'true'; 360 }); 361 362 if (toggle && !toggle.hasAttribute('data-mobile-menu-toggle')) { 363 toggle.setAttribute('data-mobile-menu-toggle', 'true'); 364 } 365 } 366 367 function setMenuState(isOpen) { 368 if (!toggle || !drawer) { 369 return; 370 } 371 372 body.classList.toggle('mobile-menu-open', isOpen); 373 docEl.classList.toggle('mobile-menu-open', isOpen); 374 toggle.classList.toggle('is-active', isOpen); 375 toggle.setAttribute('aria-expanded', isOpen ? 'true' : 'false'); 376 drawer.setAttribute('aria-hidden', isOpen ? 'false' : 'true'); 377 378 if (backdrop) { 379 backdrop.setAttribute('aria-hidden', isOpen ? 'false' : 'true'); 380 } 381 } 382 383 function bindInteractions() { 384 if (isBound) { 385 return; 386 } 387 388 document.addEventListener('click', function(event) { 389 var toggleTarget = event.target.closest('[data-mobile-menu-toggle]'); 390 var closeTarget = event.target.closest('[data-mobile-menu-close]'); 391 var linkTarget = drawer && event.target.closest('#mobileDrawer a'); 392 393 if (toggleTarget) { 394 event.preventDefault(); 395 setMenuState(!body.classList.contains('mobile-menu-open')); 396 return; 397 } 398 399 if (closeTarget || linkTarget) { 400 setMenuState(false); 401 } 402 }); 403 404 document.addEventListener('keydown', function(event) { 405 if (event.key === 'Escape') { 406 setMenuState(false); 407 } 408 }); 409 410 window.addEventListener('resize', function() { 411 if (window.innerWidth > 900) { 412 setMenuState(false); 413 } 414 }); 415 416 isBound = true; 417 } 418 419 buildMobileLayout(); 420 syncElements(); 421 initYandexRatingBadges();
422 423 if (!toggle || !drawer) { 424 return; 425 } 426 427 bindInteractions(); 428 setMenuState(false); 429 }); 430})();
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.