/** * Вебкомпонент для ініціації оновлення сторінки (Pull-to-Refresh) * за допомогою свайпу вниз на пристроях з iOS/iPadOS у режимі PWA. */ class SwipeUpdater extends HTMLElement { constructor() { super(); // 1. Створення Shadow DOM // Використовуємо тіньовий DOM для інкапсуляції стилів та структури const shadow = this.attachShadow({ mode: 'open' }); // 2. Внутрішня функція оновлення за замовчуванням this._appReload = () => { console.log('Стандартна функція: Перезавантаження сторінки'); // Стандартна дія - перезавантаження сторінки window.location.reload(); }; // 3. Внутрішній стан this._isReadyToReload = false; // Прапорець, що вказує на готовність до оновлення // 4. Створення елементів (Внутрішній HTML) shadow.innerHTML = `
`; // 5. Збереження посилань на елементи Shadow DOM this._animID = shadow.getElementById('swipe_updater'); this._animIconID = shadow.getElementById('swipe_icon'); // 6. Прив'язка контексту `this` для обробника подій (важливо для коректної роботи `this.handleScroll`) this.handleScroll = this.handleScroll.bind(this); } /** * Метод для встановлення користувацької функції оновлення. * Замінює стандартне перезавантаження сторінки. * @param {function} func - Користувацька функція, що буде викликана при свайпі. */ setReloadFunction(func) { if (typeof func === 'function') { this._appReload = func; } else { console.error('setReloadFunction вимагає передати функцію.'); } } /** * Обробник події скролу (головна логіка Pull-to-Refresh). * Відстежує прокручування вище верхньої межі сторінки (`window.scrollY < 0`). */ handleScroll() { // Перевірка на режим Standalone (PWA) - функціональність актуальна переважно тут const isStandalone = window.matchMedia('(display-mode: standalone)').matches; if (isStandalone) { let scrollY = window.scrollY; // 1. Анімація іконки під час прокручування за верхню межу (scrollY < 0) if (scrollY <= -10) { // Зміщення іконки разом із прокруткою this._animIconID.style.top = `${scrollY / 1.5}px`; this._animID.style.zIndex = '115'; // Піднімаємо z-index для видимості над контентом } else { this._animID.style.zIndex = '0'; // Повертаємо базовий z-index } const threshold = -125; // Поріг прокрутки (наприклад, -125px) для активації оновлення // 2. Логіка активації "готовий до оновлення" if (scrollY <= threshold) { if (!this._isReadyToReload) { this._isReadyToReload = true; // Поворот іконки на 180 градусів this._animIconID.style.transform = 'rotate(180deg)'; this._animIconID.setAttribute('data-state', ''); // Деактивація стану "active" } } // 3. Логіка виклику оновлення та скидання стану // Якщо користувач відпускає свайп (scrollY повертається до >= 0) І був готовий до оновлення else if (scrollY >= 0) { if (this._isReadyToReload) { // Виклик користувацької функції (або стандартного window.location.reload()) this._appReload(); // Скидання стану та анімації this._isReadyToReload = false; this._animIconID.style.transform = 'rotate(0deg)'; this._animIconID.setAttribute('data-state', 'active'); } } } } /** * Lifecycle hook: викликається при додаванні елемента в DOM. * Додаємо обробник події прокручування. */ connectedCallback() { // Прослуховування глобальної події скролу window.addEventListener('scroll', this.handleScroll); } /** * Lifecycle hook: викликається при видаленні елемента з DOM. * Видаляємо обробник події прокручування для запобігання витоку пам'яті. */ disconnectedCallback() { window.removeEventListener('scroll', this.handleScroll); } } // Реєстрація веб-компонента customElements.define('swipe-updater', SwipeUpdater); /* ============================ ПРИКЛАД ВИКОРИСТАННЯ ============================ */ /* 1. Додайте цей елемент у свій HTML: 2. Отримайте посилання на компонент у JS: const Updater = document.querySelector('swipe-updater'); 3. Користувацька функція оновлення function customReload() { const now = new Date().toLocaleTimeString(); console.log(`Користувацьке оновлення: оновлено о ${now}`); document.querySelector('h1').textContent = `Сторінка оновлена о ${now}`; // Тут можна виконати AJAX-запит, оновити DOM тощо. } 4. Перевизначення функції оновлення компонента if (Updater && Updater.setReloadFunction) { Updater.setReloadFunction(customReload); } else { console.error('Компонент SwipeUpdater не знайдено або не готовий.'); } 💡 Приклад стандартного використання (якщо не викликати setReloadFunction): При свайпі буде викликано window.location.reload(); */