PageSourceSearch

https://travel-times.ru/local/templates/main/components/bitrix/system.pagenavigation/ajax/script.js

js travel-times.ru collected 2026-10-07 16:46:28 UTC 10,894 bytes, 500 lines download raw bytes

1$(function () {
2
3    const storageKey = 'hotel_catalog_state_' + window.location.pathname;
4
5
6    /**
7     * Инициализация слайдеров отелей
8     */
9    function initHotelSliders() {
10
11        $('.hotel-img-slider').each(function () {
12
13            const sliderEl = this;
14            const slider = $(sliderEl);
15
16            // Уже инициализирован
17            if (sliderEl.swiper) {
18                return;
19            }
20
21            const slidesCount = slider
22                .find('.swiper-slide')
23                .length;
24
25            const zones = slider.find(
26                '.hotel-img-slider__zones'
27            );
28
29            zones.empty();
30
31            for (let i = 0; i < slidesCount; i++) {
32                zones.append(
33                    '<div class="hotel-img-slider__zone"></div>'
34                );
35            }
36
37            const hotelSlider = new Swiper(sliderEl, {
38                slidesPerView: 1,
39                speed: 300,
40                allowTouchMove: false,
41
42                pagination: {
43                    el: slider.find(
44                        '.hotel-img-slider__pagination'
45                    )[0],
46                    clickable: false,
47                },
48            });
49
50            slider
51                .find('.hotel-img-slider__zone')
52                .on('mouseenter', function () {
53
54                    const index = $(this).index();
55
56                    hotelSlider.slideTo(index);
57
58                });
59        });
60
61    }
62
63
64    /**
65     * Получаем сохранённое состояние
66     */
67    function getHotelState() {
68
69        const saved = sessionStorage.getItem(storageKey);
70
71        if (!saved) {
72            return null;
73        }
74
75        try {
76            return JSON.parse(saved);
77        } catch (e) {
78            return null;
79        }
80
81    }
82
83
84    /**
85     * Сохраняем состояние
86     */
87    function saveHotelState(data) {
88
89        const oldState = getHotelState() || {};
90
91        sessionStorage.setItem(
92            storageKey,
93            JSON.stringify({
94                ...oldState,
95                ...data
96            })
97        );
98
99    }
100
101
102    /**
103     * AJAX-загрузка конкретной страницы
104     */
105    function loadHotelPage(page, categoryId, callback) {
106
107        const sectionId = $('.hotels').data('section-id') || 0;
108
109        const ajaxData = {
110            HOTEL_CATEGORY: categoryId,
111            SECTION_ID: sectionId,
112            PAGEN_1: page
113        };
114
115        $.ajax({
116            url: '/local/ajax/hotels.php',
117            type: 'GET',
118            data: ajaxData,
119
120            success: function (html) {
121
122                const response = $('<div>').html(html);
123
124                const items = response.find(
125                    '.hotels__items .hotel__item'
126                );
127
128                const newBtn = response.find(
129                    '.hotel__ajax'
130                );
131
132                $('.hotels__items').append(items);
133
134                const btn = $('.hotel__ajax');
135
136                if (newBtn.length && btn.length) {
137
138                    btn.attr(
139                        'data-next-page',
140                        newBtn.attr('data-next-page')
141                    );
142
143                    btn
144                        .removeClass('loading')
145                        .text('Показать еще');
146
147                } else {
148
149                    btn.remove();
150                }
151
152                initHotelSliders();
153
154                if (typeof callback === 'function') {
155                    callback();
156                }
157            },
158
159            error: function () {
160
161                $('.hotel__ajax')
162                    .removeClass('loading')
163                    .text('Показать еще');
164            }
165        });
166    }
167
168
169    /**
170     * ============================================
171     * КНОПКА "ПОКАЗАТЬ ЕЩЁ"
172     * ============================================
173     */
174    $(document).on('click', '.hotel__ajax', function (e) {
175
176        e.preventDefault();
177
178        const btn = $(this);
179
180        if (btn.hasClass('loading')) {
181            return;
182        }
183
184        const nextPage = parseInt(
185            btn.attr('data-next-page'),
186            10
187        );
188
189        const navNum = parseInt(
190            btn.attr('data-nav-num'),
191            10
192        ) || 1;
193
194        const categoryId =
195            $('.hotel__tab.active').data('category') || '';
196
197        btn
198            .addClass('loading')
199            .text('Загрузка...');
200
201        loadHotelPage(
202            nextPage,
203            categoryId,
204            function () {
205
206                saveHotelState({
207                    loadedPage: nextPage,
208                    categoryId: categoryId
209                });
210
211            }
212        );
213
214    });
215
216
217    /**
218     * ============================================
219     * ПЕРЕХОД В ОТЕЛЬ
220     * ============================================
221     *
222     * Запоминаем карточку, по которой кликнули.
223     */
224    $(document).on(
225        'click',
226        '.hotel__item a[href]',
227        function () {
228
229            const item = $(this).closest('.hotel__item');
230
231            const categoryId =
232                $('.hotel__tab.active').data('category') || '';
233
234
235            /**
236             * Берём уникальный идентификатор карточки.
237             *
238             * Если у .hotel__item есть data-id,
239             * используем его.
240             *
241             * Иначе используем href.
242             */
243            let hotelId = item.attr('data-id') || '';
244
245            let hotelUrl = $(this).attr('href') || '';
246
247
248            saveHotelState({
249
250                loadedPage:
251                    parseInt(
252                        $('.hotel__ajax').attr('data-next-page'),
253                        10
254                    ) - 1 || 1,
255
256                categoryId: categoryId,
257
258                hotelId: hotelId,
259
260                hotelUrl: hotelUrl,
261
262                scrollY: window.scrollY,
263
264                restore: true
265
266            });
267
268        }
269    );
270
271
272    /**
273     * ============================================
274     * ПОИСК СОХРАНЁННОГО ОТЕЛЯ В DOM
275     * ============================================
276     */
277    function findSavedHotel(state) {
278
279        let item = $();
280
281
282        /**
283         * Лучший вариант — data-id
284         */
285        if (state.hotelId) {
286
287            item = $(
288                '.hotel__item[data-id="' +
289                state.hotelId +
290                '"]'
291            );
292
293        }
294
295
296        /**
297         * Если data-id нет — ищем по URL
298         */
299        if (!item.length && state.hotelUrl) {
300
301            $('.hotel__item').each(function () {
302
303                const currentItem = $(this);
304
305                const link = currentItem
306                    .find('a[href="' + state.hotelUrl + '"]')
307                    .first();
308
309                if (link.length) {
310                    item = currentItem;
311                    return false;
312                }
313
314            });
315
316        }
317
318
319        return item;
320
321    }
322
323
324    /**
325     * ============================================
326     * ПРОКРУТКА К ОТЕЛЮ
327     * ============================================
328     */
329    function scrollToSavedHotel(state) {
330
331        const item = findSavedHotel(state);
332
333
334        /**
335         * Если карточку нашли —
336         * скроллим именно к ней.
337         */
338        if (item.length) {
339
340            const headerHeight =
341                $('.header').outerHeight() || 0;
342
343            const top =
344                item.offset().top
345                - headerHeight
346                - 30;
347
348
349            window.scrollTo({
350                top: top,
351                behavior: 'auto'
352            });
353
354        } else {
355
356            /**
357             * Запасной вариант
358             */
359            window.scrollTo({
360                top: state.scrollY || 0,
361                behavior: 'auto'
362            });
363
364        }
365
366
367        /**
368         * Больше повторно не восстанавливаем
369         */
370        state.restore = false;
371
372        sessionStorage.setItem(
373            storageKey,
374            JSON.stringify(state)
375        );
376
377    }
378
379
380    /**
381     * ============================================
382     * ВОССТАНОВЛЕНИЕ AJAX-ПАГИНАЦИИ
383     * ============================================
384     */
385    function restoreHotelCatalog() {
386
387        const state = getHotelState();
388
389
390
391        if (
392            !state ||
393            !state.restore
394        ) {
395            return;
396        }
397
398        const navNum =
399            parseInt(state.navNum, 10) ||
400            parseInt($('.hotel__ajax').attr('data-nav-num'), 10) ||
401            1;
402
403        /**
404         * Запрещаем браузеру скроллить
405         * раньше, чем восстановится AJAX.
406         */
407        if ('scrollRestoration' in history) {
408            history.scrollRestoration = 'manual';
409        }
410
411
412        /**
413         * ВАЖНО:
414         *
415         * браузер мог вернуть страницу
416         * из BFCache уже со всеми подгруженными
417         * карточками.
418         *
419         * Тогда AJAX повторять нельзя.
420         */
421        const existingHotel = findSavedHotel(state);
422
423        if (existingHotel.length) {
424
425            requestAnimationFrame(function () {
426
427                requestAnimationFrame(function () {
428                    scrollToSavedHotel(state);
429                });
430
431            });
432
433            return;
434        }
435
436
437        const targetPage =
438            parseInt(state.loadedPage, 10) || 1;
439
440        const categoryId =
441            state.categoryId || '';
442
443
444        /**
445         * Первая страница уже находится
446         * в исходном HTML.
447         */
448        let currentPage = 1;
449
450
451        function loadNextPage() {
452
453            if (currentPage >= targetPage) {
454
455                requestAnimationFrame(function () {
456
457                    requestAnimationFrame(function () {
458
459                        scrollToSavedHotel(state);
460
461                    });
462
463                });
464
465                return;
466            }
467
468
469            currentPage++;
470
471
472            loadHotelPage(
473                currentPage,
474                categoryId,
475                navNum,
476                function () {
477                    loadNextPage();
478                }
479            );
480
481        }
482
483
484        loadNextPage();
485
486    }
487
488
489    /**
490     * Обычная инициализация
491     */
492    initHotelSliders();
493
494
495    /**
496     * Восстанавливаем каталог
497     */
498    restoreHotelCatalog();
499
500});

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.