PageSourceSearch

https://izhlife.ru/local/templates/main/js/custom.js?178290830617394

js izhlife.ru collected 2026-10-02 04:56:59 UTC 17,394 bytes, 471 lines download raw bytes

1document.addEventListener("DOMContentLoaded", function() {
2    // Добавление lazyload всем изображениям с классом lazy_load
3    const materialsListImgs = document.querySelectorAll('.materials-list__item img');
4    const detailTextImgs = document.querySelectorAll('.page-material__content img');
5    const slotsBlockImgs = document.querySelectorAll('.slots__block img');
6    const lazyLoadImgs = document.querySelectorAll('img.lazy_load');
7
8    // detailTextImgs.forEach(img => {
9    //     img.classList.add('lazy_load');
10    // });
11
12    // var lazyImages = [...lazyLoadImgs, ...detailTextImgs, ...slotsBlockImgs, ...materialsListImgs];
13    // if (lazyImages.length !== 0) {
14    //     lazyImages.forEach(img => {
15    //         if (!img.dataset.src) {
16    //             img.dataset.src = img.src;
17    //             img.src = "";
18    //         }
19    //     });
20
21    //     let observer = new IntersectionObserver((entries, observer) => {
22    //         entries.forEach(entry => {
23    //             if (entry.isIntersecting) {
24    //                 let img = entry.target;
25    //                 img.src = img.dataset.src;
26    //                 img.classList.remove("lazy");
27
28    //                 observer.unobserve(img);
29    //             }
30    //         });
31    //     });
32    
33    //     lazyImages.forEach(img => observer.observe(img));
34    // }
35
36    // Фильтрация фильмов по дате, фильму и кинотеатру
37    if (document.querySelector('.cinema-block-group')) {
38        chooseDateShow();
39    }
40
41    document.addEventListener('click', function (e) {
42        const linkMovie = e.target.closest('.js-select-movie');
43        const linkCinema = e.target.closest('.js-select-cinema');
44       
45        if (linkMovie) {
46            e.preventDefault();
47            const movieId = linkMovie.dataset.id;
48            const calendarDate = document.querySelector('[data-calendar-value="head-calendar"]').textContent;
49            const [day, month, year] = calendarDate.split('.');
50            const selectedDate = `${year}-${month}-${day}`;
51    
52            fetch('/local/ajax/afisha/filter.php', {
53                method: 'POST',
54                headers: {
55                    'Content-Type': 'application/json'
56                },
57                body: JSON.stringify({ movieId, selectedDate })
58            })
59            .then(res => res.text())
60            .then(html => {
61                document.querySelector('#movie-list-container').innerHTML = html;
62                const event = new Event('ajaxUpdateMovies', { bubbles: true });
63                document.querySelector('#movie-list-container').dispatchEvent(event);
64            });
65        }
66        if (linkCinema) {
67            e.preventDefault();
68            const cinemaId = linkCinema.dataset.id;
69    
70            fetch('/local/ajax/afisha/filter.php', {
71                method: 'POST',
72                headers: {
73                    'Content-Type': 'application/json'
74                },
75                body: JSON.stringify({ cinemaId })
76            })
77            .then(res => res.text())
78            .then(html => {
79                document.querySelector('#movie-list-container').innerHTML = html;
80                const event = new Event('ajaxUpdateMovies', { bubbles: true });
81                document.querySelector('#movie-list-container').dispatchEvent(event);
82            });
83        }
84        const label = e.target.closest('.calendar-dropdown__mlabel');
85        const hasCurrentMovieParent = label && label.closest('.current_movie');
86
87        if (label && !hasCurrentMovieParent) {
88            e.preventDefault();
89            const linkDate = label;
90            const date = linkDate.dataset.date;
91            fetch('/local/ajax/afisha/filter.php', {
92                method: 'POST',
93                headers: {
94                    'Content-Type': 'application/json'
95                },
96                body: JSON.stringify({ selectedDate: date })
97            })
98            .then(res => res.text())
99            .then(html => {
100                document.querySelector('#movie-list-container').innerHTML = html;
101                const event = new Event('ajaxUpdateMovies', { bubbles: true });
102                document.querySelector('#movie-list-container').dispatchEvent(event);
103            });
104        }
105    });
106
107    // Открытие модалки с трейлером на странице списка фильмов
108    const modal = document.getElementById('trailerModal');
109    if (modal) {
110        const iframe = document.getElementById('trailerIframe');
111        const overlay = modal.querySelector('.trailer_modal__overlay');
112        const content = modal.querySelector('.trailer_modal__content');
113      
114        document.querySelectorAll('.open_trailer').forEach(btn => {
115            btn.addEventListener('click', function () {
116                const trailerUrl = this.dataset.trailer;
117                iframe.src = trailerUrl;
118                modal.classList.add('active');
119            });
120        });
121      
122        overlay.addEventListener('click', function (e) {
123            if (!content.contains(e.target)) {
124                modal.classList.remove('active');
125                iframe.src = '';
126            }
127        });
128    }
129});
130
131document.addEventListener('ajaxUpdateMovies', () => {
132    chooseDateShow();
133})
134
135function chooseDateShow () {
136    const cinemaBlocks = document.querySelectorAll('.cinema-details-block');
137    const inputDate = document.querySelector('[data-calendar-value="head-calendar"]').textContent;
138    const [day, month, year] = inputDate.split('.');
139    const calendarDate = `${year}-${month}-${day}`;
140
141    cinemaBlocks.forEach(cinemaBlock => {
142        if (cinemaBlock) {
143            const filterButtons = cinemaBlock.querySelectorAll(".date-filter-btn");
144            const datePicker = cinemaBlock.querySelector(".cinema-detail
144s-schedule__datepicker");
145            const scheduleBlocks = cinemaBlock.querySelectorAll(".cinema-details-schedule__address");
146    
147            function filterByDate(selectedDate) {
148                // Показываем расписание на выбранную дату
149                scheduleBlocks.forEach(block => {
150                    const blockDate = block.dataset.sessionDate;
151                    if (blockDate === selectedDate) {
152                        block.style.display = "";
153                    } else {
154                        block.style.display = "none";
155                    }
156                });
157                // Убираем активность с кнопок "сегодня", "завтра"
158                filterButtons.forEach(btn => {
159                    if (btn.dataset.date !== selectedDate) {
160                        btn.classList.remove("active");
161                    } else {
162                        btn.classList.add("active");
163                    }
164                })
165            }
166    
167            filterButtons.forEach(btn => {
168                btn.addEventListener("click", () => {
169                    const selectedDate = btn.dataset.date;
170                    filterByDate(selectedDate);
171                });
172            });
173
174            // Выбор даты у конкретного фильма
175            if (datePicker) {
176                datePicker.addEventListener('click', (e)=> {
177                    e.preventDefault();
178                    e.stopPropagation();
179                    const calendar = document.querySelector('.dropdown-custom.calendar-dropdown');
180                    calendar.classList.add('shown', 'current_movie');
181
182                    const rect = datePicker.getBoundingClientRect();
183                    calendar.style.top = `${window.scrollY + rect.top - 450}px`;
184                    calendar.style.left = 260 + 'px';
185
186                    calendar.addEventListener('click', (e)=> {
187                        const linkDate = e.target.closest('.calendar-dropdown__mlabel');
188                        e.preventDefault();
189                        if (linkDate && calendar.classList.contains('current_movie')) {
190                            const date = linkDate.dataset.date;
191                            filterByDate(date);
192                            
193                            setTimeout(() => {
194                                calendar.classList.remove('current_movie');
195                                calendar.style.left = '';
196                            }, 500)
197                        }
198                    })
199                })
200            }
201        
202            const today = new Date();
203            const year = today.getFullYear();
204            const month = String(today.getMonth() + 1).padStart(2, '0');
205            const day = String(today.getDate()).padStart(2, '0');
206        
207            const currentDate = `${year}-${month}-${day}`;
208            const filterDate = currentDate == calendarDate ? currentDate : calendarDate;
209        
210            // При загрузке показываем только "Сегодня" либо на дату из календаря в шапке
211            filterByDate(filterDate);
212
213            // Добавляем нижнюю рамку блокам с расписанием (кроме последнего на текущую дату)
214            const elements = Array.from(cinemaBlock.querySelectorAll('.cinema-details-schedule__address'));
215            const groupedByDate = elements.reduce((acc, el) => {
216                const date = el.dataset.sessionDate;
217                if (!acc[date]) acc[date] = [];
218                acc[date].push(el);
219                return acc;
220            }, {});
221
222            Object.values(groupedByDate).forEach(group => {                
223                if (group.length > 1) {
224                    group.slice(0, -1).forEach(el => {
225                        el.style.borderBottom = '1px solid orange';
226                        el.style.paddingBottom = '36px';
227                    });
228                }
229            });
230        }
231    })
232}
233document.addEventListener('DOMContentLoaded', function() {
234    // Функция для установки cookie
235    function setCookie(name, value, days) {
236        let expires = "";
237        if (days) {
238            let date = new Date();
239            date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
240            expires = "; expires=" + date.toUTCString();
241        }
242        document.cookie = name + "=" + (value || "") + expires + "; path=/";
243    }
244
245    // Функция для получения cookie
246    function getCookie(name) {
247        let nameEQ = name + "=";
248        let ca = document.cookie.split(';');
249        for(let i = 0; i < ca.length; i++) {
250            let c = ca[i];
251            while (c.charAt(0) == ' ') {
252                c = c.substring(1, c.length);
253            }
254            if (c.indexOf(nameEQ) == 0) {
255                return c.substring(nameEQ.length, c.length);
256            }
257        }
258        return null;
259    }
260
261    // Получаем элемент попапа
262    const cookiesPopup = document.querySelector('.cookies');
263    const acceptButton = document.querySelector('.cookies__button');
264
265    // Проверяем наличие cookie при загрузке страницы
266    if (getCookie('cookies_accepted')) {
267        cookiesPopup.style.display = 'none';
268    } else {
269        cookiesPopup.style.display = 'block';
270    }
271
272    // Обработчик клика по кнопке "Окей"
273    acceptButton.addEventListener('click', function() {
274        setCookie('cookies_accepted', 'true', 1); // Устанавливаем cookie на 1 день
275        cookiesPopup.style.display = 'none';
276    });
277});
278
279
280(function() {
281    const sentSteps = new Set();
282
283    function getMilestone(percent) {
284        if (percent === 0) return 0;
285        if (percent > 0 && percent < 50) return 25;
286        if (percent >= 50 && percent < 75) return 50;
287        if (percent >= 75 && percent < 100) return 75;
288        if (percent === 100) return 100;
289        return null;
290    }
291
292    function checkProgress() {
293        const progressBlock = document.querySelector('.test__progress');
294        if (!progressBlock) return;
295
296        const items = progressBlock.querySelectorAll('.test__progress-item');
297        const filled = progressBlock.querySelectorAll('.test__progress-item--fill');
298
299        if (!items.length) return;
300
301        const percent = Math.round((filled.length / items.length) * 100);
302        const milestone = getMilestone(percent);
303
304        if (milestone !== null && !sentSteps.has(milestone)) {
305            sentSteps.add(milestone);
306            // console.log('Отправлена цель:', milestone + '%');
307             if (typeof ym === 'function') {
308                ym(217899, 'reachGoal', 'proc_test', { progress: milestone });
309            }
310        }
311    }
312
313    function bindForm() {
314        const form = document.querySelector('.test__form');
315        if (!form) return;
316
317        form.removeEventListener('submit', form._checkProgressSubmit);
318        form._checkProgressSubmit = () => setTimeout(checkProgress, 100);
319        form.addEventListener('submit', form._checkProgressSubmit);
320    }
321
322    bindForm();
323    checkProgress();
324
325    if (typeof BX !== 'undefined') {
326        BX.addCustomEvent('onAjaxSuccess', () => {
327            sentSteps.clear();
328            bindForm();
329            checkProgress();
330        });
331    }
332})();
333(function() {
334  document.querySelectorAll('[data-drag-scroll]').forEach(function(wrap) {
335    var isDown = false;
336    var startX;
337    var scrollLeft;
338
339    wrap.addEventListener('mousedown', function(e) {
340      if (e.button !== 0) return;
341      isDown = true;
342      wrap.style.cursor = 'grabbing';
343      startX = e.pageX - wrap.offsetLeft;
344      scrollLeft = wrap.scrollLeft;
345      e.preventDefault();
346    });
347
348    document.addEventListener('mouseup', function() {
349      if (!isDown) return;
350      isDown = false;
351      wrap.style.cursor = 'grab';
352    });
353
354    wrap.addEventListener('mouseleave', function() {
355      if (!isDown) return;
356      isDown = false;
357      wrap.style.cursor = 'grab';
358    });
359
360    wrap.addEventListener('mousemove', function(e) {
361      if (!isDown) return;
362      var x = e.pageX - wrap.offsetLeft;
363      wrap.scrollLeft = scrollLeft - (x - startX) * 1.5;
364    });
365  });
366})();
367
368(function() {
369  var fileInputs = document.querySelectorAll('input[type="file"][data-max-file-size]');
370
371  if (!fileInputs.length) {
372    return;
373  }
374
375  function getFileValidationMessage(input, file) {
376    if (!input || !file) {
377      return '';
378    }
379
380    var maxFileSize = parseInt(input.getAttribute('data-max-file-size') || '0', 10);
381    var maxFileSizeMb = parseInt(input.getAttribute('data-max-file-size-mb') || '0', 10);
382    var allowedExtensions = (input.getAttribute('data-allowed-extensions') || '')
383      .split(',')
384      .map(function(item) {
385        return item.trim().toLowerCase();
386      })
387      .filter(Boolean);
388    var fileName = file.name || '';
389    var extension = fileName.indexOf('.') !== -1 ? fileName.split('.').pop().toLowerCase() : '';
390
391    if (maxFileSize > 0 && file.size > maxFileSize) {
392      return 'Файл слишком большой. Максимальный размер вложения: ' + (maxFileSizeMb || Math.round(maxFileSize / 1048576)) + ' МБ.';
393    }
394
395    if (allowedExtensions.length && allowedExtensions.indexOf(extension) === -1) {
396      return 'Недопустимый формат файла. Разрешены: ' + allowedExtensions.join(', ') + '.';
397    }
398
399    return '';
400  }
401
402  function resetFileInput(wrapper) {
403    if (!wrapper) {
404      return;
405    }
406
407    var input = wrapper.querySelector('input[type="file"]');
408    var label = wrapper.querySelector('.custom-file__label');
409
410    if (input) {
411      input.value = '';
412    }
413
414    wrapper.classList.remove('not-empty');
415
416    if (label) {
417      label.textContent = label.getAttribute('data-default-label') || 'Добавить файл';
418    }
419  }
420
421  function validateInput(input, showAlert) {
422    var files = input && input.files ? input.files : null;
423    var file = files && files.length ? files[0] : null;
424    var message = getFileValidationMessage(input, file);
425
426    if (message) {
427      if (showAlert && typeof window.alert === 'function') {
428        window.alert(message);
429      }
430
431      resetFileInput(input.closest('.custom-file'));
432      return false;
433    }
434
435    return true;
436  }
437
438  fileInputs.forEach(function(input) {
439    var wrapper = input.closest('.custom-file');
440    var label = wrapper ? wrapper.querySelector('.custom-file__label') : null;
441
442    if (label && !label.getAttribute('data-default-label')) {
443      label.setAttribute('data-default-label', label.textContent);
444    }
445
446    input.addEventListener('change', function() {
447      validateInput(input, true);
448    });
449
450    var form = input.closest('form');
451
452    if (form && !form.hasAttribute('data-file-guard-bound')) {
453      form.setAttribute('data-file-guard-bound', 'Y');
454      form.addEventListener('submit', function(event) {
455        var formInputs = form.querySelectorAll('input[type="file"][data-max-file-size]');
456        var isValid = true;
457
458        formInputs.forEach(function(formInput) {
459          if (!validateInput(formInput, true)) {
460            isValid = false;
461          }
462        });
463
464        if (!isValid) {
465          event.preventDefault();
466          event.stopPropagation();
467        }
468      }, true);
469    }
470  });
471})();

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.