PageSourceSearch

https://kiaparts.com.ua/js/memorial.js?0.1

js kiaparts.com.ua collected 2026-10-04 20:30:58 UTC 8,161 bytes, 211 lines download raw bytes

1// ================= НАСТРОЙКИ ВРЕМЕНИ И ЗВУКА ПОПАПА =================
2const POPUP_CONFIG = {
3  startHour: 9,          // Час открытия (0-23)
4  startMinute: 0,        // Минута открытия (0-59)
5  durationMinutes: 1,    // Длительность показа в минутах
6  enableMetronome: true, // Включить метроном глобально в коде (true/false)
7  soundOnByDefault: true // Включать ли звук сразу при открытии (если разрешит браузер)
8};
9// ====================================================================
10
11function addPopupStyle(){
12    const styleTag = document.createElement('style');
13    styleTag.textContent = 
14`/* Фон-подложка на весь экран */
15.popup-overlay {
16  position: fixed; top: 0; left: 0; width: 100vw; height: 100dvh;
17  background-color: rgba(0, 0, 0, 0.75); backdrop-filter: blur(5px);           
18  display: flex; justify-content: center; align-items: center; z-index: 9999;                        
19}
20/* Само белое окошко по центру */
21.popup-content {
22  position: relative;
23  font-size: 1.25rem; background: #ffffff; padding: 35px 30px 30px; border-radius: 12px;
24  max-width: 475px; width: 95%; box-shadow: 0 10px 30px rgba(0, 0, 0, 0.3); text-align: center;                   
25}
26.popup-content p { padding: 5px 0px; margin: 0; line-height: 1.4; }
27.no-scroll { overflow: hidden; }
28/* Контейнер таймера */
29.timer-overlay { display: flex; justify-content: center; align-items: center; margin-top: 20px; }
30.timer__items { display: flex; font-size: 2rem; font-weight: bold; }
31.timer__item { position: relative; min-width: 60px; margin-left: 15px; margin-right: 15px; padding-bottom: 20px; text-align: center; }
32.timer__item::before {
33  content: attr(data-title); display: block; position: absolute; left: 50%; bottom: 0;
34  transform: translateX(-50%); font-size: 12px; font-weight: normal; color: #666;
35}
36.timer__item:not(:last-child)::after { content: ':'; position: absolute; right: -18px; top: -2px; }
37
38/* Кнопка управления звуком */
39.popup-audio-toggle {
40  position: absolute; top: 15px; right: 15px;
41  background: none; border: none; font-size: 1.5rem; cursor: pointer;
42  padding: 5px; opacity: 0.6; transition: opacity 0.2s;
43}
44.popup-audio-toggle:hover { opacity: 1; }`;
45    
46    document.head.appendChild(styleTag);
47}
48
49let countdownInterval = null;
50let audioCtx = null;
51let isSoundMuted = !POPUP_CONFIG.soundOnByDefault;
52
53/**
54 * Генерация звука стука метронома без использования mp3 файлов
55 */
56function playMetronomeTick() {
57    if (!POPUP_CONFIG.enableMetronome || isSoundMuted) return;
58
59    try {
60        if (!audioCtx) {
61            audioCtx = new (window.AudioContext || window.webkitAudioContext)();
62        }
63        
64        // Если браузер заблокировал аудио из-за политики autoplay, пробуем возобновить
65        if (audioCtx.state === 'suspended') {
66            audioCtx.resume();
67        }
68
69        const osc = audioCtx.createOscillator();
70        const gain = audioCtx.createGain();
71
72        osc.connect(gain);
73        gain.connect(audioCtx.destination);
74
75        // Имитируем глухой деревянный стук
76        osc.type = 'triangle'; 
77        osc.frequency.setValueAtTime(120, audioCtx.currentTime); // Низкая частота стука
78        
79        // Быстрое затухание звука за 0.08 секунды
80        gain.gain.setValueAtTime(0.6, audioCtx.currentTime);
81        gain.gain.exponentialRampToValueAtTime(0.001, audioCtx.currentTime + 0.08);
82
83        osc.start(audioCtx.currentTime);
84        osc.stop(audioCtx.currentTime + 0.08);
85    } catch (e) {
86        console.log("Браузер заблокировал автоматический звук до первого клика:", e);
87    }
88}
89
90function getPopupDeadline() {
91    const deadline = new Date();
92    deadline.setHours(POPUP_CONFIG.startHour, POPUP_CONFIG.startMinute + POPUP_CONFIG.durationMinutes, 0, 0);
93    return deadline;
94}
95
96function isItPopupTime() {
97    const now = new Date();
98    const startTime = new Date();
99    startTime.setHours(POPUP_CONFIG.startHour, POPUP_CONFIG.startMinute, 0, 0);
100    const endTime = getPopupDeadline();
101    return now >= startTime && now < endTime;
102}
103
104/**
105 * Создание и открытие попапа
106 */
107function openPopup() {
108    document.body.classList.add('no-scroll');
109    
110    const targetDate = getPopupDeadline();
111    const timestamp = targetDate.getTime(); 
112
113    const overlay = document.createElement('div');
114    overlay.className = 'popup-overlay';
115    overlay.innerHTML = `
116      <div class="popup-content">
117        <!-- Кнопка звука -->
118        ${POPUP_CONFIG.enableMetronome ? `<button class="popup-audio-toggle" id="popupAudioBtn" title="Вкл/Выкл звук">${isSoundMuted ? '🔇' : '🔊'}</button>` : ''}
119        
120        <p>Шановні відвідувачі сайту!</p>
121        <p>Щоранку о <b>${String(POPUP_CONFIG.startHour).padStart(2, '0')}
121:${String(POPUP_CONFIG.startMinute).padStart(2, '0')}</b><br> ми зупиняємося на хвилину.</p>
122        <p>Щоб згадати тих,<br> хто віддав життя за Україну.</p>
123        <p>Щоб подякувати й зберегти світлу пам'ять.</p>
124        <div class="timer-overlay">
125            <div id="timer" class="timer" data-dead-line="${timestamp}">
126                <div class="timer__items">
127                    <div class="timer__item timer__minutes" data-title="хв">00</div>
128                    <div class="timer__item timer__seconds" data-title="сек">00</div>
129                </div>
130            </div>
131        </div>
132      </div>
133    `;
134    document.body.appendChild(overlay);
135
136    const minutesEl = overlay.querySelector('.timer__minutes');
137    const secondsEl = overlay.querySelector('.timer__seconds');
138    const audioBtn = overlay.querySelector('#popupAudioBtn');
139
140    // Переключение звука по клику на иконку в попапе
141    if (audioBtn) {
142        audioBtn.addEventListener('click', () => {
143            isSoundMuted = !isSoundMuted;
144            audioBtn.textContent = isSoundMuted ? '🔇' : '🔊';
145            
146            // Активируем контекст, если это был первый клик пользователя
147            if (!isSoundMuted && !audioCtx) {
148                audioCtx = new (window.AudioContext || window.webkitAudioContext)();
149            }
150        });
151    }
152
153    function updateTimer() {
154        const now = new Date();
155        const diff = targetDate - now;
156
157        if (diff <= 0) {
158            closePopup(overlay);
159            return;
160        }
161
162        const minutes = Math.floor((diff / 1000 / 60) % 60);
163        const seconds = Math.floor((diff / 1000) % 60);
164
165        minutesEl.textContent = String(minutes).padStart(2, '0');
166        secondsEl.textContent = String(seconds).padStart(2, '0');
167
168        // 💥 Каждый тик таймера (раз в секунду) воспроизводим удар метронома
169        playMetronomeTick();
170    }
171
172    updateTimer();
173    countdownInterval = setInterval(updateTimer, 1000);
174
175    overlay.addEventListener('needClouse', () => {
176        closePopup(overlay);
177    });
178    
179    return overlay;
180}
181
182function closePopup(overlayElement) {
183    if (countdownInterval) clearInterval(countdownInterval);
184    if (overlayElement) overlayElement.remove();
185    document.body.classList.remove('no-scroll');
186    if (audioCtx) {
187        audioCtx.close();
188        audioCtx = null;
189    }
190}
191
192function checkTimeAndRun() {
193    setInterval(() => {
194        if (isItPopupTime()) {
195            if (!document.querySelector('.popup-overlay')) {
196                openPopup();
197            }
198        }
199    }, 1000);
200}
201
202$(function(){
203    addPopupStyle();
204    
205    if (isItPopupTime()) {
206        openPopup();
207    }
208
209    checkTimeAndRun(); 
210});
211

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.