PageSourceSearch

https://gaz-time.ua/themes/mytheme/build/js/custom.js?v=21.08.2026.1

js gaz-time.ua collected 2026-09-30 14:35:35 UTC 97,231 bytes, 2,675 lines download raw bytes

1(function ($, Drupal) {
2  Drupal.behaviors.asd2eq = {
3    attach: function (context) {
4      if (typeof (initialized) == 'undefined') {
5        initialized = true;
6        // Код написанный здесь будет выполнен только один раз при загрузке страници
7
8        $(document).ajaxStart(function () {
9            $(".preloader--spin").addClass("js--active");
10          // disableScroll()
11        });
12        $(document).ajaxStop(function () {
13            $(".preloader--spin").removeClass("js--active");
14            // enableScroll()
15        });
16        
17        window.addEventListener(
18          "scroll",
19          () => {
20            if (document.querySelector(".js--lazyload")) {
21              document.querySelectorAll(".js--lazyload").forEach((el) => {
22                el.classList.remove("js--lazyload");
23              });
24            }
25          },
26          { once: true }
27        );
28        
29
30        $("#faq-accordion")
31          .on("show.bs.collapse", function (e) {
32            $(e.target).parent(".questions-item").addClass("js--active");
33          })
34          .on("hide.bs.collapse", function (e) {
35            $(e.target).parent(".questions-item").removeClass("js--active");
36          });
37        
38          const heroBannerSwiper = new Swiper(".hero-banner__left .swiper-container", {
39            navigation: {
40              nextEl: ".swiper-button-next",
41              prevEl: ".swiper-button-prev",
42            },
43            pagination: {
44              el: ".hero-banner__pagination",
45            },
46            watchSlidesVisibility: true,
47            autoplay: {
48              delay: 3000,
49              disableOnInteraction: false,
50            },
51            loop: true,
52          });
53        
54        const galleryLeft = document.querySelector(".photo-gallery__left .swiper-container")
55        const galleryRightDescription = document.querySelector('.photo-gallery__right-description .swiper-container')
56        
57        let galleryImages, galleryDescriptions
58        
59        if (galleryLeft) {
60          galleryImages = new Swiper(".photo-gallery__left .swiper-container", {
61            navigation: {
62              nextEl: ".swiper-button-next",
63              prevEl: ".swiper-button-prev",
64            },
65            watchSlidesVisibility: true,
66          });
67        }
68        
69        if (galleryRightDescription) {
70          galleryDescriptions = new Swiper(
71            ".photo-gallery__right-description .swiper-container",
72            {}
73          );
74        }
75        
76        const isPhotoGalleryInitialized = galleryImages 
77          && galleryImages instanceof Swiper 
78          && galleryDescriptions
79          && galleryDescriptions instanceof Swiper
80        
81        if (isPhotoGalleryInitialized) {
82          galleryDescriptions.controller.control = galleryImages;
83          galleryImages.controller.control = galleryDescriptions;
84        }
85        
86        const costCalcButton = document.querySelector('.cost-calculation-banner__button')
87        const gboInstallForm = document.querySelector('#gbo-install-form')
88        
89        if (costCalcButton && gboInstallForm) {
90          costCalcButton.addEventListener('click', (el) => {
91            el.preventDefault()
92            gboInstallForm.scrollIntoView({
93              behavior: 'auto'
94            })
95          })
96        }
97        
98        const thumbItem = $(".photo-gallery__right-nav .nav__item");
99        
100        if (isPhotoGalleryInitialized) {
101          galleryImages.on("slideChange", function () {
102            thumbItem.removeClass("js--active");
103            $(
104              `.photo-gallery__right-nav .nav__item[data-thumb=${galleryImages.activeIndex}]`
105            ).addClass("js--active");
106          });
107          
108          thumbItem.click(function () {
109            thumbItem.removeClass("js--active");
110            $(this).addClass("js--active");
111            galleryImages.slideTo($(this).data("thumb"), 1000, false);
112          });
113        }
114        
115        if (document.querySelector(".photo-gallery__right-nav .swiper-container")) {
116          const thumbsToSwiper = () => {
117            const breakpoint = window.matchMedia("(min-width:768px)");
118        
119            let mySwiper;
120            const breakpointChecker = function () {
121              if (breakpoint.matches) {
122                if (mySwiper !== undefined) mySwiper.destroy(true, true);
123              } else {
124                return enableSwiper();
125              }
126            };
127            const enableSwiper = () => {
128              mySwiper = new Swiper(".photo-gallery__right-nav .swiper-container", {
129                slidesPerView: 5.1,
130                paginationClickable: true,
131              });
132            };
133            breakpoint.addListener(breakpointChecker);
134            breakpointChecker();
135          };
136          thumbsToSwiper();
137        }
138        
139        var cliensSwiper = new Swiper(".clients__content-slider .swiper-container", {
140          grabCursor: true,
141          slidesPerView: "auto",
142          scrollbar: {
143            el: ".swiper-scrollbar",
144            hide: false,
145          },
146        });
147        
148        var certificatesSwiper = new Swiper(
149          ".certificates__content-slider .swiper-container",
150          {
151            grabCursor: true,
152            spaceBetween: 12,
153            slidesPerView: "auto",
154            scrollbar: {
155              el: ".swiper-scrollbar",
156              hide: false,
157            },
158          }
159        );
160        
161        var blogTeaserSwiper = new Swiper(".blog__teaser-items .swiper-container", {
162          grabCursor: true,
163          slidesPerView: "auto",
164          breakpoints: {
165            320: {
166              spaceBetween: 20,
167            },
168            1200: {
169              spaceBetween: 48,
170            },
171          },
172        });
173        
174        var reviewsSwiper = new Swiper(".paragraph__reviews-body .swiper-container", {
175          grabCursor: true,
176          slidesPerView: "auto",
177          freeMode: true,
178          breakpoints: {
179            320: {
180              spaceBetween: 20,
181            },
182            1200: {
183              spaceBetween: 36,
184            },
185          },
186        });
187        
188        var portfolioSwiper = new Swiper(
189          ".paragraph--portfolio .brands .swiper-container",
190          {
191            // grabCursor: true,
192            slidesPerView: "auto",
193            breakpoints: {
194              320: {
195                spaceBetween: 10,
196              },
197              1200: {
198                spaceBetween: 12,
199              },
200            },
201            scrollbar: {
202              el: ".swiper-scrollbar",
203              hide: false,
204            },
205          }
206        );
207        portfolioSwiper.on("slideChange", function () {
208          const target = this.slides[this.activeIndex].dataset.prop;
209          $(".paragraph--portfolio .letters__item").removeClass("js--active");
210          $(
211            `.paragraph--portfolio .letters__item[data-target-letter=${target}]`
212          ).addClass("js--active");
213        });
214        $(".paragraph--portfolio .letters__item").click(function () {
215          $(".paragraph--portfolio .letters__item").removeClass("js--active");
216          $(this).addClass("js--active");
217          const target = $(this).data("target-letter");
218          const slides = portfolioSwiper.slides;
219          portfolioSwiper.slideTo(
220            slides.findIndex((p) => p.dataset.letter === target),
221            1000,
222            false
223          );
224        });
225        
226        var portfolioLettersSwiper = new Swiper(
227          ".paragraph--portfolio .letters .swiper-container",
228          {
229            // grabCursor: true,
230            slidesPerView: "auto",
231          }
232        );
233        
234        new Tippy("#review-index", {
235          position: window.innerWidth <= 576 ? "top" : "top",
236          animation: "shift",
237          allowHTML: true,
238          arrow: "true",
239        });
240        
241        const bankTooltips = document.querySelectorAll(".banks__trigger");
242        if (bankTooltips) {
243          bankTooltips.forEach((p) => {
244            new Tippy(p, {
245              position: window.innerWidth <= 576 ? "top" : "top",
246              animation: "shift",
247              allowHTML: true,
248              arrow: "true",
249            });
250          });
251        }
252        if (document.querySelector(".paragraph--multiple-block")) {
253          const ps = new PerfectScrollbar(".paragraph--multiple-block", {
254            wheelSpeed: 1,
255            wheelPropagation: true,
256            swipeEasing: true,
257            minScrollbarLength: 20,
258            suppressScrollX: true,
259          });
260        }
261        
262        $(".paragraph--minor-text .showMore").click(function () {
263          $(this).parent(".text").toggleClass("collapsed");
264          $(this).toggleClass("js--active");
265          const target = $(this).parent(".text");
266          const top = $(target).offset().top;
267          $("body,html").animate({ scrollTop: top }, 1000);
268        });
269        
270        var gboPriceSwiper = new Swiper(
271          ".paragraph--gbo .paragraph__gbo-slider .swiper-container",
272          {
273            // grabCursor: true,
274            freeMode: true,
275            slidesPerView: "auto",
276            breakpoints: {
277              320: {
278                spaceBetween: 0,
279              },
280              768: {
281                spaceBetween: 48,
282              },
283            },
284          }
285        );
286        
287        var gboPriceSwiper = new Swiper(
288          ".paragraph--bank .paragraph__gbo-slider .swiper-container",
289          {
290            // grabCursor: true,
291            freeMode: true,
292            slidesPerView: "auto",
293            breakpoints: {
294              320: {
295                spaceBetween: 0,
296              },
297              768: {
298                spaceBetween: 48,
299              },
300            },
301          }
302        );
303        
304        $(".paragraph__gbo .paragraph__gbo-description .showMore").click(function () {
305          $(this).siblings(".description__content").toggleClass("collapsed");
306          $(this).toggleClass("js--active");
307        });
308        // gboPriceSwiper.on('transitionStart', function () {
309        //   const titles = $('.slider-head__titles .item')
310        //   titles.each(function () {
311        //     $(this).mouseout();
312        //   })
313        //  });
314        // gboPriceSwiper.on('reachBeginning', function () {
315        //   console.log('show')
316        // });
317        // const gboSliderHead = document.querySelector('.slider-head__titles')
318        // gboPriceSwiper.on('transitionStart', function () {
319        //   gboPriceSwiper.isBeginning ? gboSliderHead.classList.remove('js--hidden') : gboSliderHead.classList.add('js--hidden')
320        // });
321        
322        const gboKits = document.querySelectorAll(
323          ".paragraph__gbo-slider .swiper-slide .slide-top .trigger"
324        );
325        if (gboKits.length) {
326          gboKits.forEach((p) => {
327            new Tippy(p, {
328              position: "bottom-end",
329              animation: "shift",
330              allowHTML: true,
331              arrow: "true",
332            });
333          });
334        }
335        
336        const gboPrices = document.querySelectorAll(
337          ".paragraph__gbo-footer .left .price__trigger"
338        );
339        if (gboPrices.length) {
340          gboPrices.forEach((p) => {
341            new Tippy(p, {
342              position: "top",
343              animation: "shift",
344              allowHTML: true,
345              arrow: "true",
346            });
347          });
348        }
349        
350        // custom
351        
352        
353        
354        const customLeft = document.querySelector('.paragraph--custom .double-column__content-left')
355        const customRight = document.querySelector('.paragraph--custom .double-column__content-right')
356        const customContent = document.querySelector('.paragraph--custom .double-column__content')
357        
358        if(!!customLeft){
359          customLeft.classList.add('js--active')
360        
361          customLeft.addEventListener('mouseover', ()=>{
362            customLeft.classList.add('js--active')
363            customContent.classList.add('left-hover')
364            customContent.classList.remove('right-hover')
365            customRight.classList.remove('js--active')
366          })
367        
368          customRight.addEventListener('mouseover', ()=>{
369            customRight.classList.add('js--active')
370            customContent.classList.add('right-hover')
371            customContent.classList.remove('left-hover')
372            customLeft.classList.remove('js--active')
373          })
374        }
375        
376        
377        const stationBannerSlider = new Swiper(".station-banner__slider",
378          {
379            slidesPerView: "auto",
380            pagination: {
381              el: '.swiper-pagination',
382              clickable: true,
383            },
384            navigation: {
385              nextEl: '.station-banner__slider .swiper-button-next',
386              prevEl: '.station-banner__slider .swiper-button-prev',
387            },
388            autoplay: {
389              delay: 6000,
390              disableOnInteraction: true,
391            },
392            loop: true,
393            breakpoints: {
394              320: {
395                spaceBetween: 0,
396              },
397              768: {
398                spaceBetween: 48,
399              },
400            },
401          }
402        );
403        
404        
405        
406        
407        
408        
409        
410        
411        
412        
413        
414
415
416        const videos = document.querySelectorAll("video.video");
417        if (videos) {
418          videos.forEach(p => {
419            let playState = null;
420            let playPromise = p.play();
421            if (playPromise !== undefined) {
422              playPromise.then(_ => {
423                const observer = new IntersectionObserver((entries) => {
424                  entries.forEach((entry) => {
425                    if (!entry.isIntersecting) {
426                      p.pause();
427                      playState = false;
428                    } else {
429                      p.play();
430                      playState = true;
431                    }
432                  });
433                }, {});
434
435                observer.observe(p);
436              })
437            }
438
439          })
440        }
441
442
443        $('.header__city-selection .current').click(function () {
444
445          $(this).parent('.header__city-selection').toggleClass('js--active')
446
447          hideSubMenus()
448
449        });
450
451        
452
453        $('.header__city-selection .item').click(function () {
454
455          saveData($(this))
456
457          $('.header__city-selection').toggleClass('js--active')
458
459        });
460
461        
462
463        $('.header__city-selection .item[data-city="lviv"]').click(redirectToGBOPage)
464
465        
466
467        $('.city-popup .list__item').click(function () {
468
469          saveData($(this));
470
471          toggleCityPopup()
472
473        });
474
475        
476
477        $('.numbers_header').click(function () {
478
479          $('.header__phones').toggleClass('js--active')
480
481        });
482
483        
484
485        const certificateLinkLviv = $('.menu__item--certificate .lviv')
486
487        const certificateLinkOthers = $('.menu__item--certificate .others')
488
489        const repairLvivLink = $('.submenu__items .list-main .list__item--repair-lviv')
490
491        const repairDefaultLink = $('.submenu__items .list-main .list__item--repair-default')
492
493        
494
495        function redirectToGBOPage() {
496
497          const isUkrainianLang = drupalSettings.path.currentLanguage === 'uk'
498
499        
500
501          window.location.href = isUkrainianLang ? "/uk/node/3555" : "/stanciya-lviv"
502
503        }
504
505        
506
507        const saveData = selector => {
508
509          const name = selector.children('span').text();
510
511          const prop = selector.data('city');
512
513          const item = $(`.header__city-selection .item[data-city=${prop}]`)
514
515          setActiveInList(item)
516
517          handleSelectedLocation(prop)
518
519          setCityToCurrent(name, prop);
520
521          const savedData = JSON.stringify({ prop: prop });
522
523          localStorage.setItem('city', savedData);
524
525        };
526
527        
528
529        const setCityToCurrent = (name, prop) => {
530
531          const currentItem = $('.header__city-selection .current');
532
533          const currentText = $('.header__city-selection .current .current__text');
534
535          currentText.text(name);
536
537          currentItem.attr('data-city', prop);
538
539        };
540
541        
542
543        const setActiveInList = selector => {
544
545          $('.header__city-selection .item').removeClass('active');
546
547          $(selector).addClass('active');
548
549        };
550
551        
552
553        const toggleCityPopup = () => {
554
555          $('.city-popup').toggleClass('js--active')
556
557        };
558
559        const savedData = localStorage.getItem('city');
560
561        if (savedData) {
562
563          const { prop } = JSON.parse(savedData)
564
565        
566
567          const selector = $(`.header__city-selection .item[data-city=${prop}]`)
568
569          const name = selector.children('span').text()
570
571        
572
573          handleSelectedLocation(prop)
574
575          setCityToCurrent(name, prop)
576
577          setActiveInList(selector)
578
579          $('.header__city-selection .skeleton').removeClass('js--active')
580
581        } else {
582
583          $('.header__city-selection .skeleton').removeClass('js--active')
584
585          toggleCityPopup()
586
587          handleSelectedLocation('')
588
589        }
590
591        
592
593        function handleSelectedLocation(prop) {
594
595          const lvivGBO = $('.list-main .list__item--gbo-lviv')
596
597          const othersGBO = $('.list-main .list__item--gbo-others')
598
599        
600
601          if (prop === 'lviv') {
602
603            handleSelectedLviv(lvivGBO, othersGBO)
604
605          }
606
607          else {
608
609            handleSelectedOtherCity(lvivGBO, othersGBO)
610
611          }
612
613        }
614
615        
616
617        function handleSelectedLviv(lvivGBO, othersGBO) {
618
619          lvivGBO.removeClass('hidden')
620
621        
622
623          if (!othersGBO.hasClass('hidden')) {
624
625            othersGBO.addClass('hidden')
626
627          }
628
629        
630
631          replaceGenerationLinks('urlLviv')
632
633          toggleLocationLinks(true, { 
634
635            linkForLviv: repairLvivLink,
636
637            defaultLink: repairDefaultLink
638
639          })
640
641          toggleLocationLinks(true, { 
642
643            linkForLviv: certificateLinkLviv,
644
645            defaultLink: certificateLinkOthers
646
647          })
648
649        }
650
651        
652
653        function handleSelectedOtherCity(lvivGBO, othersGBO) {
654
655          othersGBO.removeClass('hidden')
656
657        
658
659          if (!lvivGBO.hasClass('hidden')) {
660
661            lvivGBO.addClass('hidden')
662
663          }
664
665        
666
667          replaceGenerationLinks('urlDefault')
668
669          toggleLocationLinks(false, { 
670
671            linkForLviv: repairLvivLink,
672
673            defaultLink: repairDefaultLink
674
675          })
676
677        
678
679          toggleLocationLinks(false, { 
680
681            linkForLviv: certificateLinkLviv,
682
683            defaultLink: certificateLinkOthers
684
685          })
686
687        }
688
689        
690
691        function replaceGenerationLinks(dataAttribute) {
692
693          const generationLinks = $('.submenu__items .generation .list__item--dynamic a')
694
695        
696
697          generationLinks.each(function() {
698
699            const url = $(this).data(dataAttribute)
700
701        
702
703            if (url) {
704
705              $(this).attr('href', url)
706
707            }
708
709          })
710
711        }
712
713        
714
715        function toggleLocationLinks(isLvivSelected, { linkForLviv, defaultLink }) {
716
717          if (isLvivSelected) {
718
719            linkForLviv.removeClass('hidden')
720
721        
722
723            if (!defaultLink.hasClass('hidden')) {
724
725              defaultLink.addClass('hidden')
726
727            }
728
729        
730
731          } else {
732
733            defaultLink.removeClass('hidden')
734
735        
736
737            if (!linkForLviv.hasClass('hidden')) {
738
739              linkForLviv.addClass('hidden')
740
741            }
742
743          }
744
745        }
746
747        
748
749        $('.city-popup__btn').click(function () {
750
751          toggleCityPopup()
752
753          saveData($('.header__city-selection .item.active'))
754
755        })
756
757        
758
759        $(document).on('click',function (e) {
760
761          const el = '.menu__item.menu__item--parent';
762
763          if ($(e.target).closest(el).length) return;
764
765          hideSubMenus()
766
767        });
768
769        
770
771        
772
773        
774
775        $('.menu__item.menu__item--parent').click(function (e) {
776
777          const gboInstallPageData = e.currentTarget.dataset.isGboInstallPage
778
779          const gboInstallUrl = e.currentTarget.dataset.gboInstallUrl
780
781          const isAllowToNavigate = gboInstallPageData && gboInstallPageData === '0'
782
783        
784
785          if (isAllowToNavigate) {
786
787            window.location.href = gboInstallUrl
788
789          } else {
790
791            $('.header__city-selection.js--active').removeClass('js--active')  
792
793          
794
795            if (e.target === this || e.target === this.querySelector('.menu__item-text')) {
796
797              const currentSubmenu = $(this).children('.submenu')
798
799              // -------------- UNCOMMENT WHEN VIDEOS WILL RETURN TO ME NU
800
801              pauseMenuVideos()
802
803              const currentVideo = currentSubmenu[0].querySelector('.menu-video')
804
805              if (currentVideo) {
806
807                currentVideo.play()
808
809              }
810
811              // -------------- UNCOMMENT WHEN VIDEOS WILL RETURN TO MENU
812
813              $('.menu__item.menu__item--parent .submenu').not(currentSubmenu).removeClass('js--active')
814
815              $('.menu__item.menu__item--parent').not($(this)).removeClass('js--active')
816
817              $(this).toggleClass('js--active')
818
819          
820
821          
822
823              currentSubmenu.toggleClass('js--active')
824
825              const btnBack = $('.header__menu-controls .btn__back')
826
827              checkAllSubMenus() ? btnBack.addClass('js--active') : btnBack.removeClass('js--active')
828
829              // -------------- UNCOMMENT WHEN VIDEOS WILL RETURN TO MENU
830
831              if (!checkAllSubMenus()) {
832
833                pauseMenuVideos()
834
835              }
836
837              // -------------- UNCOMMENT WHEN VIDEOS WILL RETURN TO MENU
838
839            }
840
841          }
842
843        
844
845          if(document.querySelector('.menu__item.menu__item--parent .js--active')){
846
847            $('.header__menu-overlay').addClass('js--active')
848
849          }else{
850
851            $('.header__menu-overlay').removeClass('js--active')
852
853          }
854
855        })
856
857        
858
859        const pauseMenuVideos = () => {
860
861          const menuVideos = document.querySelectorAll('.menu-video')
862
863          menuVideos.forEach(p => p.pause())
864
865        }
866
867        
868
869        const hideSubMenus = () => {
870
871          $('.menu__item.menu__item--parent .submenu').removeClass('js--active')
872
873          $('.menu__item.menu__item--parent').removeClass('js--active')
874
875          $('.header__menu-overlay').removeClass('js--active')
876
877          pauseMenuVideos()
878
879        }
880
881        
882
883        
884
885        
886
887        const checkAllSubMenus = function() {
888
889          const subMenus = document.querySelectorAll('.menu__item--parent .submenu');
890
891          let states = [];
892
893          subMenus.forEach(p => {
894
895            states.push(p.classList.contains('js--active'))
896
897          })
898
899          // states.some(state => state === true) ? disableScroll() : enableScroll()
900
901          return states.some(state => state === true)
902
903        }
904
905        
906
907        
908
909        $('.header-toggler').click(function () {
910
911          toggleMainMenu()
912
913          disableScroll()
914
915        
916
917        })
918
919        
920
921        $('.header__menu-controls .btn__close').click(function () {
922
923          toggleMainMenu()
924
925          enableScroll()
926
927        })
928
929        
930
931        $('.header__menu .anchor__link').click(function () {
932
933          $('.header__menu-controls .btn__close').trigger('click')
934
935        })
936
937        
938
939        $('.header__menu-controls .btn__back').click(function () {
940
941          $(this).removeClass('js--active')
942
943          hideSubMenus()
944
945        })
946
947        
948
949        $('.header__menu-overlay').click(function () {
950
951          toggleMainMenu()
952
953          enableScroll()
954
955        })
956
957        
958
959        const toggleMainMenu = () => {
960
961          $('.header__menu').toggleClass('js--active--mobile')
962
963          $('.header__menu-overlay').toggleClass('js--active')
964
965          $('.header__menu-controls .btn__back').removeClass('js--active')
966
967        }
968
969        
970
971        
972
973        
974
975        const subMenus = document.querySelectorAll('.menu__item .submenu')
976
977        subMenus.forEach(p => {
978
979          const subMenuPs = new PerfectScrollbar(p, {
980
981            wheelSpeed: 1,
982
983            wheelPropagation: true,
984
985            swipeEasing: true,
986
987            minScrollbarLength: 20,
988
989            suppressScrollX: true
990
991        
992
993          });
994
995        })
996
997        
998
999        const appHeight = () => {
1000
1001          const doc = document.documentElement
1002
1003          doc.style.setProperty('--app-height', `${window.innerHeight}px`)
1004
1005        }
1006
1007        window.addEventListener('resize', appHeight)
1008
1009        appHeight()
1010
1011        
1012
1013        $(window).resize(function() {
1014
1015          if (window.innerWidth >= 1024) {
1016
1017            enableScroll(false)
1018
1019          }
1020
1021        })
1022
1023        
1024
1025        function clickOutside(element, callback) {
1026
1027        
1028
1029          document.addEventListener("click", function(event) {
1030
1031        
1032
1033            let isClickInsideElement = element.contains(event.target);
1034
1035        
1036
1037        
1038
1039            if (!isClickInsideElement) {
1040
1041              callback();
1042
1043            }
1044
1045          });
1046
1047        }
1048
1049        
1050
1051        const headerPhone = document.querySelector('.header__phones')
1052
1053        const headerCity = document.querySelector('.header__city-selection')
1054
1055        
1056
1057        clickOutside(headerPhone, function() {
1058
1059          headerPhone.classList.remove('js--active')
1060
1061        });
1062
1063        
1064
1065        clickOutside(headerCity, function() {
1066
1067          headerCity.classList.remove('js--active')
1068
1069        });
1070
1071        
1072
1073        
1074
1075
1076        const $body = document.querySelector('body');
1077        const getScrollbarWidth = () => {
1078          return window.innerWidth - document.documentElement.clientWidth;
1079        }
1080
1081        let scrollPosition = 0;
1082
1083        const disableScroll = function () {
1084          scrollPosition = window.pageYOffset;
1085          //$body.style.paddingRight = `${getScrollbarWidth()}px`;
1086          $body.style.setProperty('--pr', `${getScrollbarWidth()}px`)
1087          $body.style.overflow = 'hidden';
1088          $body.style.position = 'fixed';
1089          $body.style.top = `-${scrollPosition}px`;
1090          $body.style.width = '100%';
1091        };
1092        const enableScroll = function (isScrollTop) {
1093          // $body.style.removeProperty('padding-right');
1094          // $body.style.setProperty('--pr', `${0}px`)
1095          $body.style.removeProperty('overflow');
1096          $body.style.removeProperty('position');
1097          $body.style.removeProperty('top');
1098          $body.style.removeProperty('width');
1099          if (isScrollTop !== false) {
1100            window.scrollTo(0, scrollPosition);
1101          }
1102
1103        };
1104
1105        /*let currentLetter = '';
1106        
1107        $('.page-portfolio .filter input').change(function () {
1108          currentLetter = $(this).val();
1109          makeSearch(currentLetter);
1110        });
1111        
1112        $('.page-portfolio .filter input[type=radio]').click(function () {
1113          if (currentLetter === $(this).val()) {
1114            $(this).prop('checked', false);
1115            makeSearch('', 'byWord');
1116            currentLetter = ''
1117          }
1118        });
1119        
1120        
1121        const makeSearch = function (keyword) {
1122          let filter = keyword.toUpperCase();
1123          const list = document.querySelector('.page-portfolio .brands, .page-portfolio .autos');
1124          let items = list.querySelectorAll('.brands__item, .autos__items');
1125          for (let i = 0; i < items.length; i += 1) {
1126            let txtValue = items[i].getAttribute('data-search')
1127            if (txtValue.toUpperCase().indexOf(filter) > -1) {
1128              items[i].style.display = "";
1129            } else {
1130              items[i].style.display = "none";
1131            }
1132          }
1133        };*/
1134        
1135        $('.page-portfolio .filter .letter').click(function () {
1136          $(`.page-portfolio .brands__item, .page-portfolio .autos__item`).removeClass('js--active')
1137          const target = $(`.page-portfolio .brands__item[data-search=${this.dataset.prop}], .page-portfolio .autos__item[data-search=${this.dataset.prop}]`)
1138          target.addClass('js--active')
1139          const top = $(target).offset().top;
1140          $('body,html').animate({scrollTop: top}, 1000);
1141        });
1142        
1143
1144        const state = (key) => sessionStorage.getItem(key)
1145        
1146        const announcesWrapper = document.querySelector('.header-announces')
1147        
1148        const messagesWrapper = document.querySelector('.header-messages')
1149        
1150        const types = {
1151          messages: {
1152            key: 'messages',
1153            selector: messagesWrapper.querySelectorAll('.header-messages__item'),
1154          },
1155          announces: {
1156            key: 'announces',
1157            selector: announcesWrapper.querySelectorAll('.header-announces__item'),
1158          }
1159        }
1160        
1161        const setActiveNotify = (index, selector, key) => {
1162          selector[index].classList.add('js--active')
1163          let store = getState(key)
1164          const closeBtn = selector[index].querySelector('.close')
1165          closeBtn.addEventListener('click', (e) => {
1166            e.preventDefault()
1167            selector[index].classList.remove('js--active')
1168            store.closed.push(index)
1169            setDataToState(key, store)
1170          })
1171        }
1172        
1173        const getState = (key) => JSON.parse(state(key))
1174        
1175        const setDataToState = (key, data) => {
1176          const storeItem = { ...data }
1177          sessionStorage.setItem(`${key}`, JSON.stringify(storeItem))
1178        }
1179        
1180        const checkIsAllClosed = (arrayOfClosed, selector) => {
1181          const indices = Array.from(Array(selector.length).keys())
1182          return indices.every(p => arrayOfClosed.includes(p))
1183        }
1184        
1185        const detectActive = (stateIndex, arrayOfClosed, selector) => {
1186          let tempIndex = stateIndex += 1
1187          tempIndex = tempIndex === selector.length ? 0 : tempIndex
1188          if (arrayOfClosed.includes(tempIndex)) {
1189            return detectActive(tempIndex, arrayOfClosed, selector)
1190          } else {
1191            return tempIndex
1192          }
1193        }
1194        
1195        const getInitialState = () => {
1196          return { closed: [], active: 0 }
1197        }
1198        
1199        const setDataAndActivate = (key, data, index, selector) => {
1200          setDataToState(key, data)
1201          setActiveNotify(index, selector, key)
1202        }
1203        
1204        const notifyAction = type => {
1205          const key = type.key
1206          const selector = type.selector
1207          if (state(key)) {
1208            let store = getState(key)
1209            if (!checkIsAllClosed(store.closed, selector)) {
1210              store.active = detectActive(store.active, store.closed, selector)
1211              setDataAndActivate(key, store, store.active, selector)
1212              // setDataToState(key, store);
1213              // setActiveNotify(store.active, selector, key);
1214            }
1215          } else {
1216            const initialState = getInitialState()
1217            setDataAndActivate(key, initialState, initialState.active, selector)
1218            // setDataToState(key, initialState);
1219            // setActiveNotify(initialState.active, selector, key);
1220          }
1221        };
1222        
1223        if (types.announces.selector.length > 0) {
1224          notifyAction(types.announces)
1225        }
1226        
1227        if (types.messages.selector.length > 0) {
1228          notifyAction(types.messages)
1229        }
1230        
1231        
1232
1233        var autosSliderrSwiper = new Swiper('.autos-slider .swiper-container', {
1234          grabCursor: true,
1235          slidesPerView: 'auto',
1236          breakpoints: {
1237            320: {
1238              spaceBetween: 20
1239            },
1240            1200: {
1241              spaceBetween: 24
1242            }
1243          }
1244        });
1245        
1246
1247        // Nov 30, 2020 00:00:00
1248        const timers = document.querySelectorAll('.timer__clock');
1249        if (timers.length > 0) {
1250          timers.forEach(timer => {
1251            const deadline = timer.dataset.deadline;
1252            const countDownDate = new Date(deadline).getTime();
1253            const interval = setInterval(function() {
1254              const now = new Date().getTime();
1255              const distance = countDownDate - now;
1256              const days = Math.floor(distance / (1000 * 60 * 60 * 24));
1257              const hours = Math.floor((distance % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
1258              const minutes = Math.floor((distance % (1000 * 60 * 60)) / (1000 * 60));
1259              const seconds = Math.floor((distance % (1000 * 60)) / 1000);
1260              setCount(timer, { days, hours, minutes, seconds });
1261              // setCount(timer, { days: 27, hours: 9, minutes: 46, seconds: 58 });
1262              if (distance < 0) {
1263                clearInterval(interval);
1264                setCount(timer, { days: 0, hours: 0, minutes: 0, seconds: 0 });
1265              }
1266            }, 1000);
1267          })
1268        }
1269        const setCount = (timer, counts) => {
1270          const { days, hours, minutes, seconds } = counts;
1271          timer.querySelector('.days .days__count .number').textContent = days;
1272          timer.querySelector('.hours .hours__count .number').textContent = hours;
1273          timer.querySelector('.minutes .minutes__count .number').textContent = minutes;
1274          timer.querySelector('.seconds .seconds__count .number').textContent = seconds;
1275        };
1276        
1277        
1278        // const timers = document.querySelectorAll('.timer__clock');
1279        // if (timers.length > 0) {
1280        //   timers.forEach(p => {
1281        //     function CountdownTracker(label, value){
1282        //       var el = document.createElement('span');
1283        //       el.className = 'flip-clock__piece';
1284        //       el.innerHTML = '<span class="flip-clock__card card"><span class="card__top"></span><span class="card__bottom"></span><span class="card__back"><span class="card__bottom"></span></span></span>' +
1285        //         '<span class="flip-clock__slot">' + label + '</span>';
1286        //       this.el = el;
1287        //       var top = el.querySelector('.card__top'),
1288        //         bottom = el.querySelector('.card__bottom'),
1289        //         back = el.querySelector('.card__back'),
1290        //         backBottom = el.querySelector('.card__back .card__bottom');
1291        //       this.update = function(val){
1292        //         val = ( '0' + val ).slice(-2);
1293        //         if ( val !== this.currentValue ) {
1294        //           if ( this.currentValue >= 0 ) {
1295        //             back.setAttribute('data-value', this.currentValue);
1296        //             bottom.setAttribute('data-value', this.currentValue);
1297        //           }
1298        //           this.currentValue = val;
1299        //           top.innerText = this.currentValue;
1300        //           backBottom.setAttribute('data-value', this.currentValue);
1301        //           this.el.classList.remove('flip');
1302        //           void this.el.offsetWidth;
1303        //           this.el.classList.add('flip');
1304        //         }
1305        //       }
1306        //       this.update(value);
1307        //     }
1308        //     function getTimeRemaining(endtime) {
1309        //       var t = Date.parse(endtime) - Date.parse(new Date());
1310        //       return {
1311        //         'Total': t,
1312        //         'Days': Math.floor(t / (1000 * 60 * 60 * 24)),
1313        //         'Hours': Math.floor((t / (1000 * 60 * 60)) % 24),
1314        //         'Minutes': Math.floor((t / 1000 / 60) % 60),
1315        //         'Seconds': Math.floor((t / 1000) % 60)
1316        //       };
1317        //     }
1318        //     function getTime() {
1319        //       var t = new Date();
1320        //       return {
1321        //         'Total': t,
1322        //         'Hours': t.getHours() % 12,
1323        //         'Minutes': t.getMinutes(),
1324        //         'Seconds': t.getSeconds()
1325        //       };
1326        //     }
1327        //     function Clock(countdown,callback) {
1328        //       countdown = countdown ? new Date(Date.parse(countdown)) : false;
1329        //       callback = callback || function(){};
1330        //       var updateFn = countdown ? getTimeRemaining : getTime;
1331        //       this.el = document.createElement('div');
1332        //       this.el.className = 'flip-clock';
1333        //       var trackers = {},
1334        //         t = updateFn(countdown),
1335        //         key, timeinterval;
1336        //       for ( key in t ){
1337        //         if ( key === 'Total' ) { continue; }
1338        //         trackers[key] = new CountdownTracker(key, t[key]);
1339        //         this.el.appendChild(trackers[key].el);
1340        //       }
1341        //       var i = 0;
1342        //       function updateClock() {
1343        //         timeinterval = requestAnimationFrame(updateClock);
1344        //         // throttle so it's not constantly updating the time.
1345        //         if ( i++ % 10 ) { return; }
1346        //         var t = updateFn(countdown);
1347        //         if ( t.Total < 0 ) {
1348        //           cancelAnimationFrame(timeinterval);
1349        //           for ( key in trackers ){
1350        //             trackers[key].update( 0 );
1351        //           }
1352        //           callback();
1353        //           return;
1354        //         }
1355        //         for ( key in trackers ){
1356        //           trackers[key].update( t[key] );
1357        //         }
1358        //       }
1359        //       setTimeout(updateClock,500);
1360        //     }
1361        //     const deadline =  p.dataset.deadline
1362        //     var c = new Clock(deadline);
1363        //     p.appendChild(c.el);
1364        //   })
1365        // }
1366        
1367        
1368        
1369        
1370        
1371        
1372        
1373
1374        const totalSum = 480;
1375        const stepsCount = 6;
1376        
1377        const progress = document.querySelector(".calculator-progress__bar");
1378        if (progress) {
1379          const getCurrentStep = () =>
1380            document.querySelector(".paragraph--calculator").dataset.step - 1;
1381          let currentStep = getCurrentStep();
1382          const radius = progress.r.baseVal.value;
1383          const circumference = 2 * Math.PI * radius;
1384        
1385          progress.style.setProperty(
1386            "--dasharray",
1387            `${circumference} ${circumference}`
1388          );
1389          progress.style.setProperty("--dashoffset", circumference);
1390        
1391          const setProgress = () => {
1392            const percent = (currentStep * 100) / stepsCount;
1393            const offset = circumference - (percent / 100) * circumference;
1394            progress.style.setProperty("--dashoffset", offset);
1395          };
1396        
1397          setProgress();
1398        
1399          const animateValue = (el, start, end, duration) => {
1400            if (start === end) return;
1401            const range = end - start;
1402            let current = start;
1403            const increment = end > start ? 1 : -1;
1404            const stepTime = Math.abs(Math.floor(duration / range));
1405            const timer = setInterval(() => {
1406              current += increment;
1407              el.innerHTML = current;
1408              if (current === end) {
1409                clearInterval(timer);
1410              }
1411            }, stepTime);
1412          };
1413          const btnBack = document.querySelector(".calculator-left__btn");
1414          btnBack.addEventListener("click", () => {
1415            document.querySelector(".calculator-right input.button-prev").click();
1416          });
1417        
1418          $(document).ajaxStop(function () {
1419            currentStep = getCurrentStep();
1420            const currentSum = parseInt(
1421              document.querySelector(".calculator-progress__info .count").textContent
1422            );
1423            const target = document.querySelector(".calculator-progress__info .count");
1424            const end = (totalSum / stepsCount) * getCurrentStep();
1425            animateValue(target, currentSum, end, 800);
1426            setProgress();
1427          });
1428        }
1429        var calculatorSwiper = new Swiper(".paragraph__calculator .swiper-container", {
1430          slidesPerView: 1,
1431          pagination: {
1432            el: ".swiper-pagination",
1433            clickable: true,
1434          },
1435        });
1436        
1437
1438        const mapEl = document.getElementById("map-desktop");
1439        const mobileMapEl = document.getElementById("map-mobile");
1440        
1441        window.initGmap = () => {
1442          const currentLang = drupalSettings.path.currentLanguage || 'ru'
1443          const isPolishVersion = currentLang === 'pl'
1444          const isUkrainian = currentLang === 'uk'
1445          const icon = "/themes/mytheme/build/img/map/pin--mini.svg"
1446          const isDesktop = window?.innerWidth > 992
1447        
1448          if (mapEl) {
1449            const myLatLng = { lat: 50.454784, lng: 30.603934877317855 }; // {lat: 50.454784, lng: 30.457707}
1450            const plLatLng = { lat: 52.23649162256689, lng: 21.141722957670297 }
1451            const initialCoordinates = isPolishVersion ? plLatLng : myLatLng
1452            const mapHeader = document.querySelector(".stations-map__map-header");
1453            const mapFooter = document.querySelector(".stations-map__map-footer");
1454            const mobileHideStations = document.querySelector(
1455                ".stations-map__map .hide"
1456            );
1457            const mobileStationsToggler = document.querySelector(
1458                ".stations-map__toggler"
1459            );
1460            const stationsList = document.querySelector(".stations-map__list");
1461            const mobileBackBtn = document.querySelector(".stations-map__nav-back");
1462            const citiesFilter = document.querySelector(".stations-map__nav-nav");
1463            let isMobileStationsListOpen = false;
1464            let isSomeStationActive = false;
1465            let currentFilter = "All";
1466            const cities = {
1467              All: {
1468                prop: false,
1469                coords: isPolishVersion ? plLatLng : myLatLng,
1470              },
1471              Kyiv: {
1472                prop: "Kyiv",
1473                coords: myLatLng,
1474              },
1475              Irpen: {
1476                prop: "Irpen",
1477                coords: { lat: 50.529903833371336, lng: 30.244301860118266 },
1478              },
1479              Borispol: {
1480                prop: "Borispol",
1481                coords: { lat: 50.36515915615754, lng: 30.919675492643083 },
1482              },
1483              Warszawa: {
1484                prop: "Warszawa",
1485                coords: { lat: 52.23649162256689, lng: 21.141722957670297 },
1486              },
1487              Lviv: {
1488                prop: "Lviv",
1489                coords: { lat: 49.83607773238876, lng: 23.977604557329887 },
1490              },
1491            };
1492        
1493            const translations = {
1494              uk: {
1495                tooltipTitle: {
1496                  obolon: "Оболонь",
1497                  slavutich: "Славутич",
1498                  podil: "Поділ",
1499                  okr: "Кільцева дорога",
1500                  svn: "Святошино / Нивки",
1501                  warszawa: 'Warszawa',
1502                  irpin: 'Ірпінь',
1503                  borispil: 'Бориспіль',
1504                  lviv: 'Львів',
1505                },
1506                street: {
1507                  obolon: "вул. Автозаводська, 18",
1508                  slavutich: "вул. Центральна та вул. 139-та Садова",
1509                  podil: "вул. Набережно-Лугова, 8",
1510                  okr: 'с. Софіївська Борщагівка, вул. Садова, 48а',
1511                  svn: "вул. Академіка Туполєва, 19 (МРЕВ)",
1512                  warszawa: 'st. Łysakowska 29',
1513                  irpin: 'вул. Центральна, 30',
1514                  borispil: 'вул. Київський шлях, 2/15 (орієнтир – ТРЦ «Аеромолл»)',
1515                  lviv: 'вул.Сяйво 2/4'
1516                },
1517              },
1518              ru: {
1519                tooltipTitle: {
1520                  obolon: "Оболонь",
1521                  slavutich: "Славутич",
1522                  podil: "Подол",
1523                  okr: "Окружная дорога",
1524                  warszawa: 'Warszawa',
1525                  irpin: 'Ирпень',
1526                  svn: "Святошино / Нивки",
1527                  borispil: 'Борисполь',
1528                  lviv: 'Львов'
1529                },
1530                street: {
1531                  obolon: "ул. Автозаводская, 18",
1532                  slavutich: "ул. Центральная и 139-я Садовая",
1533                  podil: "ул. Набережно-Луговая, 8",
1534                  okr: 'Окружная дорога',
1535                  warszawa: 'st. Łysakowska 29',
1536                  irpin: 'ул. Центральная, 30',
1537                  svn: "ул. Академика Туполева, 19 (МРЭО)",
1538                  borispil: 'ул. Киевский шлях 2/15 (ориентир Аэромолл ТРЦ)',
1539                  lviv: 'ул.Сяйво 2/4'
1540                },
1541              },
1542              pl: {
1543                tooltipTitle: {
1544                  obolon: "Obolon",
1545                  slavutich: "Slavutich",
1546                  podil: "Podol",
1547                  okr: "Ring road",
1548                  warszawa: 'Warszawa',
1549                  irpin: 'Irpen',
1550                  svn: "Svyatoshino / Nyvky",
1551                  borispil: 'Borispol',
1552                  lviv: 'Lviv'
1553                },
1554                street: {
1555                  obolon: "st. Avtozavodskaya, 18",
1556                  slavutich: "corner of st. Central and 139th Sadovaya",
1557                  podil: "st. Naberezhno-Lugovaya, 8",
1558                  okr: 'Sofievskaya Borschagovka, st. Sadovaya, 48a',
1559                  warszawa: 'st. Łysakowska 29',
1560                  irpin: 'st. Centralnaya, 30',
1561                  svn: "st. Academician Tupolev, 19 (MREO)",
1562                  borispil: 'st. Kievskiy shlyakh 2/15 (landmark Aeromall mall)',
1563                  lviv: 'st. Syaivo 2/4'
1564                },
1565              },
1566            };
1567        
1568            function getTranslation(key, value) {
1569              const currentLang = drupalSettings.path.currentLanguage || "ru";
1570              return translations[currentLang]?.[key]?.[value] || value;
1571            };
1572        
1573            function getGeneralTranslations() {
1574              const translations = {
1575                uk: {
1576                  city: "Місто",
1577                  phone: "Тел:",
1578                  routeName: 'МАРШРУТ',
1579                  schedule: 'Пн.-Нд.',
1580                  short_schedule: 'Пн.-Сб.',
1581                  sunday_off: 'Нд - <span class="google-maps-content__value">вихідний</span>',
1582                },
1583                ru: {
1584                  city: "Город",
1585                  phone: "Тел:",
1586                  routeName: 'МАРШРУТ',
1587                  schedule: 'Пн.-Вс.',
1588                  short_schedule: 'Пн.-Сб.',
1589                  sunday_off: 'Вс - <span class="google-maps-content__value">выходной</span>',
1590                },
1591                pl: {
1592                  city: "Miasto",
1593                  phone: "Tel:",
1594                  routeName: 'TRASA',
1595                  schedule: 'Pn - Pt',
1596                  short_schedule: 'Pn - Sb',
1597                  sunday_off: 'Niedziela - <span class="google-maps-content__value">dzień wolny</span>',
1598                },
1599              };
1600            
1601              return translations[drupalSettings.path.currentLanguage || "ru"];
1602            };
1603        
1604            function getVideoLabel() {
1605              return {
1606                uk: 'ВІДЕО',
1607                ru: 'ВИДЕО',
1608                pl: 'WIDEO'
1609              }?.[currentLang] || 'ВІДЕО'
1610            }
1611          
1612            let markers = [];
1613            const allStations = [
1614              {
1615                position: new google.maps.LatLng(50.50325247173102, 30.460030329447736),
1616                name: "obolon",
1617                city: cities.Kyiv.prop,
1618                tooltipTitle: getTranslation('tooltipTitle', 'obolon'),
1619                street: getTranslation('street', 'obolon'),
1620                schedule: "9:00-19:00",
1621                weekend: "9:00-20:00", // day off
1622                phone: "067 415 05 00",
1623                isUkraineLocation: true,
1624                video: {
1625                  url: "https://youtube.com/shorts/I3A_XCBPT04",
1626                  label: getVideoLabel(),
1627                },
1628                route:
1629                    "https://www.google.com/maps/dir//%D0%A1%D0%A2%D0%9E+%22%D0%92%D1%80%D0%B5%D0%BC%D1%8F+%D0%B3%D0%B0%D0%B7%D0%B0%22,+%D0%B2%D1%83%D0%BB%D0%B8%D1%86%D1%8F+%D0%90%D0%B2%D1%82%D0%BE%D0%B7%D0%B0%D0%B2%D0%BE%D0%B4%D1%81%D1%8C%D0%BA%D0%B0,+18,+%D0%9A%D0%B8%D1%97%D0%B2,+%D0%A3%D0%BA%D1%80%D0%B0%D0%B8%D0%BD%D0%B0,+04074/@50.503252,30.46003,18z/data=!4m16!1m6!3m5!1s0x0:0xfd04a06b153a3f7b!2z0KHQotCeICLQktGA0LXQvNGPINCz0LDQt9CwIg!8m2!3d50.5032513!4d30.4600303!4m8!1m0!1m5!1m1!1s0x40d4cd87ace34a99:0xfd04a06b153a3f7b!2m2!1d30.4600303!2d50.5032513!3e3?hl=ru-RU",
1630              },
1631              {
1632                position: new google.maps.LatLng(50.38756527514124, 30.603934877317855),
1633                name: "slavutich",
1634                city: cities.Kyiv.prop,
1635                tooltipTitle: getTranslation('tooltipTitle', 'slavutich'),
1636                street: getTranslation('street', 'slavutich'),
1637                schedule: "9:00-19:00",
1638                weekend: "9:00-19:00",
1639                phone: "067 415 05 00",
1640                isUkraineLocation: true,
1641                video: {
1642                  url: 'https://youtube.com/shorts/o6ffqAMN6wE',
1643                  label: getVideoLabel(),
1644                },
1645                route:
1646                    "https://www.google.com/maps/dir//Vremya+Haza,+%D0%9A%D0%B8%D0%B5%D0%B2,+%D0%BF%D0%B5%D1%80%D0%B5%D1%81%D0%B5%D1%87%D0%B5%D0%BD%D0%B8%D0%B5+%D1%83%D0%BB.+%D0%A6%D0%B5%D0%BD%D1%82%D1%80%D0%B0%D0%BB%D1%8C%D0%BD%D0%B0%D1%8F+%D0%B8,+139-%D0%B0+%D0%A1%D0%B0%D0%B4%D0%BE%D0%B2%D0%B0+%D0%B2%D1%83%D0%BB%D0%B8%D1%86%D1%8F,+%D0%9A%D0%B8%D1%97%D0%B2,+%D0%A3%D0%BA%D1%80%D0%B0%D0%B8%D0%BD%D0%B0,+02132/@50.387565,30.603935,18z/data=!4m16!1m6!3m5!1s0x0:0xd1e7dfa2d9c3f0d8!2sVremya+Haza!8m2!3d50.3875638!4d30.6039362!4m8!1m0!1m5!1m1!1s0x40d4c5cf0af22b15:0xd1e7dfa2d9c3f0d8!2m2!1d30.6039362!2d50.3875638!3e3?hl=ru-RU",
1647              },
1648              // {
1649              //   position: new google.maps.LatLng(50.49894576900998, 30.435807259506863),
1650              //   name: 'vino',
1651              //   city: cities.Kyiv.prop,
1652              //   schedule: '9:00-19:00',
1653              //   weekend: '9:00-19:00',
1654              //   phone: '067 415 05 00',
1655              //   isUkraineLocation: true,
1656              //   route: 'https://www.google.com/maps/dir//Vremya+Haza,+%D0%B2%D1%83%D0%BB%D0%B8%D1%86%D1%8F+%D0%9D%D0%BE%D0%B2%D0%BE%D0%BC%D0%BE%D1%81%D1%82%D0%B8%D1%86%D1%8C%D0%BA%D0%B0,+25,+%D0%9A%D0%B8%D1%97%D0%B2,+%D0%A3%D0%BA%D1%80%D0%B0%D0%B8%D0%BD%D0%B0,+04074/@50.498946,30.435807,18z/data=!4m16!1m6!3m5!1s0x0:0x51075f4a5f685ca1!2sVremya+Haza!8m2!3d50.4989458!4d30.4358065!4m8!1m0!1m5!1m1!1s0x40d4cd77b3d888d5:0x51075f4a5f685ca1!2m2!1d30.4358065!2d50.4989458!3e3?hl=ru-RU'
1657              // },
1658              {
1659                position: new google.maps.LatLng(50.42007855116396, 30.37027661226821),
1660                name: "okr",
1661                city: cities.Kyiv.prop,
1662                tooltipTitle: getTranslation('tooltipTitle', 'okr'),
1663                street: getTranslation('street', 'okr'),
1664                schedule: "9:00-19:00",
1665                weekend: "9:00-20:00",
1666                phone: "067 415 05 00",
1667                isUkraineLocation: true,
1668                video: {
1669                  url: 'https://youtube.com/shorts/ab4PNuJmh0s',
1670                  label: getVideoLabel(),
1671                },
1672                route:
1673                    "https://www.google.com/maps/dir//%D0%92%D1%80%D0%B5%D0%BC%D1%8F+%D0%93%D0%B0%D0%B7%D0%B0,+%D0%B2%D1%83%D0%BB%D0%B8%D1%86%D1%8F+%D0%A1%D0%B0%D0%B4%D0%BE%D0%B2%D0%B0,+48%D0%B0,+%D0%9A%D0%B8%D1%97%D0%B2,+%D0%9A%D0%B8%D1%97%D0%B2%D1%81%D1%8C%D0%BA%D0%B0+%D0%BE%D0%B1%D0%BB.,+%D0%A3%D0%BA%D1%80%D0%B0%D0%B8%D0%BD%D0%B0,+08131/@50.420079,30.370277,18z/data=!4m16!1m6!3m5!1s0x0:0x17a83725ca9cfa3d!2z0JLRgNC10LzRjyDQk9Cw0LfQsA!8m2!3d50.4200794!4d30.3702768!4m8!1m0!1m5!1m1!1s0x40d4cb9918d69bcd:0x17a83725ca9cfa3d!2m2!1d30.3702768!2d50.4200794!3e3?hl=ru-RU",
1674              },
1675              {
1676                position: new google.maps.LatLng(50.47597828976137, 30.507431046627243),
1677                name: "podol",
1678                city: cities.Kyiv.prop,
1679                tooltipTitle: getTranslation('tooltipTitle', 'podil'),
1680                street: getTranslation('street', 'podil'),
1681                schedule: "9:00-19:00",
1682                weekend: "9:00-19:00",
1683                phone: "067 415 05 00",
1684                isUkraineLocation: true,
1685                video: {
1686                  url: 'https://youtube.com/shorts/-fxfKW-AeBA',
1687                  label: getVideoLabel(),
1688                },
1689                route:
1690                    "https://www.google.com/maps/dir//%D0%92%D1%80%D0%B5%D0%BC%D1%8F+%D0%93%D0%B0%D0%B7%D0%B0,+%D0%B2%D1%83%D0%BB%D0%B8%D1%86%D1%8F+%D0%9D%D0%B0%D0%B1%D0%B5%D1%80%D0%B5%D0%B6%D0%BD%D0%BE-%D0%9B%D1%83%D0%B3%D0%BE%D0%B2%D0%B0,+8,+%D0%9A%D0%B8%D1%97%D0%B2,+%D0%A3%D0%BA%D1%80%D0%B0%D0%B8%D0%BD%D0%B0,+04071/@50.475978,30.507431,18z/data=!4m16!1m6!3m5!1s0x0:0x263c33b20756c4f7!2z0JLRgNC10LzRjyDQk9Cw0LfQsA!8m2!3d50.47598!4d30.5074301!4m8!1m0!1m5!1m1!1s0x40d4ce0ef6ce0f69:0x263c33b20756c4f7!2m2!1d30.5074301!2d50.47598!3e3?hl=ru-RU",
1691              },
1692              {
1693                position: new google.maps.LatLng(50.48693400379458, 30.394202915345303),
1694                name: "svn",
1695                city: cities.Kyiv.prop,
1696                tooltipTitle: getTranslation('tooltipTitle', 'svn'),
1697                street: getTranslation('street', 'svn'),
1698                schedule: "9:00-19:00",
1699                weekend: "9:00-19:00",
1700                phone: "067 415 05 00",
1701                isUkraineLocation: true,
1702                video: {
1703                  url: 'https://youtube.com/shorts/_pYEiuNc4Ds',
1704                  label: getVideoLabel(),
1705                },
1706                route:
1707                    "https://www.google.com/maps/dir//Vremya+Haza,+%D0%B2%D1%83%D0%BB%D0%B8%D1%86%D1%8F+%D0%90%D0%BA%D0%B0%D0%B4%D0%B5%D0%BC%D1%96%D0%BA%D0%B0+%D0%A2%D1%83%D0%BF%D0%BE%D0%BB%D1%94%D0%B2%D0%B0,+19,+%D0%9A%D0%B8%D1%97%D0%B2,+%D0%A3%D0%BA%D1%80%D0%B0%D0%B8%D0%BD%D0%B0,+04128/@50.486934,30.394203,18z/data=!4m16!1m6!3m5!1s0x0:0xf6dd2c0be1597cb2!2sVremya+Haza!8m2!3d50.4869331!4d30.3942027!4m8!1m0!1m5!1m1!1s0x40d4cd89f16a7b41:0xf6dd2c0be1597cb2!2m2!1d30.3942027!2d50.4869331!3e3?hl=ru-RU",
1708              },
1709              {
1710                position: new google.maps.LatLng(
1711                    50.529903833371336,
1712                    30.244301860118266
1713                ),
1714                name: "irpen",
1715                city: cities.Irpen.prop,
1716                tooltipTitle: getTranslation('tooltipTitle', 'irpin'),
1717                street: getTranslation('street', 'irpin'),
1718                schedule: "9:00-18:00",
1719                weekend: "9:00-18:00",
1720                phone: "067 415 05 00",
1721                isUkraineLocation: true,
1722                video: {
1723                  url: 'https://youtube.com/shorts/VatznfrPUfc',
1724                  label: getVideoLabel(),
1725                },
1726                route:
1727                    "https://www.google.com/maps/dir//%D0%A1%D0%A2%D0%9E+%D0%92%D1%80%D0%B5%D0%BC%D1%8F+%D0%B3%D0%B0%D0%B7%D0%B0+-+%D1%81%D0%B5%D1%80%D0%B2%D0%B8%D1%81+%D0%93%D0%91%D0%9E,+%D0%B2%D1%83%D0%BB%D0%B8%D1%86%D1%8F+%D0%A6%D0%B5%D0%BD%D1%82%D1%80%D0%B0%D0%BB%D1%8C%D0%BD%D0%B0,+30,+%D0%86%D1%80%D0%BF%D1%96%D0%BD%D1%8C,+%D0%9A%D0%B8%D1%97%D0%B2%D1%81%D1%8C%D0%BA%D0%B0+%D0%BE%D0%B1%D0%BB.,+%D0%A3%D0%BA%D1%80%D0%B0%D0%B8%D0%BD%D0%B0,+08200/@50.529904,30.244302,18z/data=!4m16!1m6!3m5!1s0x0:0xd39cc8b9cbeaab3d!2z0KHQotCeINCS0YDQtdC80Y8g0LPQsNC30LAgLSDRgdC10YDQstC40YEg0JPQkdCe!8m2!3d50.529903!4d30.2443019!4m8!1m0!1m5!1m1!1s0x472b33b7404ae23d:0xd39cc8b9cbeaab3d!2m2!1d30.2443019!2d50.529903!3e3?hl=ru-RU",
1728              },
1729              {
1730                position: new google.maps.LatLng(50.36515915615754, 30.919675492643083),
1731                name: "borispol",
1732                city: cities.Borispol.prop,
1733                tooltipTitle: getTranslation('tooltipTitle', 'borispil'),
1734                street: getTranslation('street', 'borispil'),
1735                schedule: "9:00-18:00",
1736                weekend: "9:00-18:00", // 'day off',
1737                isUkraineLocation: true,
1738                phone: "067 415 05 00",
1739                video: {
1740                  url: 'https://youtube.com/shorts/eKhXujwCC6c',
1741                  label: getVideoLabel(),
1742                },
1743                route:
1744                    "https://www.google.com/maps/dir//%D0%92%D1%80%D0%B5%D0%BC%D1%8F+%D0%93%D0%B0%D0%B7%D0%B0,+%D0%B2%D1%83%D0%BB%D0%B8%D1%86%D1%8F+%D0%9A%D0%B8%D1%97%D0%B2%D1%81%D1%8C%D0%BA%D0%B8%D0%B9+%D1%88%D0%BB%D1%8F%D1%85,+2%2F15,+%D0%91%D0%BE%D1%80%D0%B8%D1%81%D0%BF%D1%96%D0%BB%D1%8C,+%D0%9A%D0%B8%D1%97%D0%B2%D1%81%D1%8C%D0%BA%D0%B0+%D0%BE%D0%B1%D0%BB.,+%D0%A3%D0%BA%D1%80%D0%B0%D0%B8%D0%BD%D0%B0,+08301/@50.365174,30.919806,20z/data=!4m16!1m6!3m5!1s0x0:0x17c86378317ebd0f!2z0JLRgNC10LzRjyDQk9Cw0LfQsA!8m2!3d50.365159!4d30.9196762!4m8!1m0!1m5!1m1!1s0x40d4e90ba151e99b:0x17c86378317ebd0f!2m2!1d30.9196762!2d50.365159!3e3?hl=ru-RU",
1745              },
1746              {
1747                position: new google.maps.LatLng(52.23649162256689, 21.141722957670297),
1748                name: "warszawa",
1749                city: cities.Warszawa.prop,
1750                tooltipTitle: getTranslation('tooltipTitle', 'warszawa'),
1751                street: getTranslation('street', 'warszawa'),
1752                schedule: "09:00 - 18:00",
1753                weekend: "09:00 - 16:00", // 'day off',
1754                phone: "+48 222 57 1717",
1755                isUkraineLocation: false,
1756                route: "https://maps.app.goo.gl/7p9CKuB894fUxviz9",
1757                video: {
1758                  url: '',
1759                  label: getVideoLabel(),
1760                },
1761              },
1762              {
1763                position: new google.maps.LatLng(49.83607773238876, 23.977604557329887),
1764                name: "lviv",
1765                city: cities.Lviv.prop,
1766                tooltipTitle: getTranslation('tooltipTitle', 'lviv'),
1767                street: getTranslation('street', 'lviv'),
1768                schedule: "9:00-19:00",
1769                weekend: "9:00-19:00", // 'day off',
1770                phone: "+380671899325",
1771                isUkraineLocation: true,
1772                video: {
1773                  url: 'https://www.youtube.com/shorts/xDsWpNIASXA',
1774                  label: getVideoLabel(),
1775                },
1776                route:
1777                    "https://www.google.com/maps/dir//%D0%B2%D1%83%D0%BB%D0%B8%D1%86%D1%8F+%D0%A1%D1%8F%D0%B9%D0%B2%D0%BE,+2,+%D0%9B%D1%8C%D0%B2%D1%96%D0%B2,+%D0%9B%D1%8C%D0%B2%D0%BE%D0%B2%D1%81%D0%BA%D0%B0%D1%8F+%D0%BE%D0%B1%D0%BB%D0%B0%D1%81%D1%82%D1%8C/@49.8361283,23.9364041,13z/data=!3m1!4b1!4m9!4m8!1m0!1m5!1m1!1s0x473add8a132bb41b:0x3b8ecfdc4901b5b0!2m2!1d23.9776033!2d49.8360802!3e3?hl=ru-RU&entry=ttu",
1778              },
1779            ];
1780        
1781            const stations = isPolishVersion 
1782              ? allStations.filter((station) => !station.isUkraineLocation) 
1783              : allStations
1784        
1785            // desktop map instance
1786            const mapDesktop = new google.maps.Map(mapEl, {
1787              zoom: 10,
1788              // disableDefaultUI: true,
1789              // styles: styles,
1790            });
1791        
1792            // Mobile tab map instance
1793            const activeMobileMapInstance = new google.maps.Map(mobileMapEl, {
1794              zoom: 10,
1795            })
1796        
1797            const map = isDesktop ? mapDesktop : activeMobileMapInstance
1798        
1799            const generalTranslations = getGeneralTranslations()
1800        
1801            const infoWindow = new google.maps.InfoWindow();
1802        
1803            function generateInfoModalContent(station) {
1804              return station ? `
1805                <div class="google-maps-content">
1806                  <p class="google-maps-content__city">${station.tooltipTitle}</p>
1807                  <p class="google-maps-content__description">${station.street}</p>
1808                  <p class="google-maps-content__schedule">${(station.name === 'lviv' ? generalTranslations.short_schedule : generalTranslations.schedule)} <span class="google-maps-content__value">${station.schedule}</span></p>
1809                  ${station.name === 'lviv' ? `
1810                    <p class="google-maps-content__schedule">
1811                      ${generalTranslations.sunday_off}
1812                    </p>
1813                  ` : ''}
1814                  ${isPolishVersion ? `
1815                    <p class="google-maps-content__schedule">
1816                      Sobota <span class="google-maps-content__value">09:00 - 16:00</span> <br>
1817                    </p>
1818                    <p class="google-maps-content__schedule">
1819                      Niedziela - <span class="google-maps-content__value">dzień wolny</span>
1820                    </p>
1821                  ` : ''}
1822                  <p class="google-maps-content__phone">
1823                    ${generalTranslations.phone} 
1824                    <a href="tel:${station.phone}" class="google-maps-content__value">${station.phone}</a>
1825                  </p>
1826                  <div class="google-maps-content__row">
1827                      <a href="${station.route}" class="google-maps-content__route" target="_blank">${generalTranslations.routeName}</a>
1828                      ${station?.video?.url
1829                        ? `<a
1830                              href="${station?.video?.url}"
1831                              class="google-maps-content__route"
1832                              target="_blank"
1833                             >${station.video.label}</a>`
1834                        : ''
1835                      }
1836                  </div>
1837                </div>
1838              ` : ''
1839            }
1840        
1841            const setMarkers = (mapInstance, stations, coords, isFromCLoseButton) => {
1842              if (stations.length === 1 && !isFromCLoseButton) {
1843                // selection of first sidebar station
1844                const station = stations[0];
1845                const prop = station.name;
1846                const selectors = {
1847                  desktop: `.stations-map-desktop .stations-map__list-item[data-prop=${prop}]`,
1848                  mobile: `.stations-mobile .stations-map__list-item[data-prop=${prop}]`
1849                }
1850                const dynamicLinkSelector = isDesktop 
1851                  ? selectors.desktop
1852                  : selectors.mobile
1853                const currentLink = stationsList.querySelector(dynamicLinkSelector);
1854                // currentLink.click()
1855                setTimeout(() => {
1856                  setActiveClass(stationLinks, currentLink);
1857                  const name = currentLink.querySelector(".content__title").textContent;
1858                  setMobileContent(currentLink, station);
1859                  isSomeStationActive = true;
1860                  showMapControls(name, station);
1861                  toggleMobileBackBtn();
1862                  // currentLink.classList.add('js--active')
1863                }, 0);
1864              }
1865              stations.forEach((station) => {
1866                const marker = new google.maps.Marker({
1867                  position: station.position,
1868                  icon: icon,
1869                  map: mapInstance,
1870                  title: station.tooltipTitle
1871                  // animation: google.maps.Animation.DROP,
1872                });
1873        
1874                markers.push(marker);
1875                marker.addListener("click", () => {
1876                  mapInstance.setZoom(18);
1877                  infoWindow.setContent(generateInfoModalContent(station))
1878                  infoWindow.open(mapInstance, marker)
1879                  mapInstance.panTo(marker.getPosition());
1880          
1881                  const selectors = {
1882                    desktop: `.stations-map-desktop .stations-map__list-item[data-prop=${station.name}]`,
1883                    mobile: `.stations-mobile .stations-map__list-item[data-prop=${station.name}]` 
1884                  }
1885                  const dynamicSelector = isDesktop 
1886                    ? selectors.desktop
1887                    : selectors.mobile
1888        
1889                  const target = document.querySelector(dynamicSelector);
1890                  setActiveClass(stationLinks, target);
1891                  scrollToStation(target);
1892                  const name = target.querySelector(".content__title").textContent;
1893                  const obj = stations.find((p) => p.name === station.name);
1894                  setMobileContent(target, obj);
1895                  isSomeStationActive = true;
1896                  showMapControls(name, obj);
1897                  toggleMobileBackBtn();
1898                });
1899              });
1900              mapInstance.panTo(coords);
1901            };
1902        
1903            const reloadMarkers = (mapInstance) => {
1904              markers.forEach((marker) => {
1905                mapInstance.setZoom(10);
1906                marker.setMap(null);
1907              });
1908            };
1909        
1910            // Desktop Top filters above the map
1911            const mapDesktopNavLinks = document.querySelectorAll(".stations-map-desktop .stations-map__nav .link");
1912            initMapNavLinks(map, mapDesktopNavLinks)
1913        
1914            function initMapNavLinks(map, links) {
1915              links.forEach((link) => {
1916                link.addEventListener("click", () => {
1917                  const newStations = cities[link.dataset.prop].prop
1918                      ? stations.filter((p) => p.city === link.dataset.prop)
1919                      : stations;
1920                  reloadMarkers(map);
1921                  setMarkers(map, newStations, cities[link.dataset.prop].coords);
1922                  setActiveClass(links, link);
1923                  // TODO: HERE
1924                  setActiveClass(stationLinks);
1925                  hideStations(link.dataset.prop);
1926                  currentFilter = link.dataset.prop;
1927                  hideMapControls(map);
1928                  scrollToStation();
1929                });
1930              });
1931            }
1932        
1933            // left sidebar buttons
1934            const dynamicSelector = isDesktop 
1935              ? ".stations-map-desktop .stations-map__list .stations-map__list-item"
1936              : ".stations-mobile .stations-map__list .stations-map__list-item"
1937            const stationLinks = document.querySelectorAll(
1938                dynamicSelector
1939            );
1940            stationLinks.forEach((link) => {
1941              link.addEventListener("click", () => {
1942                const selectedStation = stations.find((p) => p.name === link.dataset.prop)
1943                const selectedMarker = markers.find((marker) => marker.position?.lat() === selectedStation.position?.lat())        
1944        
1945                if (selectedMarker) {
1946                  infoWindow.setContent(generateInfoModalContent(selectedStation))
1947                  infoWindow.open(map, selectedMarker)
1948                };
1949                map.setZoom(15);
1950                map.panTo(selectedStation.position);
1951                setActiveClass(stationLinks, link);
1952                const name = link.querySelector(".content__title").textContent;
1953                const obj = stations.find((p) => p.name === link.dataset.prop);
1954                setMobileContent(link, obj);
1955                isSomeStationActive = true;
1956                showMapControls(name, obj);
1957                toggleMobileBackBtn();
1958              });
1959            });
1960        
1961            const setActiveClass = (items, target) => {
1962              items.forEach((p) => {
1963                p.classList.remove("js--active");
1964              });
1965              if (target) {
1966                target.classList.add("js--active");
1967                if (window.innerWidth < 1024) {
1968                  scrollToStation();
1969                }
1970              }
1971            };
1972        
1973            const hideStations = (prop) => {
1974              if (cities[prop].prop) {
1975                stationLinks.forEach((p) => p.classList.add("d-none"));
1976                const currentStationLinks = document.querySelectorAll(
1977                    `.stations-map__list-item[data-city=${prop}]`
1978                );
1979                currentStationLinks.forEach((p) => {
1980                  p.classList.remove("d-none");
1981                  p.classList.remove("js--hidden--mobile");
1982                });
1983              } else {
1984                stationLinks.forEach((p) => {
1985                  p.classList.remove("d-none");
1986                  p.classList.remove("js--hidden--mobile");
1987                });
1988              }
1989            };
1990        
1991            const showMapControls = (name, { schedule, weekend, route, phone }) => {
1992              const obj = {
1993                name: name,
1994                route: route,
1995                schedule: schedule,
1996                weekend: Drupal.t(weekend),
1997                phone: phone,
1998              };
1999              setDesktopContent(obj, false);
2000              mapHeader.classList.add("js--active");
2001              mapFooter.classList.add("js--active");
2002              // mapEl.classList.add('js--active')
2003            };
2004            const hideMapControls = (mapInstance, isFromCloseButton) => {
2005              isFromCloseButton = !!isFromCloseButton;
2006              setDesktopContent({}, true);
2007              mapHeader.classList.remove("js--active");
2008              mapFooter.classList.remove("js--active");
2009              // mapEl.classList.remove('js--active')
2010              const newStations = cities[currentFilter].prop
2011                  ? stations.filter((p) => p.city === currentFilter)
2012                  : stations;
2013              reloadMarkers(mapInstance);
2014              setMarkers(mapInstance, newStations, cities[currentFilter].coords, isFromCloseButton);
2015              setActiveClass(stationLinks);
2016              hideStations(currentFilter);
2017              isSomeStationActive = false;
2018              toggleMobileBackBtn();
2019            };
2020        
2021            mapHeader.querySelector(".close").addEventListener("click", () => {
2022              const mapInstance = isDesktop ? map : activeMobileMapInstance
2023              hideMapControls(mapInstance, true);
2024            });
2025        
2026            const setDesktopContent = (
2027                { name, schedule, weekend, phone, route },
2028                isClear
2029            ) => {
2030              mapHeader.querySelector(".name").textContent = isClear ? "" : name;
2031              mapFooter.querySelector(
2032                  ".bottom__schedule-item--total .text"
2033              ).textContent = isClear ? "" : schedule;
2034              mapFooter.querySelector(
2035                  ".bottom__schedule-item--weekend .text"
2036              ).textContent = isClear ? "" : weekend;
2037              mapFooter.querySelector(".phone").textContent = isClear ? "" : phone;
2038              mapFooter.querySelector(".phone").href = isClear ? "" : `tel:${phone}`;
2039              mapFooter.querySelector(".buttons__route").href = isClear ? "" : route;
2040              if (typeof window.BinotelCallTracking !== 'undefined' && window.BinotelCallTracking[502069]) {
2041                window.BinotelCallTracking[502069].replacePhoneNumbersOnDynamicContent();
2042              }
2043            };
2044        
2045            const setMobileContent = (
2046                selector,
2047                { schedule, weekend, route, phone }
2048            ) => {
2049              if (!selector) {
2050                console.log('setMobileContent no selector', selector)
2051                return
2052              }
2053              selector.querySelector(".schedule-item--total .text").textContent =
2054                  schedule;
2055              selector.querySelector(".schedule-item--weekend .text").textContent =
2056                  Drupal.t(weekend);
2057              selector.querySelector(".link--route").href = route;
2058              selector.querySelector(".phone").href = `tel:${phone}`;
2059              selector.querySelector(".phone").textContent = phone;
2060              if (typeof window.BinotelCallTracking !== 'undefined' && window.BinotelCallTracking[502069]) {
2061                window.BinotelCallTracking[502069].replacePhoneNumbersOnDynamicContent();
2062              }
2063            };
2064        
2065            const initDesktopMap = () => {
2066              const availableStations = isPolishVersion 
2067                ? stations.filter((station) => !station.isUkraineLocation) 
2068                : stations
2069        
2070              setMarkers(map, availableStations, initialCoordinates)
2071            };
2072            initDesktopMap();
2073        
2074            // Don't know why add scrollbar for list, maybe for cross browser styles,
2075            // just leave this shit for now
2076            const stationsListPs = new PerfectScrollbar(".stations-map-desktop .stations-map__list", {
2077              wheelSpeed: 1,
2078              wheelPropagation: false,
2079              swipeEasing: true,
2080              minScrollbarLength: 20,
2081              suppressScrollX: true,
2082            });
2083            const stationsListPsMobile = new PerfectScrollbar(".stations-mobile .stations-map__list", {
2084              wheelSpeed: 1,
2085              wheelPropagation: false,
2086              swipeEasing: true,
2087              minScrollbarLength: 20,
2088              suppressScrollX: true,
2089            });
2090            const scrollToStation = (target) => {
2091              document.querySelector(".stations-map__list").scrollTo({
2092                top: target ? target.offsetTop : 0,
2093                behavior: "smooth",
2094              });
2095              stationsListPs.update();
2096              stationsListPsMobile.update();
2097              // $('.stations-map__list').animate({scrollTop: target.offsetTop}, 1000);
2098            };
2099        
2100            mobileStationsToggler.addEventListener("click", function () {
2101              isMobileStationsListOpen = true;
2102              this.classList.add("js--hidden");
2103              stationsList.classList.add("js--active");
2104              mobileHideStations.classList.add("js--active");
2105              // mapEl.classList.add("js--collapsed");
2106              toggleMobileBackBtn();
2107            });
2108        
2109            mobileHideStations.addEventListener("click", function () {
2110              isMobileStationsListOpen = false;
2111              this.classList.remove("js--active");
2112              stationsList.classList.remove("js--active");
2113              mobileStationsToggler.classList.remove("js--hidden");
2114              // mapEl.classList.remove("js--collapsed");
2115              toggleMobileBackBtn();
2116              // hideMapControls()
2117            });
2118        
2119            mobileBackBtn.addEventListener("click", () => {
2120              const mapInstance = isDesktop ? map : activeMobileMapInstance
2121              hideMapControls(mapInstance, true);
2122            });
2123        
2124            const toggleMobileBackBtn = () => {
2125              if (isMobileStationsListOpen && isSomeStationActive) {
2126                mobileBackBtn.classList.add("js--active");
2127                citiesFilter.classList.add("js--hidden");
2128              } else {
2129                mobileBackBtn.classList.remove("js--active");
2130                citiesFilter.classList.remove("js--hidden");
2131              }
2132            };
2133        
2134            function initMobileStationActive() {
2135              const tabSelectors = {
2136                listed: {
2137                  tab: document.querySelector('.stations-mobile__tab--listed'),
2138                  body: document.querySelector('.stations-mobile__tab-body--listed'),
2139                },
2140                map: {
2141                  tab: document.querySelector('.stations-mobile__tab--map'),
2142                  body: document.querySelector('.stations-mobile__tab-body--map'),
2143                }
2144              }
2145        
2146              const { listed, map } = tabSelectors
2147        
2148              // Check if all elements present
2149              if (!listed.tab || !map.tab || !listed.body || !map.body) return
2150        
2151              // Set listed to be default active tab
2152              setActiveTab('listed')
2153        
2154              // Event listeners
2155              listed.tab.addEventListener('click', () => setActiveTab('listed'))
2156              map.tab.addEventListener('click', () => setActiveTab('map'))
2157        
2158              function setActiveTab(activeKey) {
2159                Object.entries(tabSelectors).forEach(([key, { tab, body }]) => {
2160                  const isActive = key === activeKey
2161                  tab.classList.toggle('active', isActive)
2162                  body.classList.toggle('active', isActive)
2163                })
2164              }
2165            }
2166        
2167            initMobileStationActive()
2168        
2169            function initStationAccordions() {
2170              const stationElements = document.querySelectorAll('.stations-mobile__city-station')
2171              if (!stationElements.length) return
2172        
2173              let activeStationEl = null
2174              let activeMapInstance = null
2175        
2176              function closeOpenedStation() {
2177                if (!activeStationEl) return
2178        
2179                activeStationEl.classList.remove('active')
2180                const prevMap = activeStationEl.querySelector('.map')
2181                if (prevMap) prevMap.style.display = 'none'
2182              }
2183        
2184              stationElements.forEach(stationEl => {
2185                const headingEl = stationEl.querySelector('.stations-mobile__city-station-heading')
2186                const stationMapEl = stationEl.querySelector('.map')
2187                const cityId = stationEl.dataset.id
2188                const foundStation = allStations.find((item) => item.name === cityId)
2189        
2190                if (!foundStation) return
2191                
2192                const lat = parseFloat(foundStation.position?.lat())
2193                const lng = parseFloat(foundStation?.position?.lng())
2194        
2195                headingEl.addEventListener('click', (e) => {
2196                  const isArrow = e.target.classList.contains('stations-mobile__station-arrow')
2197        
2198                  if (stationEl === activeStationEl && !isArrow) {
2199                    return
2200                  }
2201        
2202                  // if station is active and click on arrow — close this and clear
2203                  if (stationEl === activeStationEl && isArrow) {
2204                    closeOpenedStation()
2205                    activeStationEl = null
2206                    return
2207                  }
2208        
2209                  // deactivate previous station and hide map
2210                  if (activeStationEl) {
2211                    closeOpenedStation()
2212                  }
2213        
2214                  // make a new station active
2215                  activeStationEl = stationEl
2216                  activeStationEl.classList.add('active')
2217                  stationMapEl.style.display = 'block'
2218        
2219                  // init map
2220                  activeMapInstance = new google.maps.Map(stationMapEl, {
2221                    center: { lat, lng },
2222                    zoom: 15,
2223                  })
2224        
2225                  const marker = new google.maps.Marker({
2226                    position: { lat, lng },
2227                    icon: icon,
2228                    map: activeMapInstance,
2229                    title: cityId,
2230                  })
2231        
2232                  function openMarkerInfo() {
2233                    activeMapInstance.setZoom(15)
2234                    infoWindow.setContent(generateInfoModalContent(foundStation))
2235                    infoWindow.open(activeMapInstance, marker)
2236                    activeMapInstance.panTo(marker.getPosition())
2237                  }
2238        
2239                  openMarkerInfo()
2240        
2241                  marker.addListener("click", openMarkerInfo)
2242                })
2243              })
2244            }
2245        
2246            initStationAccordions()
2247        
2248            function initMobileMap() {
2249              if (!mobileMapEl) return
2250        
2251              const availableStations = isPolishVersion 
2252                ? stations.filter((station) => !station.isUkraineLocation) 
2253                : stations
2254        
2255              setMarkers(activeMobileMapInstance, availableStations, initialCoordinates)
2256        
2257              const mapMobileNavLinks = document.querySelectorAll(".stations-mobile .stations-map__nav .link");
2258              initMapNavLinks(activeMobileMapInstance, mapMobileNavLinks)
2259            }
2260        
2261            initMobileMap()
2262        
2263            function setActiveStationByPage() {
2264              const path = window.location.pathname;
2265        
2266              // 1. Конфігурація відповідностей шляхів і ID станцій
2267              const stationRoutes = [
2268                {
2269                  id: 'borispol',
2270                  paths: ['/uk/kontakty/borispol', '/kontakty/borispol'],
2271                },
2272                {
2273                  id: 'irpen',
2274                  paths: ['/uk/stantsiya-irpin', '/stanciya-irpen', '/stacja-irpen'],
2275                },
2276                {
2277                  id: 'warszawa',
2278                  paths: ['/mi-u-polschi', '/uk/my-u-polshchi'],
2279                },
2280                {
2281                  id: 'lviv',
2282                  paths: ['/uk/stantsiya-lviv', '/stanciya-lvov'],
2283                },
2284              ]
2285        
2286              // 2. Пошук відповідної станції за URL
2287              const matchedStation = stationRoutes.find(route => route.paths.includes(path))
2288              if (!matchedStation) return
2289        
2290              const stationId = matchedStation.id
2291              const selectedStation = stations.find(p => p.name === stationId)
2292              const selectedMarker = markers.find(marker => marker.position?.lat() === selectedStation?.position?.lat())
2293        
2294              if (!selectedMarker) return
2295          
2296              // 3. Відображення маркера та інформаційного вікна
2297              setActiveMarkerInfo(selectedStation, selectedMarker)
2298        
2299              // 4. Активуємо відповідний DOM-елемент
2300              const selectors = {
2301                desktop: `.stations-map-desktop .stations-map__list-item[data-prop=${stationId}]`,
2302                mobile: `.stations-mobile .stations-map__list-item[data-prop=${stationId}]`,
2303              };
2304              const dynamicLinkSelector = isDesktop ? selectors.desktop : selectors.mobile
2305              const link = document.querySelector(dynamicLinkSelector)
2306              if (!link) return
2307        
2308              setActiveClass(stationLinks, link);
2309        
2310              const name = link.querySelector(".content__title")?.textContent;
2311              const obj = stations.find(p => p.name === link.dataset.prop);
2312        
2313              setMobileContent(link, obj);
2314              isSomeStationActive = true;
2315              showMapControls(name, obj);
2316              toggleMobileBackBtn();
2317            }
2318        
2319            setActiveStationByPage()
2320        
2321            function setActiveMarkerInfo(selectedStation, selectedMarker) {
2322              if (isDesktop) {
2323                infoWindow.setContent(generateInfoModalContent(selectedStation))
2324                infoWindow.open(map, selectedMarker)
2325                map.setZoom(15)
2326                map.panTo(selectedStation.position)
2327              } else {
2328                const listedMobileStationHeading = document.querySelector(
2329                  `.stations-mobile__city-station[data-id="${selectedStation.name}"] .stations-mobile__city-station-heading`
2330                )
2331                if (listedMobileStationHeading) {
2332                  setTimeout(() => {
2333                    listedMobileStationHeading.click()
2334                  }, 100)
2335                }
2336              }
2337            }
2338        
2339            // the smooth zoom function
2340            // function smoothZoom (map, max, cnt) {
2341            //   if (cnt >= max) {
2342            //     return;
2343            //   }
2344            //   else {
2345            //     const z = google.maps.event.addListener(map, 'zoom_changed', function(event){
2346            //       google.maps.event.removeListener(z);
2347            //       smoothZoom(map, max, cnt + 1);
2348            //     });
2349            //     setTimeout(function(){map.setZoom(cnt)}, 80); // 80ms is what I found to work well on my system -- it might not work well on all systems
2350            //   }
2351            // }
2352          }
2353        };
2354        
2355
2356        const sideAnnouncesWrapper = document.querySelector('.side-announces')
2357        const sideAnnouncesKey = 'sideAnnounces'
2358        if (sideAnnouncesWrapper) {
2359          const observeAnnounces = () => {
2360            const observer = new IntersectionObserver((entries) => {
2361              entries.forEach((entry) => {
2362                // console.log(entry)
2363                if (entry.isIntersecting) {
2364                  entry.target.classList.add('js--active')
2365                }
2366              })
2367            }, {})
2368            observer.observe(sideAnnouncesWrapper)
2369          }
2370          const sessionStorageData = (key) => sessionStorage.getItem(key)
2371          const getSessionStorageData = (key) => JSON.parse(sessionStorageData(key))
2372          const sideAnnounces = sideAnnouncesWrapper.querySelectorAll(
2373            '.side-announces__item',
2374          )
2375          const getState = () => getSessionStorageData(sideAnnouncesKey)
2376          const getLastIndex = (arr) => arr.slice(-1)[0]
2377          const setDataToSessionStorage = (data) => {
2378            sessionStorage.setItem(sideAnnouncesKey, JSON.stringify(data))
2379          }
2380          const createInitialState = () => [0]
2381        
2382          const activateAnnounce = () => {
2383            const index = getLastIndex(getState())
2384            sideAnnounces[index].classList.add('js--active')
2385            const closeBtn = sideAnnounces[index].querySelector('.close')
2386        
2387            if(!!closeBtn) {
2388              closeBtn.addEventListener('click', () => {
2389                sideAnnounces[index].classList.remove('js--active')
2390                sideAnnouncesWrapper.classList.add('js--hidden')
2391              })
2392            }
2393          }
2394          if (sessionStorageData(sideAnnouncesKey)) {
2395            const state = getState()
2396            const newIndex = getLastIndex(state) + 1
2397            if (newIndex < sideAnnounces.length) {
2398              observeAnnounces()
2399              state.push(newIndex)
2400              setDataToSessionStorage(state)
2401              activateAnnounce()
2402            }
2403          } else {
2404            const initialState = createInitialState()
2405            observeAnnounces()
2406            setDataToSessionStorage(initialState)
2407            activateAnnounce()
2408          }
2409          // sideAnnounces.forEach((p, index) => { console.log(index) })
2410        }
2411        
2412
2413      }
2414
2415      const numReg = new RegExp('^\\d*[.|,]?\\d*$')
2416      const replaceVal = val => val.replace(/\D/g, '');
2417
2418      //Код написанный здесь будет выполнен при каждом AJAX запросе
2419
2420      $(".paragraph--cta-hr .form-item-field-years-0-value input").on('propertychange input', function ()
2421
2422      {
2423        // const submit = $(this).parent().siblings('.button')
2424        if (!numReg.test(this.value) || (this.value === '')) {
2425          this.value = replaceVal(this.value)
2426        }
2427      });
2428      $(".paragraph__calculator .form-item-form-text:not(.form-item-email) input").on('propertychange input', function ()
2429      {
2430        if (!numReg.test(this.value)) {
2431            this.value = replaceVal(this.value)
2432          }
2433      });
2434
2435      $(".form-item-form-select select").change(function () {
2436        setTimeout(() => {
2437          $('.chosen-search-input').blur()
2438        }, 100)
2439      })
2440
2441      // $(".paragraph__calculator .form-item-form-text input").mask("+38 (099) 999 99 99");
2442      const detailsList = document.querySelector('.details__set-modal .list-wrapper')
2443      if (detailsList) {
2444        const detailsListPs = new PerfectScrollbar(detailsList, {
2445          wheelSpeed: 1,
2446          wheelPropagation: false,
2447          swipeEasing: true,
2448          minScrollbarLength: 20,
2449          suppressScrollX: true
2450
2451        });
2452      }
2453
2454      const toTopButton = $('.to-top-button');
2455      $(window).scroll(function() {
2456        if ($(this).scrollTop() > 1000) {
2457          toTopButton.addClass('visible');
2458        } else {
2459          toTopButton.removeClass('visible');
2460        }
2461      });
2462
2463      toTopButton.click(function() {
2464        $('html, body').animate({ scrollTop: 0 }, 300);
2465      });
2466    }
2467  };
2468}(jQuery, Drupal));
2469
2470
2471(function ($, Drupal) {
2472    Drupal.behaviors.validation = {
2473        attach: function (context) {
2474
2475            function standartMusk (event){
2476                let x = event.target.value
2477                    .replace(/\D/g, "")
2478                    .match(/(\d{0,3})(\d{0,9})/);
2479
2480                if (event.target.value.length > 13){
2481                    event.target.value = event.target.value.slice(0, 13);
2482                }
2483
2484                if (!x[2]) {
2485                    event.target.value = "+380";
2486                    return
2487                }
2488
2489                event.target.value = `+${x[1]}${x[2]}`;
2490            }
2491
2492            function  languagePlMusk (event){
2493                let x = event.target.value
2494                    .replace(/\D/g, "")
2495                    .match(/(\d{0,11})/);
2496
2497                if (event.target.value.length > 12){
2498                    event.target.value = event.target.value.slice(0, 12);
2499                }
2500
2501
2502                event.target.value = `+${x[1]}`;
2503            }
2504
2505            function inputClickPosition (event){
2506                event.target.selectionStart = event.target.selectionStart < 4 ? 4 : event.target.selectionStart
2507            }
2508
2509            function handlePLInputClickPosition(event) {
2510                const input = event.target;
2511                const value = input.value;
2512            
2513                // Ensure that the cursor remains after +380 or after the entered numbers
2514                const prefixLength = 3; // length of "+380"
2515                const digitsOnly = value.slice(prefixLength).replace(/\D/g, ''); // all digits after "+380"
2516            
2517                const newCursorPosition = digitsOnly.length + prefixLength; // Position after the last digit or +380
2518            
2519                // Place the cursor after +380 or the last entered digit
2520                setTimeout(() => {
2521                    input.selectionStart = input.selectionEnd = Math.max(newCursorPosition, prefixLength);
2522                }, 0);
2523            }
2524
2525            function handleInputClickPosition(event, prefixLength = 4) {
2526                const input = event.target;
2527            
2528                // Ensure that the cursor remains after +380 or after the entered numbers
2529                const digitsOnly = input.value.slice(prefixLength).replace(/\D/g, ''); // all digits after prefixLength
2530            
2531                const newCursorPosition = digitsOnly.length + prefixLength; // Position after the last digit or +380
2532            
2533                // Place the cursor after +380 or the last entered digit
2534                setTimeout(() => {
2535                    input.selectionStart = input.selectionEnd = Math.max(newCursorPosition, prefixLength);
2536                }, 0);
2537            }
2538
2539            function setPhoneError (input, error){
2540                input.addClass('input-error')
2541                input.next('.input-error__text').remove();
2542                input.after(`<p class='input-error__text'>${error}</p>`);
2543            }
2544
2545            function removePhoneError (input) {
2546                input.removeClass('input-error');
2547                input.next('.input-error__text').remove();
2548            }
2549
2550            // click position
2551            $('input[name="contact_info[phone]"]').on('click', (event)=> inputClickPosition(event));
2552
2553            const domenIsPL = drupalSettings.path.currentLanguage === 'pl'
2554
2555            if (domenIsPL){
2556                $(".form-item-form-tel input").attr('placeholder', '+48').mask("+99999999999");
2557                $('input[name="contact_info[phone]"]').attr('placeholder', '+48')
2558                $(".form-item-form-tel input").on('click focus', (event)=> handleInputClickPosition(event, 1));
2559
2560                $('input[name="contact_info[phone]"]').on('focus', (event)=> languagePlMusk(event));
2561                $('input[name="contact_info[phone]"]').on('input',(event)=> languagePlMusk(event));
2562                $('#edit-payment-type-answer-2').siblings('label').hide();
2563
2564                // form validation
2565                $("form").on( "submit", function( event ) {
2566                    event.preventDefault();
2567
2568                    const phoneInput = $(this).find('input[name="contact_info[phone]"]');
2569                    let errorText = ''
2570                    let isError = false
2571
2572                    removePhoneError(phoneInput)
2573
2574                    // phone validation
2575
2576                    $(this).find(phoneInput).each(function() {
2577
2578                        if(phoneInput.val().length === 0){
2579                            errorText = "Pole jest obowiązkowe"
2580                            setPhoneError(phoneInput,errorText)
2581                            isError = true
2582                        }
2583
2584                        if(phoneInput.val().length !== 12) {
2585                            errorText = 'Sprawdź prawidłowe wejście'
2586                            setPhoneError(phoneInput,errorText)
2587                            isError = true
2588                        }
2589
2590                    })
2591
2592                    // ...
2593
2594                    if (isError) return
2595
2596                    this.submit();
2597                });
2598
2599            }else{
2600                $(".form-item-form-tel input").attr('placeholder', '+380').mask("+380999999999");
2601                $('input[name="contact_info[phone]"]').attr('placeholder', '+380')
2602                $('input[name="contact_info[phone]"]').on('focus',(event)=> standartMusk(event));
2603                $('input[name="contact_info[phone]"]').on('input',(event)=> standartMusk(event));
2604                $(".form-item-form-tel input").on('click focus', (event)=> handleInputClickPosition(event, 4));
2605
2606                // form validation
2607
2608                $("form").on( "submit", function( event ) {
2609                    event.preventDefault();
2610
2611                    const phoneInput = $(this).find('input[name="contact_info[phone]"]');
2612                    const operatorArr = ['+38039','+38067','+38068','+38096','+38097','+38098','+38050','+38066','+38095',"+38099","+38063","+38073","+38093","+38091","+38092","+38089","+38094"]
2613                    let errorText = ''
2614                    let isError = false
2615
2616                    removePhoneError(phoneInput)
2617
2618                    // phone validation
2619
2620                    $(this).find(phoneInput).each(function() {
2621
2622                        const checkOperatorInVal = operatorArr.some((operator) =>
2623                            phoneInput.val().slice(0, 6).startsWith(operator)
2624                        );
2625
2626                        if(phoneInput.val().length === 0){
2627
2628                            if (window.location.href.indexOf('/uk') !== -1) {
2629                                errorText = "Поле обв'язкове до заповенння"
2630                            }else{
2631                                errorText = 'Поле обезательное к заполнению'
2632                            }
2633
2634                            setPhoneError(phoneInput,errorText)
2635                            isError = true
2636                        }
2637
2638                        if(phoneInput.val().length !== 13) {
2639
2640                            if (window.location.href.indexOf('/uk') !== -1) {
2641                                errorText = 'Перевірте правильність введення'
2642                            }else{
2643                                errorText = 'Проверьте правильность ввода'
2644                            }
2645
2646                            setPhoneError(phoneInput,errorText)
2647                            isError = true
2648                        }
2649
2650                        if(!checkOperatorInVal){
2651
2652                            if (window.location.href.indexOf('/uk') !== -1) {
2653                                errorText = 'Перевірте правильність введення'
2654                            }else{
2655                                errorText = 'Проверьте правильность ввода'
2656                            }
2657
2658                            setPhoneError(phoneInput,errorText)
2659                            isError = true
2660                        }
2661                    })
2662
2663                    // ...
2664
2665                    if (isError) return
2666
2667                    $(".preloader--spin").addClass("js--active");
2668                    this.submit();
2669                });
2670
2671            }
2672        }
2673    };
2674}(jQuery, Drupal));
2675

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.