PageSourceSearch

https://capitaltour.ru/bitrix/cache/js/s1/travelsoft/page_705e6a31…2abd33c6d514059c5845e_v1.js?178876247485072

js capitaltour.ru collected 2026-10-08 02:28:55 UTC 85,072 bytes, 2,011 lines download raw bytes

1
2; /* Start:"a:4:{s:4:"full";s:96:"/local/templates/travelsoft/components/bitrix/news.list/headicontSwiper/script.js?17773209312366";s:6:"source";s:81:"/local/templates/travelsoft/components/bitrix/news.list/headicontSwiper/script.js";s:3:"min";s:0:"";s:3:"map";s:0:"";}"*/
3document.addEventListener('DOMContentLoaded', function () {
4    const swiper = new Swiper(".headicontSwiper", {
5        loop: true,
6        lazy: true,
7        speed: 800, // Увеличил скорость для плавности
8        effect: 'fade',
9        fadeEffect: {
10            crossFade: true
11        },
12        slidesPerView: 1,
13        spaceBetween: 0,
14        navigation: {
15            nextEl: '.swiper-button-next',
16            prevEl: '.swiper-button-prev',
17        },
18        pagination: {
19            el: ".swiper-pagination",
20            clickable: true,
21        },
22        autoplay: {
23            delay: 6000, // 3 секунды
24            disableOnInteraction: false // чтобы не останавливался при клике
25        },
26        on: {
27            init: function () {
28                animateSlide(this.activeIndex);
29            },
30            slideChangeTransitionStart: function () {
31                resetAnimation();
32            },
33            slideChangeTransitionEnd: function () {
34                animateSlide(this.activeIndex);
35            }
36        }
37    });
38
39    // Функция сброса анимации
40    function resetAnimation() {
41        const slides = document.querySelectorAll('.swiper-slide');
42        slides.forEach(slide => {
43            slide.querySelectorAll('.animate-on-scroll').forEach(el => {
44                el.classList.remove('visible');
45            });
46            slide.querySelectorAll('.fiturs-ttl').forEach(text => {
47                text.style.opacity = '1';
48            });
49        });
50    }
51
52    // Функция анимации для конкретного слайда
53    function animateSlide(slideIndex) {
54        const slides = document.querySelectorAll('.swiper-slide');
55        const activeSlide = slides[slideIndex];
56
57        if (!activeSlide) return;
58
59        // Анимируем контейнеры
60        const elements = activeSlide.querySelectorAll('.animate-on-scroll');
61        elements.forEach((el, index) => {
62            setTimeout(() => {
63                el.classList.add('visible');
64            }, 200 + (index * 200)); // Задержка для каждого элемента
65        });
66    }
67
68    // Инициализация при загрузке
69    setTimeout(() => {
70        resetAnimation();
71        animateSlide(0);
72    }, 500);
73});
74/* End */
75;
76; /* Start:"a:4:{s:4:"full";s:95:"/local/templates/travelsoft/components/bitrix/news.list/filter_tour25/script.js?178315032353695";s:6:"source";s:79:"/local/templates/travelsoft/components/bitrix/news.list/filter_tour25/script.js";s:3:"min";s:0:"";s:3:"map";s:0:"";}"*/
77
78document.addEventListener('DOMContentLoaded', function () {
79
80
81
82    // Глобальные переменные для хранения данных
83    const rootFilter = document.querySelector('[data-ts-component="filter_tour25"]');
84    if (!rootFilter) {
85        console.warn('[filter_tour25] Корневой контейнер не найден, инициализация пропущена');
86    } else {
87        let config = {};
88        try {
89            config = JSON.parse(rootFilter.dataset.tsConfig || '{}');
90        } catch (e) {
91            config = {};
92        }
93
94
95
96
97        let selectedCityId = null;
98        let selectedCountryId = null;
99        let selectedDate = null;
100        let selectedDuration = null;
101        let filterData = null;
102        let selectedTourId = null;
103        let selectedTour = null;
104        let adultCount = 2;
105        let childCount = 0;
106        let childAges = Array(3).fill(6);
107        let availableNights = [];
108        let selectedCalendarDate = null;
109        let selectedNightsCount = null;
110        let countriesData = null;
111        let countriesFlags = [];
112
113        const ajaxPath = config.ajaxPath;
114
115        // Элементы формы
116        const citySelectBtn = rootFilter.querySelector('#city-select-btn');
117        const countrySelectBtn = rootFilter.querySelector('#country-select-btn');
118        const dateSelectBtn = rootFilter.querySelector('#date-select-btn');
119        const personsSelectBtn = rootFilter.querySelector('#persons-select-btn');
120        const findLink = rootFilter.querySelector('#find-tour-link');
121
122        // !citySelectBtn || !countrySelectBtn || !dateSelectBtn || !personsSelectBtn || !findLink
123        // if (!true) {
124        //     console.warn('[filter_tour25] Не найдены обязательные элементы фильтра, инициализация пропущена');
125        // } else {
126
127        // Инициализация при загрузке страницы
128        // document.addEventListener('DOMContentLoaded', function () {
129        // loadInitialData();
130        loadCountriesData()
131            .then(data => {
132                if (data && data.cityFrom && data.cityFrom.length > 0) {
133                    citySelectBtn.disabled = false;
134                    filterData = data;
135                    console.log("!!!!!!!!!!!!!!!!!!!!!!");
136                    console.log(filterData);
137                    console.log("!!!!!!!!!!!!!!!!!!!!!!");
138                }
139            })
140            .catch(error => {
141                console.error('Ошибка при загрузке начальных данных:', error);
142            });
143        initEventHandlers();
144
145        // });
146
147        // Загрузка начальных данных (города и страны)
148        function loadInitialData() {
149            fetch('/local/templates/travelsoft/components/bitrix/news.list/filter_tour25/proxy.php?countryTo=2&cityFrom=30&flightTo=true&' + Math.random())
150                .then(response => response.json())
151                .then(data => {
152                    filterData = data;
153                    if (data.cityFrom && data.cityFrom.length > 0) {
154                        citySelectBtn.disabled = false;
155                    }
156                })
157                .catch(error => {
158                    console.error('Ошибка при загрузке начальных данных:', error);
159                });
160        }
161
162        // Функция загрузки стран
163        function loadCountriesData(cityId = null) {
164            let url = '/local/templates/travelsoft/components/bitrix/news.list/filter_tour25/proxy.php?flightTo=true&' + Math.random();
165
166            if (cityId) {
167                url += `&cityFrom=${cityId}`;
168            }
169
170            return fetch(url)
171                .then(response => response.json())
172                .then(data => {
173                    countriesData = data;
174                    return data;
175                })
176                .catch(error => {
177                    console.error('Ошибка при загрузке данных стран:', error);
178                    return null;
179                });
180        }
181
182        function loadCountriesFlags() {
183
184            BX.ajax({
185                url: "/local/templates/travelsoft/components/bitrix/news.list/filter_tour25/ajax_flags.php",
186                data: {
187                    sessid: BX.bitrix_sessid()
188                },
189                method: 'POST',
190                dataType: 'json',
191                onsuccess: function (data) {
192                    countriesFlags = data;
193                    console.log(data);
194
195                    return data;
196                },
197                onfailure: function (error) {
198                    console.log("Status: " + error);
199                }
200            });
201
202        }
203
204        // Функция для открытия модального окна городов
205        function openCityModal() {
206            const modalContainer = document.getElementById('cityModalContainer');
207            modalContainer.innerHTML = '<div class="text-center py-4">Загрузка городов...</div>';
208
209            if (!filterData || !filterData.cityFrom) {
210                // loadInitialData();
211                loadCountriesData(selectedCityId || null);
212            }
213
214            let html = `
215        <div class="modal fade modalfilter25" id="cityModal" tabindex="-1" role="dialog" aria-labelledby="cityModalLabel" aria-hidden="true">
216        <div class="modal-dialog" role="document">
217        <div class="modal-content">
218        <div class="modal-header">
219    <h5 class="modal-title" id="cityModalLabel">Вылет</h5>
220    <button type="button" class="close" data-dismiss="modal" aria-label="Close">
221        
222    </button>
223</div>
224<div class="modal-body">
225    <div class="list-group">`;
226
227            if (filterData && filterData.cityFrom) {
228                filterData.cityFrom.forEach(city => {
229                    html += `
230        <a href="#" class="city-item" data-city-id="${city.id}">
231            ${city.name}
232        </a>`;
233                });
234            }
235
236            html += `
237    </div>
238</div>
239<div class="modal-footer">
240    <button type="button" class="btn btn-secondary" data-dismiss="modal">Закрыть</button>
241    <button type="button" class="btn btn-primary" id="confirm-city">Применить</button>
242</div>
243</div>
244</div>
245</div>`;
246
247            modalContainer.innerHTML = html;
248
249            $('#cityModal').modal('show');
250
251            document.querySelectorAll('#cityModal .city-item').forEach(item => {
252                item.addEventListener('click', function (e) {
253                    e.preventDefault();
254                    document.querySelectorAll('#cityModal .city-item').forEach(i => i.classList.remove('active'));
255                    this.classList.add('active');
256                });
257            });
258
259            document.getElementById('confirm-city').addEventListener('click', function () {
260                const selected = document.querySelector('#cityModal .city-item.active');
261                if (selected) {
262                    selectCity({
263                        id: selected.dataset.cityId,
264                        name: selected.textContent.trim()
265                    });
266                    $('#cityModal').modal('hide');
267                }
268            });
269        }
270
271        function openCountryModal() {
272            const modalContainer = document.getElementById('countryModalContainer');
273            modalContainer.innerHTML = '<div class="text-center py-4">Загрузка стран...</div>';
274            // Проверяем, есть ли актуальные данные
275            if (!countriesData || !countriesData.countryTo) {
276                loadCountriesData(selectedCityId)
277                    .then(data => {
278                        if (data && data.countryTo) {
279                            renderCountryModal(data.countryTo);
280                        } else {
281                            modalContainer.innerHTML = '<div class="text-center py-4">Нет доступных стран</div>';
282                        }
283                    });
284            } else {
285                renderCountryModal(countriesData.countryTo);
286            }
287        }
288
289        // Функция отрисовки модального окна стран
290        function renderCountryModal(countries) {
291            // loadCountriesFlags();
292
293            BX.ajax({
294                url: "/local/templates/travelsoft/components/bitrix/news.list/filter_tour25/ajax_flags.php",
295                data: {
296                    sessid: BX.bitrix_sessid()
297                },
298                method: 'POST',
299                dataType: 'json',
300                onsuccess: function (data) {
301                    countriesFlags = data;
302                    console.log(countriesFlags);
303
304
305
306
307                    const modalContainer = document.getElementById('countryModalContainer');
308                    const isMobile = window.innerWidth <= 768;
309
310                    let html = `
311    <div class="modal fade modalfilter25" id="countryModal" tabindex="-1" role="dialog" aria-labelledby="countryModalLabel" aria-hidden="true">
312        <div class="modal-dialog modal-lg" role="document">
313            <div class="modal-content">
314                <div class="modal-header">
315                    <h5 class="modal-title" id="countryModalLabel">Направление</h5>
316                    <button type="button" class="close" data-dismiss="modal" aria-label="Close">
317                        <span aria-hidden="true">&times;</span>
318                    </button>
319                </div>
320                ${isMobile ? '<button type="button" class="back-to-countries d-none"><i class="fas fa-arrow-left"></i> <span class="country-name"></span></button>' : ''}
321                <div class="modal-body">
322                    <div class="row ${isMobile ? 'mobile-view' : ''}">
323                        <div class="col-md-6 border-right ${isMobile ? 'mobile-panel mobile-panel-countries' : ''}">
324                            <h6 class="text-left mb-3">Все страны</h6>
325                            <div class="list-group country-list" id="countryList" style="max-height: 400px; overflow-y: auto;"></div>
326                        </div>
327                        <div class="col-md-6 ${isMobile ? 'mobile-panel mobile-panel-tours d-none' : ''}">
328                            <h6 class="text-left mb-3">Доступные туры</h6>
329                            <div class="tour-list" id="tourList" style="max-height: 400px; overflow-y: auto;">
330                                <div class="text-muted text-center py-5">Выберите страну для просмотра туров</div>
331                            </div>
332                        </div>
333                    </div>
334                </div>
335                <div class="modal-footer">
336                    <button type="button" class="btn btn-secondary" data-dismiss="modal">Закрыть</button>
337                    <button type="button" class="btn btn-primary" id="confirm-country-tour">Применить</button>
338                </div>
339            </div>
340        </div>
341    </div>`;
342
343                    modalContainer.innerHTML = html;
344
345                    // Заполняем список стран
346                    const countryList = document.getElementById('countryList');
347                    countryList.innerHTML = '';
348
349                    if (countries && countries.length > 0) {
350                        countries.forEach(country => {
351                            const countryItem = document.createElement('a');
352                            countryItem.href = '#';
353                            countryItem.className = 'country-item';
354                            countryItem.dataset.countryId = country.id;
355
356                            countryItem.innerHTML = `
357                <div class="d-flex justify-content-between align-items-center">
358                    <span style="display: flex; gap: 5px; align-items: center;"><i class="fi fi-${countriesFlags['results'][country.name].toLowerCase()}"></i>${country.name}</span>
359                </div>
360            `;
361                            countryList.appendChild(countryItem);
362                        });
363
364                        // Добавляем обработчики событий
365                        document.querySelectorAll('.country-item').forEach(item => {
366                            item.addEventListener('click', function (e) {
367                                e.preventDefault();
368                                document.querySelectorAll('.country-item').forEach(i => i.classList.remove('active'));
369                                this.classList.add('active');
370
371                                if (isMobile) {
372                                    document.querySelector('.mobile-panel-countries').classList.add('d-none');
373                                    document.querySelector('.mobile-panel-tours').classList.remove('d-none');
374                                    document.querySelector('.back-to-countries').classList.remove('d-none');
375                                    document.querySelector('.back-to-countries .country-name').textContent = this.textContent.trim();
376                                }
377
378                                loadToursForCountry(this.dataset.countryId);
379                            });
380                        });
381                    } else {
382                        countryList.innerHTML = '<div class="text-muted text-center py-5">Нет доступных стран</div>';
383                    }
384
385                    $('#countryModal').modal('show');
386
387                    // Обработчик кнопки подтверждения
388                    document.getElementById('confirm-country-tour').addEventListener('click', function () {
389                        const selectedTourItem = document.querySelector('.tour-item.active');
390                        const selectedCountryItem = document.querySelector('.country-item.active');
391
392                        if (selectedCountryItem && selectedTourItem) {
393                            selectCountryAndTour({
394                                countryId: selectedCountryItem.dataset.countryId,
395                                countryName: selectedCountryItem.textContent.trim(),
396                                tourId: selectedTourItem.dataset.tourId,
397                                tourName: selectedTourItem.dataset.tourName,
398                                tourDesc: selectedTourItem.dataset.tourDesc || ''
399                            });
400                            $('#countryModal').modal('hide');
401                        } else {
402                            alert('Пожалуйста, выберите страну и тур');
403                        }
404                    });
405
406
407                },
408                onfailure: function (error) {
409                    console.log("Status: " + error);
410                }
411            });
412
413
414        }
415
416        // Функция загрузки туров для выбранной страны
417        function loadToursForCountry(countryId) {
418            const tourList = document.getElementById('tourList');
419            tourList.innerHTML = '<div class="text-center py-4">Загрузка туров...</div>';
420
421            BX.ajax({
422                url: ajaxPath,
423                data: {
424                    action: 'getTours',
425                    countryId: countryId,
426                    cityId: selectedCityId,
427                    sessid: BX.bitrix_sessid()
428                },
429                method: 'POST',
430                dataType: 'html',
431                onsuccess: function (html) {
432                    const parser = new DOMParser();
433                    const doc = parser.parseFromString(html, 'text/html');
434                    const tourCards = doc.querySelectorAll('.tour-card');
435
436                    if (tourCards.length > 0) {
437                        tourList.innerHTML = '';
438
439                        tourCards.forEach(card => {
440                            const tourItem = document.createElement('div');
441                            tourItem.className = 'tour-item select-tour';
442                            tourItem.dataset.tourId = card.dataset.tourId;
443                            tourItem.dataset.tourName = card.dataset.tourName;
444                            tourItem.dataset.tourDesc = card.dataset.tourDesc || '';
445
446                            tourItem.innerHTML = `
447
448${card.dataset.tourName}
449${card.dataset.tourDesc ? `<p class="card-text">${card.dataset.tourDesc}</p>` : ''}
450
451`;
452
453                            tourList.appendChild(tourItem);
454                        });
455
456                        document.querySelectorAll('.tour-item').forEach(item => {
457                            item.addEventListener('click', function (e) {
458                                if (!e.target.classList.contains('select-tour') &&
459                                    !e.target.closest('.select-tour')) {
460                                    return;
461                                }
462
463                                e.preventDefault();
464                                document.querySelectorAll('.tour-item').forEach(i => i.classList.remove('active'));
465                                this.classList.add('active');
466                            });
467                        });
468                    } else {
469                        tourList.innerHTML = '<div class="text-muted text-center py-5">Нет доступных туров для выбранной страны</div>';
470                    }
471                },
472                onfailure: function () {
473                    tourList.innerHTML = '<div class="text-center py-4">Ошибка загрузки туров</div>';
474                }
475            });
476        }
477
478        // Функция для открытия модального окна дат и ночей
479        function openDateModal() {
480            function getFirstAvailableMonth(datesArray) {
481                if (!datesArray || !datesArray.length) return null;
482                // Преобразуем строки дат в объекты Date
483                const months = datesArray.map(dateStr => {
484                    const d = new Date(dateStr);
485                    return { year: d.getFullYear(), month: d.getMonth() };
486                });
487                // Найти первый уникальный месяц
488                return months[0];
489            }
490
491            const modalContainer = document.getElementById('dateModalContainer');
492            modalContainer.innerHTML = `
493<div class="modal fade modalfilter25" id="dateModal" tabindex="-1" role="dialog" aria-hidden="true">
494    <div class="modal-dialog modal-lg">
495        <div class="modal-content">
496            <div class="modal-header">
497                <h5 class="modal-title">Выберите дату и продолжительность</h5>
498                <button type="button" class="close" data-dismiss="modal"></button>
499            </div>
500            <div class="modal-body">
501                <div class="row">
502                    <div class="col-md-8 border-right">
503                        <h6 class="text-center mb-3"><img src="${config.templateFolder}/calendar-dates.svg" width="16" height="16" loading="lazy" decoding="async" alt="" aria-hidden="true"/> Дата вылета</h6>
504                        <div class="dual-calendar">
505                            <div class="calendar-nav">
506                                <button type="button" class="prev-year">&lt;&lt;</button>
507                                <button type="button" class="prev-month"></button>
508                                <span class="current-month"></span>
509                                <button type="button" class="next-month"></button>
510                                <button type="button" class="next-year">&gt;&gt;</button>
511                            </div>
512                            <div class="months-container"></div>
513                        </div>
514                    </div>
515                    <div class="col-md-4">
516                        <h6 class="text-center mb-3"><img src="${config.templateFolder}/moon.svg" width="16" height="16" loading="lazy" decoding="async" alt="" aria-hidden="true"/> Количество ночей</h6>
517                        <div class="nights-grid" id="nightsGrid"></div>
518                    </div>
519                </div>
520            </div>
521            <div class="modal-footer">
522                <button type="button" class="btn btn-secondary" data-dismiss="modal">Закрыть</button>
523                <button type="button" class="btn btn-primary" id="confirm-date-duration">Применить</button>
524            </div>
525        </div>
526    </div>
527</div>`;
528
529            let selectedDate = null;
530            let selectedNights = null;
531
532            function loadAvailableNights(date) {
533                const dateStr = moment(date).format('YYYY-MM-DD');
534                const nightsGrid = document.getElementById('nightsGrid');
535                nightsGrid.classList.add('gridFlex');
536                nightsGrid.innerHTML = '<div style="text-align: center; width: 100% display: flex; justify-content: center;" class="text-center py-4">Загрузка доступных ночей...</div>';
537
538                fetch(`/local/templates/travelsoft/components/bitrix/news.list/filter_tour25/proxy.php?cityFrom=${selectedCityId}&countryTo=${selectedCountryId}&tourTo=${selectedTourId}&dateFrom=${dateStr}&dateTo=${dateStr}&flightTo=true`)
539                    .then(response => response.json())
540                    .then(data => {
541                        if (data && data.nightTo && data.nightTo.length > 0) {
542                            nightsGrid.classList.remove('gridFlex');
543                            renderNightsGrid(data.nightTo);
544                        } else {
545                            nightsGrid.innerHTML = '<div class="text-muted text-center py-5">Нет доступных туров на выбранную дату</div>';
546                        }
547                    })
548                    .catch(error => {
549                        console.error('Ошибка при загрузке ночей:', error);
550                        nightsGrid.innerHTML = '<div class="text-center py-4">Ошибка загрузки данных</div>';
551                    });
552            }
553
554            function handleDateClick(dayCell, currentDate) {
555                document.querySelectorAll('.day.selected').forEach(d => d.classList.remove('selected'));
556                dayCell.classList.add('selected');
557                selectedDate = currentDate;
558                selectedNights = null;
559                document.getElementById('confirm-date-duration').disabled = true;
560                loadAvailableNights(currentDate);
561            }
562
563            function updateConfirmButton() {
564                const confirmBtn = document.getElementById('confirm-date-duration');
565                confirmBtn.disabled = !(selectedDate && selectedNights);
566            }
567
568            function renderNightsGrid(availableNights = []) {
569                const nightsGrid = document.getElementById('nightsGrid');
570                nightsGrid.innerHTML = '';
571                for (let i = 1; i <= 30; i++) {
572                    const nightItem = document.createElement('div');
573                    nightItem.className = `night-item ${availableNights.includes(i) ? 'available' : 'disabled'}`;
574                    nightItem.dataset.nights = i;
575                    nightItem.textContent = i;
576                    if (availableNights.includes(i)) {
577                        nightItem.addEventListener('click', function () {
578                            document.querySelectorAll('.night-item.active').forEach(item => item.classList.remove('active'));
579                            this.classList.add('active');
580                            selectedNights = i;
581                            updateConfirmButton();
582                        });
583                    }
584                    nightsGrid.appendChild(nightItem);
585                }
586            }
587
588            function initDualCalendar() {
589                let currentMonth, currentYear;
590                if (filterData && filterData.dateTo && filterData.dateTo.length > 0) {
591                    console.log(filterData);
592                    console.log("!!!!!!!!!!!!!!!!!!!!!!");
593
594
595                    const firstMonth = getFirstAvailableMonth(filterData.dateTo);
596                    if (firstMonth) {
597                        currentMonth = firstMonth.month;
598                        currentYear = firstMonth.year;
599                    } else {
600                        const today = new Date();
601                        currentMonth = today.getMonth();
602                        currentYear = today.getFullYear();
603                    }
604                } else {
605                    const today = new Date();
606                    currentMonth = today.getMonth();
607                    currentYear = today.getFullYear();
608                }
609
610                renderTwoMonths(currentYear, currentMonth);
611
612                document.querySelector('.prev-month').addEventListener('click', () => {
613                    currentMonth--;
614                    if (currentMonth < 0) {
615                        currentMonth = 11;
616                        currentYear--;
617                    }
618                    renderTwoMonths(currentYear, currentMonth);
619                });
620
621                document.querySelector('.next-month').addEventListener('click', () => {
622                    currentMonth++;
623                    if (currentMonth > 11) {
624                        currentMonth = 0;
625                        currentYear++;
626                    }
627                    renderTwoMonths(currentYear, currentMonth);
628                });
629
630                document.querySelector('.prev-year').addEventListener('click', () => {
631                    currentYear--;
632                    renderTwoMonths(currentYear, currentMonth);
633                });
634
635                document.querySelector('.next-year').addEventListener('click', () => {
636                    currentYear++;
637                    renderTwoMonths(currentYear, currentMonth);
638                });
639            }
640
641            function renderTwoMonths(year, month) {
642                const monthsContainer = document.querySelector('.months-container');
643                monthsContainer.innerHTML = '';
644                renderMonth(year, month, monthsContainer);
645                let nextMonth = month + 1;
646                let nextYear = year;
647                if (nextMonth > 11) {
648                    nextMonth = 0;
649                    nextYear++;
650                }
651                renderMonth(nextYear, nextMonth, monthsContainer);
652                const monthNames = ['Январь', 'Февраль', 'Март', 'Апрель', 'Май', 'Июнь',
653                    'Июль', 'Август', 'Сентябрь', 'Октябрь', 'Ноябрь', 'Декабрь'];
654                document.querySelector('.current-month').textContent =
655                    `${monthNames[month]} ${year} / ${monthNames[nextMonth]} ${nextYear}`;
656            }
657
658            function renderMonth(year, month, container) {
659                const monthDiv = document.createElement('div');
660                monthDiv.className = 'month-calendar';
661                const monthNames = ['Январь', 'Февраль', 'Март', 'Апрель', 'Май', 'Июнь',
662                    'Июль', 'Август', 'Сентябрь', 'Октябрь', 'Ноябрь', 'Декабрь'];
663                const monthTitle = document.createElement('div');
664                monthTitle.className = 'month-title';
665                monthTitle.textContent = `${monthNames[month]} ${year}`;
666                monthDiv.appendChild(monthTitle);
667
668                const weekdays = ['Пн', 'Вт', 'Ср', 'Чт', 'Пт', 'Сб', 'Вс'];
669                const weekdaysRow = document.createElement('div');
670                weekdaysRow.className = 'weekdays';
671                weekdays.forEach(day => {
672                    const dayCell = document.createElement('div');
673                    dayCell.textContent = day;
674                    weekdaysRow.appendChild(dayCell);
675                });
676                monthDiv.appendChild(weekdaysRow);
677
678                const firstDay = (new Date(year, month, 1).getDay() + 6) % 7; // Пн=0
679                const daysInMonth = new Date(year, month + 1, 0).getDate();
680                const today = new Date();
681
682                let date = 1;
683                for (let i = 0; i < 6; i++) {
684                    if (date > daysInMonth) break;
685                    const weekRow = document.createElement('div');
686                    weekRow.className = 'week';
687                    for (let j = 0; j < 7; j++) {
688                        if (i === 0 && j < firstDay) {
689                            const emptyCell = document.createElement('div');
690                            emptyCell.className = 'day empty';
691                            weekRow.appendChild(emptyCell);
692                        } else if (date > daysInMonth) {
693                            const emptyCell = document.createElement('div');
694                            emptyCell.className = 'day empty';
695                            weekRow.appendChild(emptyCell);
696                        } else {
697                            const dayCell = document.createElement('div');
698                            dayCell.className = 'day';
699                            dayCell.textContent = date;
700                            const currentDate = new Date(year, month, date);
701                            const dateStr = moment(currentDate).format('YYYY-MM-DD');
702                            if (filterData.dateTo && filterData.dateTo.includes(dateStr) && currentDate >= today) {
703                                dayCell.classList.add('available');
704                                dayCell.addEventListener('click', function () {
705                                    // Снимаем выделение со всех дней
706                                    document.querySelectorAll('.day.selected').forEach(d => d.classList.remove('selected'));
707                                    // Выделяем выбранный день
708                                    this.classList.add('selected');
709                                    // Сохраняем выбранную дату
710                                    selectedDate = currentDate;
711                                    selectedNights = null;
712                                    updateConfirmButton();
713                                    // Подгружаем ночи для выбранной даты
714                                    loadAvailableNights(currentDate);
715                                });
716                                if (date === today.getDate() && month 
716=== today.getMonth() && year === today.getFullYear()) {
717                                    dayCell.classList.add('today');
718                                }
719                            } else {
720                                dayCell.classList.add('disabled');
721                            }
722                            weekRow.appendChild(dayCell);
723                            date++;
724                        }
725                    }
726                    monthDiv.appendChild(weekRow);
727                }
728                container.appendChild(monthDiv);
729            }
730
731            // Инициализация календаря с учётом доступных дат
732            initDualCalendar();
733
734            // Обработчик кнопки подтверждения
735            document.getElementById('confirm-date-duration').addEventListener('click', function () {
736                if (selectedDate && selectedNights) {
737                    selectDateAndDuration({
738                        date: selectedDate,
739                        duration: selectedNights
740                    });
741                    $('#dateModal').modal('hide');
742                }
743            });
744
745            $('#dateModal').modal('show');
746            updateConfirmButton();
747        }
748
749        function openPersonsModal() {
750            const modalContainer = document.getElementById('personsModalContainer');
751
752            let html = `
753                <div class="modal fade modalfilter25" id="personsModal" tabindex="-1" role="dialog" aria-labelledby="personsModalLabel" aria-hidden="true">
754                    <div class="modal-dialog" role="document">
755                        <div class="modal-content">
756                            <div class="modal-header">
757                                <h5 class="modal-title" id="personsModalLabel">Количество человек</h5>
758                                <button type="button" class="close" data-dismiss="modal" aria-label="Close">
759                                    
760                                </button>
761                            </div>
762                            <div class="modal-body">
763                                <!-- Взрослые -->
764                                <div class="d-flex justify-content-between align-items-center mb-4">
765                                    <div>
766                                        <h6>Взрослые (12+)</h6>
767                                    </div>
768                                    <div class="d-flex align-items-center">
769                                        <button type="button" class="btn btn-outline-secondary btn-sm adult-decrement" ${adultCount <= 1 ? 'disabled' : ''}>
770                                            <i class="fas fa-minus"></i>
771                                        </button>
772                                        <span class="mx-3 adult-count">${adultCount}</span>
773                                        <button type="button" class="btn btn-outline-secondary btn-sm adult-increment" ${adultCount >= 4 ? 'disabled' : ''}>
774                                            <i class="fas fa-plus"></i>
775                                        </button>
776                                    </div>
777                                </div>
778                                
779                                <!-- Дети -->
780                                <div class="d-flex justify-content-between align-items-center mb-4">
781                                    <div>
782                                        <h6>Дети (До 12 лет)</h6>
783                                    </div>
784                                    <div class="d-flex align-items-center">
785                                        <button type="button" class="btn btn-outline-secondary btn-sm child-decrement" ${childCount <= 0 ? 'disabled' : ''}>
786                                            <i class="fas fa-minus"></i>
787                                        </button>
788                                        <span class="mx-3 child-count">${childCount}</span>
789                                        <button type="button" class="btn btn-outline-secondary btn-sm child-increment" ${childCount >= 3 ? 'disabled' : ''}>
790                                            <i class="fas fa-plus"></i>
791                                        </button>
792                                    </div>
793                                </div>
794                                
795                                <div class="children-ages-txt">*Пожалуйста, укажите возраст детей на дату возвращения из поездки</div>
796                                <div id="children-ages-container" class="mt-3"></div>
797                            </div>
798                            <div class="modal-footer">
799                                <button type="button" class="btn btn-secondary" data-dismiss="modal">Закрыть</button>
800                                <button type="button" class="btn btn-primary" id="confirm-persons">Применить</button>
801                            </div>
802                        </div>
803                    </div>
804                </div>`;
805
806            modalContainer.innerHTML = html;
807
808            $('#personsModal').modal('show');
809            updatePersonsModal();
810
811            // Обработчики событий
812            document.querySelector('.adult-increment').addEventListener('click', function () {
813                if (adultCount < 4) {
814                    adultCount++;
815                    updatePersonsModal();
816                }
817            });
818
819            document.querySelector('.adult-decrement').addEventListener('click', function () {
820                if (adultCount > 1) {
821                    adultCount--;
822                    updatePersonsModal();
823                }
824            });
825
826            document.querySelector('.child-increment').addEventListener('click', function () {
827                if (childCount < 3) {
828                    childCount++;
829                    // Новый ребенок получает возраст по умолчанию (6 лет)
830                    childAges[childCount - 1] = 6;
831                    updatePersonsModal();
832                }
833            });
834
835            document.querySelector('.child-decrement').addEventListener('click', function () {
836                if (childCount > 0) {
837                    childCount--;
838                    updatePersonsModal();
839                }
840            });
841
842            document.getElementById('confirm-persons').addEventListener('click', function () {
843                // Возраста уже сохраняются при изменении select'ов
844                updateTotalPersons();
845                $('#personsModal').modal('hide');
846            });
847
848
849            // Уничтожаем Select2 при скрытии модального окна
850            $('#personsModal').on('hidden.bs.modal', function () {
851                select2Instances.forEach(select2 => {
852                    try {
853                        select2.destroy();
854                    } catch (e) {
855                        // Игнорируем ошибки
856                    }
857                });
858                select2Instances = [];
859            });
860
861        }
862
863        // Обновление модального окна количества человек
864        let select2Instances = [];
865        let skeletonTimeout;
866
867        function updatePersonsModal() {
868            const adultCountElement = document.querySelector('.adult-count');
869            if (adultCountElement) adultCountElement.textContent = adultCount;
870
871            const childCountElement = document.querySelector('.child-count');
872            if (childCountElement) childCountElement.textContent = childCount;
873
874            document.querySelector('.adult-increment').disabled = adultCount >= 4;
875            document.querySelector('.adult-decrement').disabled = adultCount <= 1;
876            document.querySelector('.child-increment').disabled = childCount >= 3;
877            document.querySelector('.child-decrement').disabled = childCount <= 0;
878
879            const container = document.getElementById('children-ages-container');
880            if (container) {
881                // Очищаем предыдущий таймаут скелетона
882                if (skeletonTimeout) {
883                    clearTimeout(skeletonTimeout);
884                }
885
886                // Показываем простой скелетон
887                container.innerHTML = `
888            <div class="skeleton-loader">
889                ${childCount > 0 ? Array(childCount).fill(`
890                    <div class="skeleton-item">
891                        <div class="skeleton-label"></div>
892                        <div class="skeleton-field"></div>
893                    </div>
894                `).join('') : ''}
895            </div>
896        `;
897
898                skeletonTimeout = setTimeout(() => {
899                    // Уничтожаем все старые Select2
900                    select2Instances.forEach(select2 => {
901                        try {
902                            select2.destroy();
903                        } catch (e) {
904                            // ...
905                        }
906                    });
907                    select2Instances = [];
908
909                    // Очищаем контейнер
910                    container.innerHTML = '';
911
912                    for (let i = 0; i < childCount; i++) {
913                        const wrapper = document.createElement('div');
914                        wrapper.className = 'mb-2 fade-in';
915
916                        const label = document.createElement('label');
917                        label.textContent = `${i + 1}-й ребенок`;
918                        label.className = 'form-label d-block';
919
920                        const ageSelect = document.createElement('select');
921                        ageSelect.className = 'form-control child-age hidden-select';
922                        ageSelect.dataset.index = i;
923
924                        // Если childAges[i] не определен, используем значение по умолчанию
925                        const currentAge = childAges[i] || 6;
926
927                        // Заполнение вариантов возраста
928                        function pluralizeYears(n) {
929                            if (n % 10 === 1 && n % 100 !== 11) {
930                                return 'год';
931                            } else if ([2, 3, 4].includes(n % 10) && !(n % 100 >= 12 && n % 100 <= 14)) {
932                                return 'года';
933                            } else {
934                                return 'лет';
935                            }
936                        }
937
938                        for (let age = 1; age <= 12; age++) {
939                            const option = document.createElement('option');
940                            option.value = age;
941                            option.textContent = `${age} ${pluralizeYears(age)}`;
942                            option.selected = (currentAge === age);
943                            ageSelect.appendChild(option);
944                        }
945
946                        wrapper.appendChild(label);
947                        wrapper.appendChild(ageSelect);
948                        container.appendChild(wrapper);
949                    }
950
951                    // Инициализация Select2 только если элементы есть
952                    if (childCount > 0) {
953                        initializeSelect2();
954                    }
955                }, 200);
956            }
957        }
958
959        function initializeSelect2() {
960            // Уничтожаем все предыдущие Select2
961            $('.child-age').each(function () {
962                const $select = $(this);
963                if ($select.data('select2')) {
964                    try {
965                        $select.select2('destroy');
966                    } catch (e) {
967                        // ...
968                    }
969                }
970            });
971
972            setTimeout(() => {
973                $('.child-age').each(function () {
974                    const $select = $(this);
975                    const $wrapper = $select.closest('.mb-2');
976
977                    if (!$select.data('select2')) {
978                        $select.removeClass('hidden-select');
979
980                        const select2Instance = $select.select2({
981                            minimumResultsForSearch: Infinity
982                        }).on('select2:select', function (e) {
983                            const index = $(this).data('index');
984                            const value = parseInt(e.params.data.id);
985                            childAges[index] = value;
986                        });
987
988                        select2Instances.push(select2Instance);
989                    }
990                });
991            }, 50);
992        }
993        // Функции выбора значений
994        function selectCity(city) {
995            selectedCityId = city.id;
996
997            if (!city.name) {
998                citySelectBtn.textContent = "Выберите город";
999            } else {
1000                citySelectBtn.textContent = city.name;
1001            }
1002            document.getElementById('city-id').value = city.id;
1003
1004            // Блокируем кнопку выбора страны пока грузятся данные
1005            countrySelectBtn.disabled = true;
1006            countrySelectBtn.textContent = 'Загрузка стран...';
1007
1008            // Загружаем обновленные данные для выбранного города
1009            loadCountriesData(city.id)
1010                .then(data => {
1011                    if (data && data.countryTo && data.countryTo.length > 0) {
1012                        countrySelectBtn.disabled = false;
1013                        countrySelectBtn.textContent = 'Выберите направление';
1014                        filterData = data; // Обновляем общие данные фильтра
1015                    } else {
1016                        countrySelectBtn.textContent = 'Нет доступных стран';
1017                        countrySelectBtn.disabled = true;
1018                    }
1019                })
1020                .catch(error => {
1021                    countrySelectBtn.textContent = 'Ошибка загрузки';
1022                    countrySelectBtn.disabled = true;
1023                });
1024
1025            // Сбрасываем остальные выборы
1026            selectedCountryId = null;
1027            selectedTourId = null;
1028            selectedDate = null;
1029            selectedDuration = null;
1030            document.getElementById('country-id').value = '';
1031            document.getElementById('tour-date-value').value = '';
1032            document.getElementById('duration-value').value = '';
1033            document.getElementById('tour-id').value = '';
1034
1035            dateSelectBtn.disabled = true;
1036            dateSelectBtn.textContent = 'Сначала выберите направление';
1037
1038            generateTourLink();
1039        }
1040
1041        function selectCountryAndTour(data) {
1042            selectedCountryId = data.countryId;
1043            selectedTourId = data.tourId;
1044            selectedTour = {
1045                id: data.tourId,
1046                name: data.tourName,
1047                description: data.tourDesc || ''
1048            };
1049
1050            countrySelectBtn.textContent = `${data.countryName} - ${data.tourName}`;
1051            document.getElementById('country-id').value = data.countryId;
1052            document.getElementById('tour-id').value = data.tourId;
1053
1054
1055
1056            selectedDate = null;
1057            selectedDuration = null;
1058            document.getElementById('tour-date-value').value = '';
1059            document.getElementById('duration-value').value = '';
1060
1061            if (selectedCityId && selectedCountryId) {
1062                loadFilterData(selectedCityId, selectedCountryId, selectedTourId);
1063            }
1064
1065            // dateSelectBtn.disabled = false;
1066            // dateSelectBtn.textContent = 'Выберите дату';
1067
1068            dateSelectBtn.textContent = 'Загрузка...';
1069            setTimeout(() => {
1070                dateSelectBtn.disabled = false;
1071                dateSelectBtn.textContent = 'Выберите дату';
1072            }, 1000);
1073
1074
1075            // temporaryDisableButton();
1076            generateTourLink();
1077        }
1078
1079        function temporaryDisableButton() {
1080            // 2. Сохраняем старый текст, чтобы вернуть его потом
1081            const originalText = countrySelectBtn.innerText;
1082
1083            // 3. Делаем disabled и меняем текст
1084            dateSelectBtn.disabled = true;
1085            dateSelectBtn.innerText = 'Загрузка...';
1086
1087            // 4. Через 1 секунду (1000 мс) возвращаем все назад
1088            setTimeout(() => {
1089                dateSelectBtn.disabled = false;
1090                dateSelectBtn.innerText = 'Выберите дату';
1091                // Если нужно вернуть именно старый текст, а не фиксированный:
1092                // countrySelectBtn.innerText = originalText;
1093            }, 1000);
1094        }
1095
1096        function selectDateAndDuration(data) {
1097            selectedDate = moment(data.date).format('YYYY-MM-DD');
1098            selectedDuration = data.duration;
1099
1100            dateSelectBtn.textContent = `${moment(data.date).format('DD.MM.YYYY')} (${data.duration} ${pluralize(data.duration, ['ночь', 'ночи', 'ночей'])})`;
1101            document.getElementById('tour-date-value').value = selectedDate;
1102            document.getElementById('duration-value').value = selectedDuration;
1103
1104            // Устанавливаем dateTo равным dateFrom
1105            //document.getElementById('date-to-value').value = selectedDate;
1106
1107            generateTourLink();
1108        }
1109
1110        function updateTotalPersons() {
1111            let text = `${adultCount} ${pluralize(adultCount, ['взрослый', 'взрослых', 'взрослых'])}`;
1112            if (childCount > 0) {
1113                text += `, ${childCount} ${pluralize(childCount, ['ребенок', 'ребенка', 'детей'])}`;
1114            }
1115            personsSelectBtn.textContent = text;
1116            generateTourLink();
1117        }
1118
1119        // Функция загрузки данных фильтра
1120        function loadFilterData(cityId, countryId = null, tourId = null) {
1121            let url = `/local/templates/travelsoft/components/bitrix/news.list/filter_tour25/proxy.php?cityFrom=${cityId}&flightTo=true&rand=` + Math.random();
1122            console.log('LOAD FILTER DATA');
1123            console.log('LOAD FILTER DATA');
1124            if (countryId) {
1125                url += `&countryTo=${countryId}`;
1126            }
1127
1128            if (tourId) {
1129                url += `&tourTo=${tourId}`;
1130            }
1131
1132            fetch(url)
1133                .then(response => response.json())
1134                .then(data => {
1135                    filterData = data;
1136                })
1137                .catch(error => console.error('Ошибка:', error));
1138        }
1139
1140        // Генерация ссылки на подбор тура
1141        function generateTourLink() {
1142            if (!selectedCityId || !selectedCountryId || !selectedTourId || !selectedDate || !selectedDuration) {
1143                findLink.href = '';
1144                findLink.style.pointerEvents = 'none';
1145                findLink.style.opacity = '0.5';
1146                return;
1147            }
1148
1149            const params = {
1150                transportType: 'flight',
1151                withHotel: 'true',
1152                cityFrom: selectedCityId,
1153                countryTo: selectedCountryId,
1154                'tourTo[0]': selectedTourId,
1155                promoProgram: 'true',
1156                dateFrom: selectedDate,
1157                dateTo: moment(selectedDate).add(parseInt(selectedDuration), 'days').format('YYYY-MM-DD'),
1158                'nightTo[0]': selectedDuration,
1159                adultCount: adultCount,
1160                childCount: childCount,
1161                pageIndex: '0'
1162            };
1163
1164            // Добавляем возраст детей
1165            document.querySelectorAll('.child-age').forEach(select => {
1166                const index = select.dataset.index;
1167                params[`childAge[${index}]`] = select.value;
1168            });
1169
1170
1171            // const baseUrl = 'https://booking.capitaltour.ru/Tour';
1172            const baseUrl = 'https://online.capitaltour.ru/Tour';
1173            const queryString = Object.keys(params)
1174                .map(key => `${encodeURIComponent(key)}=${encodeURIComponent(params[key])}`)
1175                .join('&');
1176
1177            findLink.href = `${baseUrl}?${queryString}`;
1178            findLink.style.pointerEvents = 'auto';
1179            findLink.style.opacity = '1';
1180        }
1181
1182        // Инициализация обработчиков событий
1183        function initEventHandlers() {
1184            citySelectBtn.addEventListener('click', function (e) {
1185                e.preventDefault();
1186                openCityModal();
1187            });
1188
1189            countrySelectBtn.addEventListener('click', function (e) {
1190                e.preventDefault();
1191                openCountryModal();
1192            });
1193
1194            dateSelectBtn.addEventListener('click', function (e) {
1195                e.preventDefault();
1196                openDateModal();
1197            });
1198
1199            personsSelectBtn.addEventListener('click', function (e) {
1200                e.preventDefault();
1201                openPersonsModal();
1202            });
1203        }
1204
1205        // Вспомогательные функции
1206        function pluralize(n, words) {
1207            return n % 100 > 10 && n % 100 < 15 ? words[2] : [2, 3, 4].includes(n % 10) ? words[1] : words[0];
1208        }
1209
1210
1211        function setVh() {
1212            document.documentElement.style.setProperty('--vh', `${window.innerHeight * 0.01}px`);
1213        }
1214
1215        setVh();
1216        window.addEventListener('resize', setVh);
1217
1218
1219        // }
1220
1221        setTimeout(function () {
1222            const currentCityId = Number(config.currentCityFromId || window.currentCityFromId || 0);
1223            const cities = window.cities || {};
1224            const fallbackName = config.currentCityFromName || '';
1225            selectCity({
1226                id: currentCityId,
1227                name: cities[currentCityId] ? cities[currentCityId].NAME : fallbackName
1228            });
1229        }, 400);
1230    }
1231});
1232/* End */
1233;
1234; /* Start:"a:4:{s:4:"full";s:86:"/local/components/travelsoft/favorites.add/templates/.default/script.js?17455787132069";s:6:"source";s:71:"/local/components/travelsoft/favorites.add/templates/.default/script.js";s:3:"min";s:0:"";s:3:"map";s:0:"";}"*/
1235
1236BX.namespace("Travelsoft");
1237
1238if (!BX.Travelsoft.add2favorites) {
1239    BX.Travelsoft.add2favorites = function (url, object_type, object_id, store_id, hash, context) {
1240        context.disabled = true;
1241        BX.ajax.get(url, {
1242            sessid: BX.bitrix_sessid(),
1243            OBJECT_TYPE: object_type || '',
1244            OBJECT_ID: object_id || '',
1245            HASH: hash || '',
1246            ACTION: "ADD",
1247            STORE_ID: store_id || ''
1248        }, function (resp) {
1249            
1250            resp = JSON.parse(resp);
1251            context.disabled = false;
1252            if (resp.error) {
1253                alert(BX.message('TRAVELSOFT_FAVORITES_ADD_ERROR'));
1254                return;
1255            }
1256            
1257            context.classList = "favorites__button bg-star_filled";
1258            context.innerText = BX.message("TRAVELSOFT_FAVORITES_REMOVE_FAV");
1259            context.onclick = function () {
1260                BX.Travelsoft.deleteFromFavorites(url, object_type, object_id, store_id, hash, this);
1261            };
1262            
1263        });
1264    };
1265}
1266
1267if (!BX.Travelsoft.deleteFromFavorites) {
1268    BX.Travelsoft.deleteFromFavorites = function (url, object_type, object_id, store_id, hash, context) {
1269        context.disabled = true;
1270        BX.ajax.get(url, {
1271            sessid: BX.bitrix_sessid(),
1272            OBJECT_TYPE: object_type || '',
1273            OBJECT_ID: object_id || '',
1274            HASH: hash || '',
1275            ACTION: "DELETE",
1276            STORE_ID: store_id || ''
1277        }, function (resp) {
1278            
1279            resp = JSON.parse(resp);
1280            context.disabled = false;
1281            if (resp.error) {
1282                alert(BX.message('TRAVELSOFT_FAVORITES_DELETE_ERROR'));
1283                return;
1284            }
1285            
1286            context.classList = "favorites__button bg-star";
1287            context.innerText = BX.message("TRAVELSOFT_FAVORITES_ADD_TO_FAV");
1288            context.onclick = function () {
1289                BX.Travelsoft.add2favorites(url, object_type, object_id, store_id, hash, this);
1290            };
1291
1292        });
1293    };
1294}
1295/* End */
1296;
1297; /* Start:"a:4:{s:4:"full";s:121:"/local/templates/travelsoft/components/travelsoft/travelsoft.news.list/home_recommend_intourdv25/script.js?17767924361015";s:6:"source";s:106:"/local/templates/travelsoft/components/travelsoft/travelsoft.news.list/home_recommend_intourdv25/script.js";s:3:"min";s:0:"";s:3:"map";s:0:"";}"*/
1298document.addEventListener('DOMContentLoaded', function () {
1299    const root = document.querySelector('[data-ts-component="home_recommend_intourdv25"]');
1300    if (!root) return;
1301
1302    let config = {};
1303    try {
1304        config = JSON.parse(root.dataset.tsConfig || '{}');
1305    } catch (error) {
1306        config = {};
1307    }
1308
1309    if (!Array.isArray(config.ajaxData) || !config.ajaxData.length) return;
1310
1311    function loadData(searchData) {
1312        const data = searchData.shift();
1313        if (!data) return;
1314        const requestData = { searchData: data, sessid: BX.bitrix_sessid() };
1315        $.get(config.ajaxUrl, requestData, function (response) {
1316            if (response.result) {
1317                response.result.forEach((item) => {
1318                    $(`#price-${item.uniq_id}`).html(`${item.price || 'Нет предложений'} <br><small>Мест: ${item.quota}</small>`);
1319                });
1320            }
1321            loadData(searchData);
1322        }, 'json');
1323    }
1324
1325    loadData(config.ajaxData.slice());
1326});
1327
1328/* End */
1329;
1330; /* Start:"a:4:{s:4:"full";s:58:"/local/templates/travelsoft/js/lazy-load.js?17756695832887";s:6:"source";s:43:"/local/templates/travelsoft/js/lazy-load.js";s:3:"min";s:0:"";s:3:"map";s:0:"";}"*/
1331(function (window, document) {
1332    'use strict';
1333
1334    var SELECTOR = '.js-lazy-image';
1335    var OBSERVER_ROOT_MARGIN = '200px 0px';
1336
1337    function setState(img, state) {
1338        var container = img.closest('[data-lazy-container]') || img.parentElement;
1339
1340        if (!container) {
1341            return;
1342        }
1343
1344        container.classList.remove('is-loading', 'is-loaded', 'is-error');
1345        container.classList.add(state);
1346    }
1347
1348    function hasLoadedSource(img) {
1349        return !!img.getAttribute('src') && img.getAttribute('src') !== img.dataset.lazyPlaceholder;
1350    }
1351
1352    function applySource(img) {
1353        if (!img || img.dataset.lazyProcessed === '1') {
1354            return;
1355        }
1356
1357        setState(img, 'is-loading');
1358
1359        var dataSrc = img.getAttribute('data-src');
1360        var dataSrcset = img.getAttribute('data-srcset');
1361        var dataSizes = img.getAttribute('data-sizes');
1362
1363        if (dataSrc) {
1364            img.setAttribute('src', dataSrc);
1365        }
1366
1367        if (dataSrcset) {
1368            img.setAttribute('srcset', dataSrcset);
1369        }
1370
1371        if (dataSizes) {
1372            img.setAttribute('sizes', dataSizes);
1373        }
1374
1375        img.dataset.lazyProcessed = '1';
1376
1377        if (img.complete && hasLoadedSource(img)) {
1378            setState(img, 'is-loaded');
1379        }
1380    }
1381
1382    function initImage(img) {
1383        if (!img) {
1384            return;
1385        }
1386
1387        img.addEventListener('load', function () {
1388            setState(img, 'is-loaded');
1389        });
1390
1391        img.addEventListener('error', function () {
1392            setState(img, 'is-error');
1393        });
1394
1395        if (img.dataset.lazySkip === '1') {
1396            setState(img, 'is-loaded');
1397        }
1398    }
1399
1400    function init() {
1401        var images = document.querySelectorAll(SELECTOR);
1402
1403        if (!images.length) {
1404            return;
1405        }
1406
1407        images.forEach(initImage);
1408
1409        if (!('IntersectionObserver' in window)) {
1410            images.forEach(applySource);
1411            return;
1412        }
1413
1414        var observer = new IntersectionObserver(function (entries) {
1415            entries.forEach(function (entry) {
1416                if (!entry.isIntersecting) {
1417                    return;
1418                }
1419
1420                applySource(entry.target);
1421                observer.unobserve(entry.target);
1422            });
1423        }, {
1424            rootMargin: OBSERVER_ROOT_MARGIN,
1425            threshold: 0.01
1426        });
1427
1428        images.forEach(function (img) {
1429            if (img.dataset.lazySkip === '1') {
1430                applySource(img);
1431                return;
1432            }
1433
1434            observer.observe(img);
1435        });
1436    }
1437
1438    if (document.readyState === 'loading') {
1439        document.addEventListener('DOMContentLoaded', init);
1440    } else {
1441        init();
1442    }
1443
1444    window.TravelsoftLazyLoad = {
1445        init: init,
1446        applySource: applySource
1447    };
1448})(window, document);
1449
1450/* End */
1451;
1452; /* Start:"a:4:{s:4:"full";s:92:"/local/templates/travelsoft/components/bitrix/main.feedback/sletter/script.js?17887604111886";s:6:"source";s:77:"/local/templates/travelsoft/components/bitrix/main.feedback/sletter/script.js";s:3:"min";s:0:"";s:3:"map";s:0:"";}"*/
1453$(document).ready(function () {
1454    const rootSletter = document.querySelector('[data-ts-component="feedback_sletter"]');
1455    if (!rootSletter) return;
1456
1457    let config = {};
1458    try {
1459        config = JSON.parse(rootSletter.dataset.tsConfig || '{}');
1460    } catch (error) {
1461        config = {};
1462    }
1463
1464    $('#tour_submit_sletter' + config.rand).click(function (event) {
1465        event.preventDefault();
1466
1467        var btnid = $(this).data('id');
1468
1469        var email = $('#feedback_form_email_sletter' + btnid).val();
1470        var formcheck = $('#agree_sletter' + btnid).prop('checked');
1471        var url = $('#feedback_form_url_sletter' + btnid).val();
1472        var sess = $('#feedback_form_sess_sletter' + btnid).val();
1473        var radioPerson = $('input[name="person_type_sletter' + btnid + '"]:checked').val();
1474
1475        if (formcheck && email) {
1476            $.ajax({
1477                type: 'POST',
1478                url: '/local/templates/travelsoft/components/bitrix/main.feedback/sletter/ajax.php',
1479                data: { EMAIL: email, URL: url, SESS: sess, PERSON_TYPE: radioPerson },
1480                success: function (data) {
1481                    if (data) {
1482                        showFeedbackSuccess({ mode: 'open-success-modal', message: data });
1483                    } else {
1484                        window.ctReachGoal && window.ctReachGoal('FORM_SUBSCRIBE');
1485                        showFeedbackSuccess({ mode: 'open-success-modal' });
1486                    }
1487                },
1488                error: function () {
1489                    showFeedbackSuccess({
1490                        mode: 'open-success-modal',
1491                        message: 'Произошла ошибка при отправке формы. Пожалуйста, проверьте, все ли поля были заполнены.'
1492                    });
1493                }
1494            });
1495        }
1496    });
1497});
1498
1499/* End */
1500;
1501; /* Start:"a:4:{s:4:"full";s:72:"/local/templates/travelsoft/js/feedback-success-helper.js?17767924363108";s:6:"source";s:57:"/local/templates/travelsoft/js/feedback-success-helper.js";s:3:"min";s:0:"";s:3:"map";s:0:"";}"*/
1502(function (window, document) {
1503    var DEFAULT_SUCCESS_MESSAGE = 'Спасибо! Мы свяжемся с вами в ближайшее время.';
1504
1505    function escapeHtml(text) {
1506        return String(text)
1507            .replace(/&/g, '&amp;')
1508            .replace(/</g, '&lt;')
1509            .replace(/>/g, '&gt;')
1510            .replace(/"/g, '&quot;')
1511            .replace(/'/g, '&#039;');
1512    }
1513
1514    function getMessage(message) {
1515        return message || window.TS_FEEDBACK_SUCCESS_MESSAGE || DEFAULT_SUCCESS_MESSAGE;
1516    }
1517
1518    function buildSuccessContent(message) {
1519        return '' +
1520            '<div class="feedback-success-state text-center p-4">' +
1521            '  <h5 class="mb-3">Отправлено!</h5>' +
1522            '  <p class="mb-4">' + escapeHtml(getMessage(message)) + '</p>' +
1523            '  <button type="button" class="help__btn" data-bs-dismiss="modal" data-dismiss="modal">Закрыть</button>' +
1524            '</div>';
1525    }
1526
1527    function ensureSuccessModal() {
1528        var modal = document.getElementById('feedbackSuccessModal');
1529        if (modal) {
1530            return modal;
1531        }
1532
1533        var wrapper = document.createElement('div');
1534        wrapper.innerHTML = '' +
1535            '<div class="modal fade" id="feedbackSuccessModal" tabindex="-1" aria-hidden="true">' +
1536            '  <div class="modal-dialog modal-dialog-centered">' +
1537            '    <div class="modal-content">' +
1538            '      <div class="modal-body"></div>' +
1539            '    </div>' +
1540            '  </div>' +
1541            '</div>';
1542
1543        modal = wrapper.firstChild;
1544        document.body.appendChild(modal);
1545        return modal;
1546    }
1547
1548    function showFeedbackSuccess(options) {
1549        var params = options || {};
1550        var mode = params.mode;
1551        var message = getMessage(params.message);
1552
1553        if (mode === 'replace-modal-content') {
1554            var modalElement = params.modalId ? document.getElementById(params.modalId) : null;
1555            if (!modalElement) {
1556                return;
1557            }
1558
1559            var target = params.containerSelector
1560                ? modalElement.querySelector(params.containerSelector)
1561                : (modalElement.querySelector('.modal-body') || modalElement.querySelector('.modal-content'));
1562
1563            if (!target) {
1564                return;
1565            }
1566
1567            target.innerHTML = buildSuccessContent(message);
1568            return;
1569        }
1570
1571        if (mode === 'open-success-modal') {
1572            var successModal = ensureSuccessModal();
1573            var successContainer = successModal.querySelector('.modal-body');
1574            successContainer.innerHTML = buildSuccessContent(message);
1575
1576            if (window.bootstrap && window.bootstrap.Modal) {
1577                const modalInstance = new bootstrap.Modal(successModal);
1578                modalInstance.show();
1579                // window.bootstrap.Modal.getOrCreateInstance(successModal).show();
1580            }
1581        }
1582    }
1583
1584    window.TS_FEEDBACK_SUCCESS_MESSAGE = DEFAULT_SUCCESS_MESSAGE;
1585    window.showFeedbackSuccess = showFeedbackSuccess;
1586})(window, document);
1587
1588/* End */
1589;
1590; /* Start:"a:4:{s:4:"full";s:110:"/local/templates/travelsoft/components/travelsoft/travelsoft.news.list/h
1590ome_tourhot25/script.js?17874332571851";s:6:"source";s:95:"/local/templates/travelsoft/components/travelsoft/travelsoft.news.list/home_tourhot25/script.js";s:3:"min";s:0:"";s:3:"map";s:0:"";}"*/
1591document.addEventListener('DOMContentLoaded', function () {
1592    const root = document.querySelector('[data-ts-component="home_tourhot25"]');
1593    if (!root) return;
1594
1595    let config = {};
1596    try {
1597        config = JSON.parse(root.dataset.tsConfig || '{}');
1598    } catch (error) {
1599        config = {};
1600    }
1601
1602    const sliderClass = config.sliderClass || '';
1603    const swiperClass = config.swiperClass || '';
1604    if (!sliderClass || !swiperClass) return;
1605
1606    document.querySelectorAll('.' + sliderClass).forEach((container) => {
1607        const sliderEl = container.querySelector('.' + swiperClass);
1608        // Второй экземпляр на том же слайдере ломает листание: свайп двигает
1609        // один Swiper, а точки и стрелки остаются у другого. Файл может
1610        // выполниться дважды (ядро Битрикса + ручной тег в шаблоне), поэтому
1611        // проверяем, не инициализирован ли слайдер уже.
1612        if (!sliderEl || sliderEl.swiper) return;
1613
1614        new Swiper(sliderEl, {
1615            slidesPerView: 1.5,
1616            spaceBetween: 20,
1617            navigation: {
1618                nextEl: container.querySelector('.swiper-button-next'),
1619                prevEl: container.querySelector('.swiper-button-prev')
1620            },
1621            pagination: {
1622                el: container.querySelector('.swiper-pagination'),
1623                clickable: true
1624            },
1625            breakpoints: {
1626                1200: { slidesPerView: 4, spaceBetween: 20 },
1627                768: { slidesPerView: 2, spaceBetween: 20 },
1628                360: { slidesPerView: 1.1, spaceBetween: 10 },
1629                320: { slidesPerView: 1, spaceBetween: 10 }
1630            }
1631        });
1632    });
1633});
1634
1635/* End */
1636;
1637; /* Start:"a:4:{s:4:"full";s:77:"/local/components/travelsoft/quiz/templates/.default/script.js?17887604116920";s:6:"source";s:62:"/local/components/travelsoft/quiz/templates/.default/script.js";s:3:"min";s:0:"";s:3:"map";s:0:"";}"*/
1638/**
1639 * Квиз подбора тура: три вопроса и контакты.
1640 *
1641 * Вопросы приходят готовой разметкой из шаблона, здесь только переходы,
1642 * проверка контактов и отправка. Ответы уходят на /ajax/quiz.php, где их
1643 * ещё раз сверяют со списком вариантов.
1644 */
1645(function () {
1646	'use strict';
1647
1648	// Объединение JS в Битриксе может подключить этот файл выше по странице,
1649	// чем сам квиз, поэтому ждём готовности DOM, а не ищем разметку сразу.
1650	if (document.readyState === 'loading') {
1651		document.addEventListener('DOMContentLoaded', init);
1652	} else {
1653		init();
1654	}
1655
1656	function init() {
1657
1658	var quiz = document.querySelector('[data-quiz]');
1659	if (!quiz || quiz.dataset.quizReady === 'Y') {
1660		return;
1661	}
1662	quiz.dataset.quizReady = 'Y';
1663
1664	var steps = [].slice.call(quiz.querySelectorAll('[data-quiz-step]'));
1665	var progress = quiz.querySelector('[data-quiz-progress]');
1666	var fill = quiz.querySelector('[data-quiz-fill]');
1667	var current = quiz.querySelector('[data-quiz-current]');
1668	var actions = quiz.querySelector('[data-quiz-actions]');
1669	var backBtn = quiz.querySelector('[data-quiz-back]');
1670	var nextBtn = quiz.querySelector('[data-quiz-next]');
1671	var success = quiz.querySelector('[data-quiz-success]');
1672	var errorBox = quiz.querySelector('[data-quiz-error]');
1673	var nameInput = quiz.querySelector('[data-quiz-name]');
1674	var phoneInput = quiz.querySelector('[data-quiz-phone]');
1675
1676	if (!steps.length || !nextBtn) {
1677		return;
1678	}
1679
1680	var answers = {};
1681	var channel = 'phone';
1682	var index = 0;
1683	var sending = false;
1684
1685	function isContactStep(step) {
1686		return step.dataset.quizStep === 'contact';
1687	}
1688
1689	function render() {
1690		steps.forEach(function (step, i) {
1691			step.classList.toggle('is-active', i === index);
1692		});
1693
1694		var total = steps.length;
1695		fill.style.width = Math.round(((index + 1) / total) * 100) + '%';
1696		current.textContent = String(index + 1);
1697
1698		backBtn.hidden = index === 0;
1699
1700		var step = steps[index];
1701		if (isContactStep(step)) {
1702			nextBtn.textContent = 'Получить варианты';
1703			nextBtn.disabled = false;
1704		} else {
1705			nextBtn.textContent = 'Дальше';
1706			// Дальше пускаем только с выбранным ответом: иначе заявка приходит
1707			// пустой, и менеджеру всё равно приходится звонить и спрашивать.
1708			nextBtn.disabled = !answers[step.dataset.quizStep];
1709		}
1710	}
1711
1712	function goTo(next) {
1713		if (next < 0 || next >= steps.length) {
1714			return;
1715		}
1716		index = next;
1717		render();
1718	}
1719
1720	steps.forEach(function (step) {
1721		step.querySelectorAll('[data-quiz-value]').forEach(function (option) {
1722			option.addEventListener('click', function () {
1723				step.querySelectorAll('[data-quiz-value]').forEach(function (other) {
1724					other.classList.remove('is-selected');
1725				});
1726				option.classList.add('is-selected');
1727				answers[step.dataset.quizStep] = option.dataset.quizValue;
1728				nextBtn.disabled = false;
1729
1730				// Небольшая пауза, чтобы человек увидел, что выбор принят.
1731				window.setTimeout(function () {
1732					if (steps[index] === step) {
1733						goTo(index + 1);
1734					}
1735				}, 250);
1736			});
1737		});
1738	});
1739
1740	quiz.querySelectorAll('[data-quiz-channel]').forEach(function (button) {
1741		button.addEventListener('click', function () {
1742			quiz.querySelectorAll('[data-quiz-channel]').forEach(function (other) {
1743				other.classList.remove('is-active');
1744			});
1745			button.classList.add('is-active');
1746			channel = button.dataset.quizChannel;
1747		});
1748	});
1749
1750	backBtn.addEventListener('click', function () {
1751		goTo(index - 1);
1752	});
1753
1754	function showError(message, field) {
1755		errorBox.textContent = message;
1756		errorBox.hidden = false;
1757
1758		if (field) {
1759			field.classList.add('has-error');
1760			field.focus();
1761		}
1762	}
1763
1764	function clearError() {
1765		errorBox.hidden = true;
1766		errorBox.textContent = '';
1767		[nameInput, phoneInput].forEach(function (field) {
1768			if (field) {
1769				field.classList.remove('has-error');
1770			}
1771		});
1772	}
1773
1774	function digits(value) {
1775		return String(value || '').replace(/\D/g, '');
1776	}
1777
1778	function submit() {
1779		if (sending) {
1780			return;
1781		}
1782
1783		clearError();
1784
1785		var name = (nameInput.value || '').trim();
1786		if (name.length < 2) {
1787			showError('Напишите, как к вам обращаться.', nameInput);
1788			return;
1789		}
1790
1791		var phone = digits(phoneInput.value);
1792		if (phone.length !== 11) {
1793			showError('Проверьте номер телефона — нужно 11 цифр.', phoneInput);
1794			return;
1795		}
1796
1797		sending = true;
1798		nextBtn.disabled = true;
1799		nextBtn.textContent = 'Отправляем…';
1800
1801		var payload = new FormData();
1802		payload.append('NAME', name);
1803		payload.append('PHONE', phone);
1804		payload.append('CHANNEL', channel);
1805		payload.append('URL', window.location.pathname + window.location.search);
1806		Object.keys(answers).forEach(function (key) {
1807			payload.append('ANSWERS[' + key + ']', answers[key]);
1808		});
1809		if (window.BX && typeof BX.bitrix_sessid === 'function') {
1810			payload.append('sessid', BX.bitrix_sessid());
1811		}
1812
1813		fetch('/ajax/quiz.php', {
1814			method: 'POST',
1815			body: payload,
1816			credentials: 'same-origin'
1817		})
1818			.then(function (response) {
1819				if (response.status === 429) {
1820					throw new Error('С этого адреса сегодня уже отправляли заявки. Позвоните нам — ответим сразу.');
1821				}
1822				return response.json();
1823			})
1824			.then(function (data) {
1825				if (!data || !data.success) {
1826					throw new Error((data && data.error) || 'Не получилось отправить заявку. Позвоните нам, пожалуйста.');
1827				}
1828
1829				if (typeof window.ctReachGoal === 'function') {
1830					window.ctReachGoal('QUIZ_SUBMIT');
1831				}
1832
1833				steps.forEach(function (step) {
1834					step.classList.remove('is-active');
1835				});
1836				progress.hidden = true;
1837				actions.hidden = true;
1838				success.hidden = false;
1839				success.scrollIntoView({ block: 'center', behavior: 'smooth' });
1840			})
1841			.catch(function (error) {
1842				sending = false;
1843				nextBtn.disabled = false;
1844				nextBtn.textContent = 'Получить варианты';
1845				showError(error.message || 'Не получилось отправить заявку. Позвоните нам, пожалуйста.');
1846			});
1847	}
1848
1849	nextBtn.addEventListener('click', function () {
1850		if (isContactStep(steps[index])) {
1851			submit();
1852			return;
1853		}
1854		goTo(index + 1);
1855	});
1856
1857	[nameInput, phoneInput].forEach(function (field) {
1858		if (!field) {
1859			return;
1860		}
1861		field.addEventListener('input', clearError);
1862		field.addEventListener('keydown', function (event) {
1863			if (event.key === 'Enter') {
1864				event.preventDefault();
1865				submit();
1866			}
1867		});
1868	});
1869
1870	render();
1871
1872	}
1873})();
1874
1875/* End */
1876;
1877; /* Start:"a:4:{s:4:"full";s:122:"/local/templates/travelsoft/components/travelsoft/travelsoft.news.list/h
1877ome_recommend_intourdv252/script.js?17767924361016";s:6:"source";s:107:"/local/templates/travelsoft/components/travelsoft/travelsoft.news.list/home_recommend_intourdv252/script.js";s:3:"min";s:0:"";s:3:"map";s:0:"";}"*/
1878document.addEventListener('DOMContentLoaded', function () {
1879    const root = document.querySelector('[data-ts-component="home_recommend_intourdv252"]');
1880    if (!root) return;
1881
1882    let config = {};
1883    try {
1884        config = JSON.parse(root.dataset.tsConfig || '{}');
1885    } catch (error) {
1886        config = {};
1887    }
1888
1889    if (!Array.isArray(config.ajaxData) || !config.ajaxData.length) return;
1890
1891    function loadData(searchData) {
1892        const data = searchData.shift();
1893        if (!data) return;
1894        const requestData = { searchData: data, sessid: BX.bitrix_sessid() };
1895        $.get(config.ajaxUrl, requestData, function (response) {
1896            if (response.result) {
1897                response.result.forEach((item) => {
1898                    $(`#price-${item.uniq_id}`).html(`${item.price || 'Нет предложений'} <br><small>Мест: ${item.quota}</small>`);
1899                });
1900            }
1901            loadData(searchData);
1902        }, 'json');
1903    }
1904
1905    loadData(config.ajaxData.slice());
1906});
1907
1908/* End */
1909;
1910; /* Start:"a:4:{s:4:"full";s:85:"/local/templates/travelsoft/components/bitrix/news.list/trust/script.js?1776792436361";s:6:"source";s:71:"/local/templates/travelsoft/components/bitrix/news.list/trust/script.js";s:3:"min";s:0:"";s:3:"map";s:0:"";}"*/
1911document.addEventListener('DOMContentLoaded', function () {
1912    new Swiper('#trustslids', {
1913        slidesPerView: 1,
1914        effect: 'fade',
1915        fadeEffect: {
1916            crossFade: true
1917        },
1918        loop: true,
1919        // autoplay: {
1920        //     delay: 3000,
1921        //     disableOnInteraction: false
1922        // },
1923        speed: 800
1924    });
1925});
1926/* End */
1927;
1928; /* Start:"a:4:{s:4:"full";s:94:"/local/templates/travelsoft/components/bitrix/main.feedback/tour_form/script.js?17887604111418";s:6:"source";s:79:"/local/templates/travelsoft/components/bitrix/main.feedback/tour_form/script.js";s:3:"min";s:0:"";s:3:"map";s:0:"";}"*/
1929$(document).ready(function () {
1930
1931    $('.tour_submit_contacts').click(function (event) {
1932        event.preventDefault();
1933
1934        var name = $('#feedback_form_name_contacts').val();
1935        var phone = $('#feedback_form_phone_contacts').val();
1936        var formcheck = $('#agree_contacts').prop('checked');
1937        var url = $('#feedback_form_url_contacts').val();
1938        var sess = $('#feedback_form_sess_contacts').val();
1939        var radioPerson = $('input[name="person_type_contacts"]:checked').val();
1940
1941        if (formcheck && name && phone) {
1942            $.ajax({
1943                type: 'POST',
1944                url: '/local/templates/travelsoft/components/bitrix/main.feedback/tour_form/ajax.php',
1945                data: { NAME: name, PHONE: phone, URL: url, SESS: sess, PERSON_TYPE: radioPerson },
1946                success: function () {
1947                    window.ctReachGoal && window.ctReachGoal('FORM_CONTACTS');
1948                    showFeedbackSuccess({ mode: 'open-success-modal' });
1949                },
1950                error: function () {
1951                    showFeedbackSuccess({
1952                        mode: 'open-success-modal',
1953                        message: 'Произошла ошибка при отправке формы. Пожалуйста, проверьте, все ли поля были заполнены.'
1954                    });
1955                }
1956            });
1957        }
1958    });
1959});
1960
1961/* End */
1962;
1963; /* Start:"a:4:{s:4:"full";s:97:"/local/templates/travelsoft/components/bitrix/main.feedback/consult_form/script.js?17887604111534";s:6:"source";s:82:"/local/templates/travelsoft/components/bitrix/main.feedback/consult_form/script.js";s:3:"min";s:0:"";s:3:"map";s:0:"";}"*/
1964$(document).ready(function () {
1965
1966    $('#feedback_form_phone_consult').mask('+7 (999) 999-9999', { autoclear: false });
1967
1968    $('#tour_submit_consult').click(function (event) {
1969        event.preventDefault();
1970
1971        var phone = $('#feedback_form_phone_consult').val();
1972        var formcheck = $('#agree_consult').prop('checked');
1973        var url = $('#feedback_form_url_consult').val();
1974        var sess = $('#feedback_form_sess_consult').val();
1975        var radio = $('input[name="communication_method_consult"]:checked').val();
1976        var radioPerson = $('input[name="person_type_consult"]:checked').val();
1977
1978        if (formcheck && phone) {
1979            $.ajax({
1980                type: 'POST',
1981                url: '/local/templates/travelsoft/components/bitrix/main.feedback/consult_form/ajax.php',
1982                data: { PHONE: phone, URL: url, SESS: sess, COMMUNICATION_METHOD: radio, PERSON_TYPE: radioPerson },
1983                success: function () {
1984                    window.ctReachGoal && window.ctReachGoal('FORM_CONSULT');
1985                    showFeedbackSuccess({ mode: 'open-success-modal' });
1986                },
1987                error: function () {
1988                    showFeedbackSuccess({
1989                        mode: 'open-success-modal',
1990                        message: 'Произошла ошибка при отправке формы. Пожалуйста, проверьте, все ли поля были заполнены.'
1991                    });
1992                }
1993            });
1994        }
1995    });
1996});
1997
1998/* End */
1999;; /* /local/templates/travelsoft/components/bitrix/news.list/headicontSwiper/script.js?17773209312366*/
2000; /* /local/templates/travelsoft/components/bitrix/news.list/filter_tour25/script.
2000js?178315032353695*/
2001; /* /local/components/travelsoft/favorites.add/templates/.default/script.js?17455787132069*/
2002; /* /local/templates/travelsoft/components/travelsoft/travelsoft.news.list/home_recommend_intourdv25/script.js?17767924361015*/
2003; /* /local/templates/travelsoft/js/lazy-load.js?17756695832887*/
2004; /* /local/templates/travelsoft/components/bitrix/main.feedback/sletter/script.js?17887604111886*/
2005; /* /local/templates/travelsoft/js/feedback-success-helper.js?17767924363108*/
2006; /* /local/templates/travelsoft/components/travelsoft/travelsoft.news.list/home_tourhot25/script.js?17874332571851*/
2007; /* /local/components/travelsoft/quiz/templates/.default/script.js?17887604116920*/
2008; /* /local/templates/travelsoft/components/travelsoft/travelsoft.news.list/home_recommend_intourdv252/script.js?17767924361016*/
2009; /* /local/templates/travelsoft/components/bitrix/news.list/trust/script.js?1776792436361*/
2010; /* /local/templates/travelsoft/components/bitrix/main.feedback/tour_form/script.js?17887604111418*/
2011; /* /local/templates/travelsoft/components/bitrix/main.feedback/consult_form/script.js?17887604111534*/

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.