PageSourceSearch

https://intelcont.md/templates/shaper_helixultimate/js/custom.js?v=1789368112

js intelcont.md collected 2026-10-05 09:41:11 UTC 15,173 bytes, 667 lines download raw bytes

1// =========================================================
2// IntelCont Cookie Consent
3// =========================================================
4(function () {
5
6  function initIntelcontCookieConsent() {
7
8    const modal = document.getElementById('intelcont-cookie');
9
10    if (!modal) {
11      return;
12    }
13
14    const STORAGE_KEY = 'intelcont_cookie_consent';
15    const CONSENT_TTL = 24 * 60 * 60 * 1000;
16
17    const mainView = modal.querySelector('[data-cookie-view="main"]');
18    const settingsView = modal.querySelector('[data-cookie-view="settings"]');
19
20    const analyticsInput = document.getElementById('intelcont-cookie-analytics');
21    const marketingInput = document.getElementById('intelcont-cookie-marketing');
22
23
24    // =====================================================
25    // Чтение сохранённого выбора
26    // =====================================================
27    function readConsent() {
28
29      try {
30
31        const raw = localStorage.getItem(STORAGE_KEY);
32
33        if (!raw) {
34          return null;
35        }
36
37        const parsed = JSON.parse(raw);
38
39        if (!parsed || !parsed.timestamp) {
40          localStorage.removeItem(STORAGE_KEY);
41          return null;
42        }
43
44        if ((Date.now() - parsed.timestamp) >= CONSENT_TTL) {
45          localStorage.removeItem(STORAGE_KEY);
46          return null;
47        }
48
49        return parsed;
50
51      } catch (e) {
52        return null;
53      }
54    }
55
56
57    // =====================================================
58    // Google Consent Mode
59    // =====================================================
60    function updateGoogleConsent(analytics, marketing) {
61
62      window.dataLayer = window.dataLayer || [];
63
64      if (typeof window.gtag === 'function') {
65
66        window.gtag(
67          'consent',
68          'update',
69          {
70            analytics_storage: analytics ? 'granted' : 'denied',
71            ad_storage: marketing ? 'granted' : 'denied',
72            ad_user_data: marketing ? 'granted' : 'denied',
73            ad_personalization: marketing ? 'granted' : 'denied'
74          }
75        );
76      }
77
78      window.dataLayer.push({
79        event: 'intelcont_consent_update',
80        intelcont_analytics_consent: analytics ? 'granted' : 'denied',
81        intelcont_marketing_consent: marketing ? 'granted' : 'denied'
82      });
83    }
84
85
86    // =====================================================
87    // Сохранение выбора
88    // =====================================================
89    function writeConsent(choice, analytics, marketing) {
90
91      const payload = {
92        choice: choice,
93        analytics: analytics === true,
94        marketing: marketing === true,
95        timestamp: Date.now()
96      };
97
98      try {
99
100        localStorage.setItem(
101          STORAGE_KEY,
102          JSON.stringify(payload)
103        );
104
105      } catch (e) {
106        // Если localStorage недоступен,
107        // выбор будет действовать только до перезагрузки.
108      }
109
110      updateGoogleConsent(
111        payload.analytics,
112        payload.marketing
113      );
114
115      return payload;
116    }
117
118
119    // =====================================================
120    // Основной экран
121    // =====================================================
122    function showMain() {
123
124      if (mainView) {
125        mainView.hidden = false;
126      }
127
128      if (settingsView) {
129        settingsView.hidden = true;
130      }
131    }
132
133
134    // =====================================================
135    // Экран персонализации
136    // =====================================================
137    function showSettings() {
138
139      const saved = readConsent();
140
141      if (analyticsInput) {
142        analyticsInput.checked = saved
143          ? saved.analytics === true
144          : false;
145      }
146
147      if (marketingInput) {
148        marketingInput.checked = saved
149          ? saved.marketing === true
150          : false;
151      }
152
153      if (mainView) {
154        mainView.hidden = true;
155      }
156
157      if (settingsView) {
158        settingsView.hidden = false;
159      }
160
161      if (analyticsInput) {
162
163        window.setTimeout(function () {
164          analyticsInput.focus();
165        }, 20);
166      }
167    }
168
169
170    // =====================================================
171    // Открытие модального окна
172    // =====================================================
173    function openModal() {
174
175      modal.hidden = false;
176
177      document.documentElement.classList.add(
178        'intelcont-cookie-open'
179      );
180
181      document.body.classList.add(
182        'intelcont-cookie-open'
183      );
184
185      showMain();
186
187      const firstButton = modal.querySelector(
188        '[data-cookie-action="accept-all"]'
189      );
190
191      if (firstButton) {
192
193        window.setTimeout(function () {
194          firstButton.focus();
195        }, 50);
196      }
197    }
198
199
200    // =====================================================
201    // Закрытие модального окна
202    // =====================================================
203    function closeModal() {
204
205      modal.hidden = true;
206
207      document.documentElement.classList.remove(
208        'intelcont-cookie-open'
209      );
210
211      document.body.classList.remove(
212        'intelcont-cookie-open'
213      );
214    }
215
216
217    // =====================================================
218    // Закрытие = только обязательные cookie
219    // =====================================================
220    function dismissAsNecessaryOnly() {
221
222      writeConsent(
223        'dismissed',
224        false,
225        false
226      );
227
228      closeModal();
229    }
230
231
232    // =====================================================
233    // Клики внутри окна
234    // =====================================================
235    modal.addEventListener('click', function (e) {
236
237      const actionButton = e.target.closest(
238        '[data-cookie-action]'
239      );
240
241      const closeTrigger = e.target.closest(
242        '[data-cookie-close]'
243      );
244
245
246      // ---------------------------------------------------
247      // Крестик / overlay
248      // ---------------------------------------------------
249      if (closeTrigger) {
250
251        e.preventDefault();
252
253        dismissAsNecessaryOnly();
254
255        return;
256      }
257
258
259      if (!actionButton) {
260        return;
261      }
262
263      e.preventDefault();
264
265      const action = actionButton.getAttribute(
266        'data-cookie-action'
267      );
268
269
270      // ---------------------------------------------------
271      // Разрешить всё
272      // ---------------------------------------------------
273      if (action === 'accept-all') {
274
275        writeConsent(
276          'all',
277          true,
278          true
279        );
280
281        closeModal();
282
283        return;
284      }
285
286
287      // ---------------------------------------------------
288      // Отклонить необязательные
289      // ---------------------------------------------------
290      if (action === 'reject-optional') {
291
292        writeConsent(
293          'necessary',
294          false,
295          false
296        );
297
298        closeModal();
299
300        return;
301      }
302
303
304      // ---------------------------------------------------
305      // Персонализировать
306      // ---------------------------------------------------
307      if (action === 'customize') {
308
309        showSettings();
310
311        return;
312      }
313
314
315      // ---------------------------------------------------
316      // Сохранить настройки
317      // ---------------------------------------------------
318      if (action === 'save-settings') {
319
320        writeConsent(
321          'custom',
322          analyticsInput
323            ? analyticsInput.checked
324            : false,
325          marketingInput
326            ? marketingInput.checked
327            : false
328        );
329
330        closeModal();
331
332        return;
333      }
334
335
336      // ---------------------------------------------------
337      // Назад
338      // ---------------------------------------------------
339      if (action === 'back') {
340
341        showMain();
342
343        return;
344      }
345    });
346
347
348    // =====================================================
349    // Закрытие по Escape
350    // =====================================================
351    document.addEventListener('keydown', function (e) {
352
353      if (modal.hidden) {
354        return;
355      }
356
357      if (e.key === 'Escape') {
358        dismissAsNecessaryOnly();
359      }
360    });
361
362
363    // =====================================================
364    // Проверка сохранённого consent
365    // =====================================================
366    const currentConsent = readConsent();
367
368
369    // =====================================================
370    // Если выбор уже сохранён
371    // =====================================================
372    if (currentConsent) {
373
374      updateGoogleConsent(
375        currentConsent.analytics === true,
376        currentConsent.marketing === true
377      );
378
379      return;
380    }
381
382
383    // =====================================================
384    // Выбора нет — показываем popup
385    // =====================================================
386    window.setTimeout(function () {
387      openModal();
388    }, 500);
389  }
390
391
392  // =======================================================
393  // Надёжный запуск
394  // =======================================================
395  if (document.readyState === 'loading') {
396
397    document.addEventListener(
398      'DOMContentLoaded',
399      initIntelcontCookieConsent
400    );
401
402  } else {
403
404    initIntelcontCookieConsent();
405  }
406
407})();
408
409
410// =========================================================
411// Existing IntelCont functionality
412// =========================================================
413jQuery(function ($) {
414
415  // ---------------------------------------------------------
416  // 1. Скролл к калькулятору
417  // ---------------------------------------------------------
418  $(
419    ".my-article-body #carousel_prices .item__carousel__button a, " +
420    ".my-article-body .tarif-none-mb a, " +
421    ".my-article-body .tarif-none a"
422  ).on("click", function (e) {
423
424    e.preventDefault();
425
426    const calculator = $("#cal");
427
428    if (!calculator.length) {
429      return;
430    }
431
432    const fix = ($(window).width() < 700)
433      ? 70
434      : 0;
435
436    $([
437      document.documentElement,
438      document.body
439    ]).animate({
440      scrollTop: calculator.offset().top - fix
441    }, 500);
442  });
443
444
445  // ---------------------------------------------------------
446  // 2. Debounce
447  // ---------------------------------------------------------
448  function debounce(fn, ms) {
449
450    let timer;
451
452    return function () {
453
454      clearTimeout(timer);
455
456      const args = arguments;
457      const context = this;
458
459      timer = setTimeout(function () {
460
461        fn.apply(
462          context,
463          args
464        );
465
466      }, ms);
467    };
468  }
469
470
471  // ---------------------------------------------------------
472  // 3. Блок цен
473  // ---------------------------------------------------------
474  const root = document.querySelector(
475    '#carousel_prices'
476  );
477
478  /*
479   * Если блока цен нет, прекращается только
480   * выполнение логики цен.
481   *
482   * Cookie-модалка выше работает независимо.
483   */
484  if (!root) {
485    return;
486  }
487
488
489  // ---------------------------------------------------------
490  // 4. Выравнивание карточек по рядам
491  // ---------------------------------------------------------
492  function alignPriceButtons() {
493
494    const items = Array.from(
495      root.querySelectorAll('.item')
496    ).filter(function (el) {
497
498      return !el.classList.contains(
499        'item__content-none-xl'
500      );
501    });
502
503
504    if (!items.length) {
505      return;
506    }
507
508
509    // -------------------------------------------------------
510    // Сбрасываем высоты
511    // -------------------------------------------------------
512    items.forEach(function (item) {
513
514      const body = item.querySelector(
515        '.card__body'
516      );
517
518      if (body) {
519        body.style.height = 'auto';
520      }
521    });
522
523
524    // -------------------------------------------------------
525    // Группируем карточки по вертикальному положению
526    // -------------------------------------------------------
527    const groups = new Map();
528
529    items.forEach(function (item) {
530
531      const top = item
532        .getBoundingClientRect()
533        .top;
534
535      const key =
536        Math.round(top / 10) * 10;
537
538      if (!groups.has(key)) {
539        groups.set(key, []);
540      }
541
542      groups
543        .get(key)
544        .push(item);
545    });
546
547
548    // -------------------------------------------------------
549    // Выравниваем высоту карточек внутри каждого ряда
550    // -------------------------------------------------------
551    groups.forEach(function (rowItems) {
552
553      let maxHeight = 0;
554
555      rowItems.forEach(function (item) {
556
557        const body = item.querySelector(
558          '.card__body'
559        );
560
561        if (!body) {
562          return;
563        }
564
565        maxHeight = Math.max(
566          maxHeight,
567          body.scrollHeight
568        );
569      });
570
571
572      rowItems.forEach(function (item) {
573
574        const body = item.querySelector(
575          '.card__body'
576        );
577
578        if (
579          body &&
580          maxHeight > 0
581        ) {
582
583          body.style.height =
584            maxHeight + 'px';
585        }
586      });
587    });
588  }
589
590
591  // ---------------------------------------------------------
592  // 5. Запуск выравнивания
593  // ---------------------------------------------------------
594  function runAlignment() {
595
596    window.requestAnimationFrame(
597      function () {
598
599        alignPriceButtons();
600
601      }
602    );
603  }
604
605
606  // ---------------------------------------------------------
607  // 6. Первичная инициализация
608  // ---------------------------------------------------------
609  runAlignment();
610
611  window.setTimeout(
612    runAlignment,
613    300
614  );
615
616  window.setTimeout(
617    runAlignment,
618    1000
619  );
620
621
622  // ---------------------------------------------------------
623  // 7. Resize
624  // ---------------------------------------------------------
625  $(window).on(
626    'resize',
627    debounce(
628      runAlignment,
629      120
630    )
631  );
632
633
634  // ---------------------------------------------------------
635  // 8. Owl Carousel
636  // ---------------------------------------------------------
637  $('.owl_prices').on(
638    'initialized.owl.carousel ' +
639    'refreshed.owl.carousel ' +
640    'resized.owl.carousel ' +
641    'translated.owl.carousel',
642    runAlignment
643  );
644
645
646  // ---------------------------------------------------------
647  // 9. MutationObserver
648  // ---------------------------------------------------------
649  if (window.MutationObserver) {
650
651    const observer = new MutationObserver(
652      debounce(
653        runAlignment,
654        80
655      )
656    );
657
658    observer.observe(
659      root,
660      {
661        childList: true,
662        subtree: true
663      }
664    );
665  }
666
667});

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.