PageSourceSearch

https://www.gantuning.ru/blog/wp-content/themes/tuningblog/themes/gantuning/assets/js/custom.js?ver=0.0.2

js gantuning.ru collected 2026-10-07 23:02:46 UTC 16,549 bytes, 545 lines download raw bytes

1jQuery(document).ready(function ($) {
2  "use strict";
3  /* Закрыть плашку куки */
4  $(".js-close-cookie").click(function () {
5    $(".cooks-container").hide();
6    return false;
7  });
8  if ($(".cooks-container").length > 0) {
9    var expires = "";
10    var date = new Date();
11    date.setTime(date.getTime() + 30 * 24 * 60 * 60 * 1000);
12    expires = "; expires=" + date.toUTCString();
13    document.cookie = "user_allow_cookie=1" + expires + "; path=/";
14  }
15
16  // Обратный счетчик
17  function startCountdown($container) {
18    const endDateStr = $container.data("end");
19    const endDate = new Date(endDateStr.replace(/-/g, "/")).getTime();
20
21    if (isNaN(endDate)) {
22      console.error("Некорректная дата окончания:", endDateStr);
23      return;
24    }
25
26    const timer = setInterval(function () {
27      const now = new Date().getTime();
28      const distance = endDate - now;
29
30      if (distance < 0) {
31        clearInterval(timer);
32        $container.html("Время вышло!");
33        return;
34      }
35
36      const timeData = {
37        days: Math.floor(distance / (1000 * 60 * 60 * 24)),
38        hours: Math.floor(
39          (distance % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60)
40        ),
41        minutes: Math.floor((distance % (1000 * 60 * 60)) / (1000 * 60)),
42        seconds: Math.floor((distance % (1000 * 60)) / 1000),
43      };
44
45      $container.find("[data-countdown]").each(function () {
46        const type = $(this).data("countdown");
47        const value = timeData[type];
48        $(this).text(value < 10 ? `0${value}` : value);
49      });
50    }, 1000);
51  }
52
53  /* Кнопка "Показать больше отзывов" */
54  if ($(".js-show-more-video").length) {
55    $(".js-show-more-video").on("click", function (e) {
56      console.log($(".hidden-video").length);
57      if ($(".hidden-video").length) {
58        let stopShowing = false;
59        let showIndex = 0;
60        while (!stopShowing) {
61          $(".hidden-video").eq(0).removeClass("hidden-video").show();
62
63          showIndex++;
64
65          if (showIndex == 3 || !$(".hidden-video").length) stopShowing = true;
66        }
67      } else $(this).parent().parent().hide();
68
69      if (!$(".hidden-video").length) $(this).parent().parent().hide();
70    });
71  }
72
73  // Инициализируем все счётчики на странице
74  $("[data-countdown-container]").each(function () {
75    startCountdown($(this));
76  });
77
78  /* Редирект при изменении фильтров в отзывах */
79  $(".js-reviews-mark").on("change", function () {
80    window.location.href = $(".js-reviews-mark option:selected").val();
81  });
82
83  $(".js-reviews-model").on("change", function () {
84    window.location.href = $(".js-reviews-model option:selected").val();
85  });
86
87  /* Нажатие на машинку в шапке */
88  $(".header__top-car").on("click", function () {
89    if ($(this).hasClass("active") && $(this).attr("data-curl") != "") {
90      window.location.href = $(this).attr("data-curl");
91    } else window.location.href = "/chiptuning/";
92  });
93  /* Нажатие на корзину в шапке */
94  $(".header__top-basket").on("click", function () {
95    if ($(this).attr("data-curl") != "") {
96      window.location.href = $(this).attr("data-curl");
97    } else window.location.href = "/chiptuning/";
98  });
99
100  // Мобильное меню
101  $('[data-nav="trigger"]').on("click", function (e) {
102    $('[data-nav="nav"]').addClass("active");
103  });
104
105  $('[data-nav="close"]').on("click", function (e) {
106    $('[data-nav="nav"]').removeClass("active");
107  });
108
109  // Sliders
110  if ($(".js-slider").length) {
111    $(".js-slider").slick();
112  }
113
114  // Select customization
115  if ($(".js-select").length) {
116    $(".js-select").selectpicker();
117  }
118
119  // Запуск видео блока
120  if ($('[data-hand="elem"]').length) {
121    let VideoEl;
122
123    VideoEl = document.getElementById("hand-block-video");
124    VideoEl.autoplay = false;
125    VideoEl.pause();
126
127    let HandPos = $('[data-hand="elem"]').offset().top,
128      winHeight = $(window).height(),
129      scrollToHand = HandPos - winHeight,
130      HandPlayed = false;
131
132    $(window).on("scroll", function () {
133      let winScrollTop = $(this).scrollTop();
134      if (!HandPlayed) {
135        if (winScrollTop > scrollToHand) {
136          VideoEl = document.getElementById("hand-block-video");
137          VideoEl.play();
138          HandPlayed = true;
139        }
140      }
141    });
142
143    $('[data-hand="trigger"]').on("click", function (e) {
144      e.preventDefault();
145      VideoEl = document.getElementById("hand-block-video");
146      VideoEl.play();
147    });
148  }
149
150  function countNumber(el) {
151    let target_block = $("#green-target"); // Ищем блок
152    let blockStatus = true;
153
154    if (target_block.length)
155      $(window).scroll(function () {
156        let scrollEvent =
157          $(window).scrollTop() >
158          target_block.position().top - $(window).height();
159        if (scrollEvent && blockStatus) {
160          blockStatus = false; // Запрещаем повторное выполнение функции до следующей перезагрузки страницы.
161          $({ numberValue: 0 }).animate(
162            { numberValue: $(el).text() },
163            {
164              duration: 1000, // Скорость анимации, где 500 - 0.5 одной секунды, то есть 500 миллисекунд
165              easing: "linear",
166              step: function (val) {
167                $(el).html(Math.ceil(val)); // Блок, где необходимо сделать анимацию
168              },
169            }
170          );
171        }
172      });
173  }
174  countNumber(".num-pw");
175  countNumber(".num-hm");
176
177  // Когда доскроллили до нужного блока
178  function scrollToElement(target, item) {
179    let targetEl = $(target);
180    if (!targetEl.length) return;
181
182    let el = $(item);
183
184    $(window).on("scroll", function () {
185      if (el.hasClass("box-open")) return;
186
187      let winScrollTop = $(this).scrollTop(),
188        targetPos = targetEl.offset().top,
189        winHeight = $(window).height(),
190        scrollToElem = targetPos - winHeight;
191
192      if (winScrollTop > scrollToElem) {
193        el.addClass("box-open");
194      }
195    });
196  }
197
198  scrollToElement("#box", ".box");
199  scrollToElement("#green-target", ".power__line__green");
200
201  // Одинаковая высота колонок
202  function maxHeightFunc(el) {
203    let maxHeight = 0;
204    $(el).each(function () {
205      if ($(this).height() > maxHeight) {
206        maxHeight = $(this).height();
207      }
208    });
209    return $(el).height(maxHeight);
210  }
211
212  if ($(window).width() > 767) {
213    maxHeightFunc($(".tab--col"));
214  }
215
216  $(window).resize(function () {
217    if ($(window).width() > 767) {
218      maxHeightFunc($(".tab--col"));
219    } else {
220      $(".tab--col").height("auto");
221    }
222  });
223
224  // Разворот описаний под мобильными
225  $(".js-desripTrigger").on("click", function () {
226    $(this).toggleClass("active");
227    $(this).parents(".gan__group").toggleClass("active");
228  });
229
230  // Модалки из старого
231  $(document).on("click", "[data-prod]", function () {
232    let gtlBtn = $(this).attr("data-prod");
233    $("#" + gtlBtn + ", .gtl-data-popup, .overlay").addClass("active");
234    $("body").addClass("noscroll");
235    return false;
236  });
237
238  $(document).on("click", ".gtl-data-popup .close_btn, .overlay", function () {
239    $(".gtl-list, .gtl-data-popup, .overlay").removeClass("active");
240    $("body").removeClass("noscroll");
241  });
242
243  // Mask input
244  if ($("input[type=tel]").length) {
245    $("input[type=tel]").mask("+7 (999) 999-99-99");
246  }
247
248  // Слайдер инструкций
249
250  function slidersInstall() {
251    $(".js-slider-install-for").each(function (key, item) {
252      let sliderIdName = "slider" + key;
253      let sliderNavIdName = "sliderNav" + key;
254      this.id = sliderIdName;
255      $(".js-slider-install-nav")[key].id = sliderNavIdName;
256      let sliderId = "#" + sliderIdName;
257      let sliderNavId = "#" + sliderNavIdName;
258      $(sliderId).slick({
259        slidesToShow: 1,
260        slidesToScroll: 1,
261        infinite: false,
262        arrows: true,
263        asNavFor: sliderNavId,
264      });
265
266      $(sliderNavId).slick({
267        variableWidth: true,
268        asNavFor: sliderId,
269        dots: false,
270        arrows: false,
271        infinite: false,
272        focusOnSelect: true,
273      });
274    });
275  }
276
277  if ($(".js-slider-install-for").length) {
278    if ($(window).width() > 767) {
279      slidersInstall();
280    }
281
282    $(window).on("resize", function () {
283      if ($(window).width() > 767) {
284        slidersInstall();
285      } else {
286        $(".js-slider-install-for, .js-slider-install-nav").slick("unslick");
287      }
288    });
289  }
290
291  if ($(window).width() > 767) {
292    $('[data-bs-toggle="pill"]').on("shown.bs.tab", function (event) {
293      $(".js-slider-install-for, .js-slider-install-nav").slick("unslick");
294      slidersInstall();
295    });
296  }
297
298  $('[data-bs-toggle="pill"]').on("shown.bs.tab", function (event) {
299    setInstructionFile();
300  });
301
302  // Анимация селектов в первом блоке поиска авто
303  (function () {
304    let element = $(".b-main-form__select"),
305      activeElement = null;
306
307    element.on("click", function () {
308      if (activeElement && activeElement.is($(this))) {
309        $(this).removeClass("active");
310        activeElement = null;
311      } else {
312        element.removeClass("active");
313        $(this).addClass("active");
314        activeElement = $(this);
315      }
316    });
317
318    $(document).on("click", function (e) {
319      if (
320        activeElement &&
321        !$(e.target).closest(".b-main-form__select").length
322      ) {
323        activeElement.removeClass("active");
324        activeElement = null;
325      }
326    });
327  })();
328
329  // Показ карты на странице контактов
330
331  $("[data-triger-map]").on("click", function (e) {
332    e.preventDefault();
333    $(this).next(".contact__item__map").toggleClass("active");
334  });
335
336  // Плавная навигация
337
338  function smoothNav() {
339    if ($(window).width() < 768) {
340      $("[data-smooth-nav]").on("touchend", function (event) {
341        let id = $(this).attr("data-smooth-nav");
342        let target = $(id);
343        let top = target.offset().top;
344        $("html, body").animate({ scrollTop: top }, 500);
345      });
346    }
347  }
348
349  smoothNav();
350}); // end jQuery
351
352// Ленивая загрузка фона
353document.addEventListener("DOMContentLoaded", function () {
354  let lazyBackgrounds = [].slice.call(
355    document.querySelectorAll(".js-lazy-background")
356  );
357
358  if ("IntersectionObserver" in window) {
359    let lazyBackgroundObserver = new IntersectionObserver(function (
360      entries,
361      observer
362    ) {
363      entries.forEach(function (entry) {
364        if (entry.isIntersecting) {
365          entry.target.classList.add("visible");
366          lazyBackgroundObserver.unobserve(entry.target);
367        }
368      });
369    });
370
371    lazyBackgrounds.forEach(function (lazyBackground) {
372      lazyBackgroundObserver.observe(lazyBackground);
373    });
374  }
375});
376
377// Подгрузка youtube
378const lazyVideos = document.querySelectorAll("[data-video-id]");
379const onIntersection = (entries, observer) => {
380  entries.forEach((entry) => {
381    if (entry.isIntersecting) {
382      const videoId = entry.target.getAttribute("data-video-id");
383      const iframe = document.createElement("iframe");
384      iframe.setAttribute("src", `https://www.youtube.com/embed/${videoId}`);
385      iframe.setAttribute("frameborder", "0");
386      iframe.setAttribute("allowfullscreen", "1");
387      iframe.setAttribute("allow", "encrypted-media");
388      entry.target.parentNode.replaceChild(iframe, entry.target);
389      observer.unobserve(entry.target);
390    }
391  });
392};
393
394const observer = new IntersectionObserver(onIntersection, {
395  rootMargin: "0px 0px 200px 0px",
396  threshold: 0.1,
397});
398
399lazyVideos.forEach((video) => {
400  observer.observe(video);
401});
402
403// Подгрузка vimeo
404const onIntersectionVimeo = (entries, observer) => {
405  entries.forEach((entry) => {
406    if (entry.isIntersecting) {
407      const videoId = entry.target.getAttribute("data-vimeo-id");
408      const iframe = document.createElement("iframe");
409      iframe.setAttribute("src", `https://player.vimeo.com/video/${videoId}`);
410      iframe.setAttribute("frameborder", "0");
411      iframe.setAttribute("allowfullscreen", "1");
412      entry.target.parentNode.replaceChild(iframe, entry.target);
413      observer.unobserve(entry.target);
414    }
415  });
416};
417
418// Настройки Intersection Observer
419const observerOptionsVimeo = {
420  root: null,
421  rootMargin: "0px 0px 200px 0px",
422  threshold: 0.1,
423};
424
425// Создание экземпляра Intersection Observer
426const observerVimeo = new IntersectionObserver(
427  onIntersectionVimeo,
428  observerOptionsVimeo
429);
430
431// Находим все элементы с классом 'js-video-trigger'
432document.querySelectorAll("[data-vimeo-id]").forEach((video) => {
433  const videoId = video.getAttribute("data-vimeo-id");
434  observerVimeo.observe(video);
435});
436
437// Подгрузка rutube
438const onIntersectionRutube = (entries, observer) => {
439  entries.forEach((entry) => {
440    if (entry.isIntersecting) {
441      const videoId = entry.target.getAttribute("data-rutube-id");
442      const iframe = document.createElement("iframe");
443      iframe.setAttribute("src", `https://rutube.ru/play/embed/${videoId}/`);
444      iframe.setAttribute("frameborder", "0");
445      iframe.setAttribute("allowfullscreen", "1");
446      entry.target.parentNode.replaceChild(iframe, entry.target);
447      observer.unobserve(entry.target);
448    }
449  });
450};
451
452// Настройки Intersection Observer
453const observerOptionsRutube = {
454  root: null,
455  rootMargin: "0px 0px 200px 0px",
456  threshold: 0.1,
457};
458
459// Создание экземпляра Intersection Observer
460const observerRutube = new IntersectionObserver(
461  onIntersectionRutube,
462  observerOptionsRutube
463);
464
465// Находим все элементы с классом 'js-video-trigger'
466document.querySelectorAll("[data-rutube-id]").forEach((video) => {
467  const videoId = video.getAttribute("data-rutube-id");
468
469  observerRutube.observe(video);
470});
471
472// Tooltip
473
474const tooltipTriggerList = document.querySelectorAll(
475  '[data-bs-toggle="tooltip"]'
476);
477if (tooltipTriggerList.length) {
478  const tooltipList = [...tooltipTriggerList].map(
479    (tooltipTriggerEl) => new bootstrap.Tooltip(tooltipTriggerEl)
480  );
481}
482
483// FORM VALIDATION
484
485(function () {
486  "use strict";
487
488  let forms = document.querySelectorAll(".needs-validation");
489
490  Array.prototype.slice.call(forms).forEach(function (form) {
491    form.addEventListener(
492      "submit",
493      function (event) {
494        if (!form.checkValidity()) {
495          event.preventDefault();
496          event.stopPropagation();
497        }
498
499        form.classList.add("was-validated");
500      },
501      false
502    );
503  });
504})();
505
506// Активация по урлу таба (Инструкции)
507document.addEventListener("DOMContentLoaded", () => {
508  const hash = window.location.hash;
509
510  if (hash) {
511    const tabTrigger = document.querySelector(
512      `button[data-bs-target="${hash}"]`
513    );
514    if (tabTrigger) {
515      const bootstrapTab = new bootstrap.Tab(tabTrigger);
516      bootstrapTab.show();
517      setInstructionFile();
518    }
519  }
520
521  const elementsToAddHash = document.querySelectorAll(
522    ".install-switch__btn[data-bs-target]"
523  );
524
525  elementsToAddHash.forEach((element) => {
526    element.addEventListener("click", () => {
527      const newHash = element.dataset.bsTarget;
528      window.location.hash = newHash;
529    });
530  });
531});
532
533function setInstructionFile() {
534  if ($(".install-switch .active").attr("id") == "gt-tab") {
535    $(".instruction .instruction__title").attr(
536      "href",
537      "/themes/gantuning/assets/pdf/GAN-GT-RUS.pdf"
538    );
539  } else {
540    $(".instruction .instruction__title").attr(
541      "href",
542      "/themes/gantuning/assets/pdf/GAN-GA_GA+-RUS.pdf"
543    );
544  }
545}

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.