PageSourceSearch

https://www.gantuning.ru/themes/gantuning/assets/js/custom.js

js gantuning.ru collected 2026-10-07 23:02:29 UTC 17,300 bytes, 568 lines download raw bytes

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

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.