Додан фільтр на сторінці керування вісниками.
Виправлено помилки.
This commit is contained in:
@@ -19,6 +19,8 @@ class SwipeUpdater extends HTMLElement {
|
||||
|
||||
// 3. Внутрішній стан
|
||||
this._isReadyToReload = false; // Прапорець, що вказує на готовність до оновлення
|
||||
this._isStandalone = false; // Кеш для перевірки PWA режиму
|
||||
this._isTouching = false; // Чи тримає користувач палець на екрані
|
||||
|
||||
// 4. Створення елементів (Внутрішній HTML)
|
||||
shadow.innerHTML = `
|
||||
@@ -111,8 +113,10 @@ class SwipeUpdater extends HTMLElement {
|
||||
this._animID = shadow.getElementById('swipe_updater');
|
||||
this._animIconID = shadow.getElementById('swipe_icon');
|
||||
|
||||
// 6. Прив'язка контексту `this` для обробника подій (важливо для коректної роботи `this.handleScroll`)
|
||||
// 6. Прив'язка контексту `this` для обробників подій
|
||||
this.handleScroll = this.handleScroll.bind(this);
|
||||
this.handleTouchStart = this.handleTouchStart.bind(this);
|
||||
this.handleTouchEnd = this.handleTouchEnd.bind(this);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -128,51 +132,81 @@ class SwipeUpdater extends HTMLElement {
|
||||
}
|
||||
}
|
||||
|
||||
// Фіксуємо, що користувач торкнувся екрана
|
||||
handleTouchStart() {
|
||||
this._isTouching = true;
|
||||
}
|
||||
|
||||
// Обробка події, коли користувач відпускає екран
|
||||
handleTouchEnd() {
|
||||
this._isTouching = false;
|
||||
const threshold = -165;
|
||||
|
||||
// Якщо палець відпустили, а ефект «гумового скролу» вже повернувся вище порогу
|
||||
// (тобто користувач передумав і потягнув назад вгору перед тим як відпустити)
|
||||
if (window.scrollY > threshold && this._isReadyToReload) {
|
||||
this._resetRefreshState();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Обробник події скролу (головна логіка Pull-to-Refresh).
|
||||
* Відстежує прокручування вище верхньої межі сторінки (`window.scrollY < 0`).
|
||||
*/
|
||||
handleScroll() {
|
||||
// Перевірка на режим Standalone (PWA) - функціональність актуальна переважно тут
|
||||
const isStandalone = window.matchMedia('(display-mode: standalone)').matches;
|
||||
if (!this._isStandalone) return;
|
||||
|
||||
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 scrollY = window.scrollY;
|
||||
const threshold = -165; // Поріг прокрутки (наприклад, -125px) для активації оновлення
|
||||
|
||||
// 1. Анімація іконки під час прокручування за верхню межу (scrollY < 0)
|
||||
if (scrollY <= -10) {
|
||||
// Зміщення іконки разом із прокруткою
|
||||
this._animIconID.style.top = `${scrollY / 1.5}px`;
|
||||
this._animID.style.zIndex = '115'; // Піднімаємо z-index для видимості над контентом
|
||||
} else {
|
||||
this._animIconID.style.top = '0px';
|
||||
this._animID.style.zIndex = '0'; // Повертаємо базовий z-index
|
||||
}
|
||||
|
||||
// 2. Логіка активації "готовий до оновлення"
|
||||
if (scrollY <= threshold) {
|
||||
if (!this._isReadyToReload) {
|
||||
this._isReadyToReload = true;
|
||||
// Поворот іконки на 180 градусів
|
||||
this._animIconID.style.transform = 'rotate(180deg)';
|
||||
this._animIconID.setAttribute('data-state', ''); // Деактивація стану "active"
|
||||
}
|
||||
|
||||
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');
|
||||
}
|
||||
}
|
||||
// Скасування жесту під час руху пальцем вгору (ще до відпускання)
|
||||
else if (scrollY > threshold && scrollY < 0 && this._isTouching) {
|
||||
if (this._isReadyToReload) {
|
||||
this._isReadyToReload = false;
|
||||
this._animIconID.style.transform = 'rotate(0deg)';
|
||||
this._animIconID.setAttribute('data-state', 'active');
|
||||
}
|
||||
}
|
||||
// 3. Логіка виклику оновлення, коли сторінка повернулась до нуля
|
||||
else if (scrollY >= 0) {
|
||||
if (this._isReadyToReload) {
|
||||
this._appReload();
|
||||
this._resetRefreshState();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Допоміжний метод для повного скидання графічного стану
|
||||
*/
|
||||
_resetRefreshState() {
|
||||
this._isReadyToReload = false;
|
||||
this._animIconID.style.transform = 'rotate(0deg)';
|
||||
this._animIconID.setAttribute('data-state', 'active');
|
||||
this._animIconID.style.top = '0px';
|
||||
this._animID.style.zIndex = '0';
|
||||
}
|
||||
|
||||
|
||||
@@ -181,8 +215,15 @@ class SwipeUpdater extends HTMLElement {
|
||||
* Додаємо обробник події прокручування.
|
||||
*/
|
||||
connectedCallback() {
|
||||
// Прослуховування глобальної події скролу
|
||||
window.addEventListener('scroll', this.handleScroll);
|
||||
// Перевіряємо PWA режим ОДИН раз при додаванні компонента на сторінку
|
||||
this._isStandalone = window.matchMedia('(display-mode: standalone)').matches;
|
||||
|
||||
if (this._isStandalone) {
|
||||
window.addEventListener('scroll', this.handleScroll);
|
||||
// passive: true покращує продуктивність скролу на мобільних пристроях
|
||||
window.addEventListener('touchstart', this.handleTouchStart, { passive: true });
|
||||
window.addEventListener('touchend', this.handleTouchEnd, { passive: true });
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -190,12 +231,17 @@ class SwipeUpdater extends HTMLElement {
|
||||
* Видаляємо обробник події прокручування для запобігання витоку пам'яті.
|
||||
*/
|
||||
disconnectedCallback() {
|
||||
// Чистимо абсолютно всі додані слухачі
|
||||
window.removeEventListener('scroll', this.handleScroll);
|
||||
window.removeEventListener('touchstart', this.handleTouchStart);
|
||||
window.removeEventListener('touchend', this.handleTouchEnd);
|
||||
}
|
||||
}
|
||||
|
||||
// Реєстрація веб-компонента
|
||||
customElements.define('swipe-updater', SwipeUpdater);
|
||||
if (!customElements.get('swipe-updater')) {
|
||||
customElements.define('swipe-updater', SwipeUpdater);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
|
||||
@@ -11,7 +11,6 @@
|
||||
/>
|
||||
</svg>
|
||||
</button>
|
||||
${butt_add}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -162,7 +162,7 @@ const Sheeps = {
|
||||
let html = await fetch('/lib/pages/sheeps/index.html').then((response) => response.text());
|
||||
app.innerHTML = html;
|
||||
|
||||
await Sheeps.sheeps_list.setHTML();
|
||||
await Sheeps.sheeps_list.setHTML({});
|
||||
if (id) Sheeps.editor.setHTML(id);
|
||||
|
||||
SheepsEvents.init();
|
||||
@@ -182,7 +182,7 @@ const Sheeps = {
|
||||
|
||||
return Sheeps.sheeps_list.list
|
||||
},
|
||||
setHTML: async (search_value = null) => {
|
||||
setHTML: async ({search, filter}) => {
|
||||
let block_sheep_list = document.getElementById('block-sheeps-list');
|
||||
let block_sheep_info = document.getElementById('block-sheep-info');
|
||||
block_sheep_list.style.display = "flex";
|
||||
@@ -210,6 +210,9 @@ const Sheeps = {
|
||||
<div class="header">
|
||||
<h1>Всі вісники</h1>
|
||||
<div>
|
||||
<button title="Фільтрувати" onclick="Sheeps.filter.open()">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:svgjs="http://svgjs.com/svgjs" x="0" y="0" viewBox="0 0 24 24" xml:space="preserve" style="padding: 6px;"><g><path xmlns="http://www.w3.org/2000/svg" d="m21 2h-18a1.0007 1.0007 0 0 0 -.8193 1.5732l6.8193 9.7422v7.6846a1.0015 1.0015 0 0 0 1.53.8481l4-2.5a1.0014 1.0014 0 0 0 .47-.8481v-5.1846l6.8193-9.7422a1.0007 1.0007 0 0 0 -.8193-1.5732z"></path></g></svg>
|
||||
</button>
|
||||
<button title="Пошук" onclick="Sheeps.search.open()">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 72"><path d="M 31 11 C 19.973 11 11 19.973 11 31 C 11 42.027 19.973 51 31 51 C 34.974166 51 38.672385 49.821569 41.789062 47.814453 L 54.726562 60.751953 C 56.390563 62.415953 59.088953 62.415953 60.751953 60.751953 C 62.415953 59.087953 62.415953 56.390563 60.751953 54.726562 L 47.814453 41.789062 C 49.821569 38.672385 51 34.974166 51 31 C 51 19.973 42.027 11 31 11 z M 31 19 C 37.616 19 43 24.384 43 31 C 43 37.616 37.616 43 31 43 C 24.384 43 19 37.616 19 31 C 19 24.384 24.384 19 31 19 z"/></svg>
|
||||
</button>
|
||||
@@ -224,6 +227,27 @@ const Sheeps = {
|
||||
</div>
|
||||
`;
|
||||
|
||||
let filter_selected = Number(filter)
|
||||
html += `
|
||||
<div class="filter" id="block-sheeps-list-filter" data-state="closed">
|
||||
<select title="Оберіть групу" onchange="Sheeps.filter.input(this.value)">
|
||||
<option value="0" ${Number(filter) == 0 ? 'selected' : ''}>Всі</option>
|
||||
<option value="1" ${Number(filter) === 1 ? 'selected' : ''}>Група 1</option>
|
||||
<option value="2" ${Number(filter) === 2 ? 'selected' : ''}>Група 2</option>
|
||||
<option value="3" ${Number(filter) === 3 ? 'selected' : ''}>Група 3</option>
|
||||
<option value="4" ${Number(filter) === 4 ? 'selected' : ''}>Група 4</option>
|
||||
<option value="5" ${Number(filter) === 5 ? 'selected' : ''}>Група 5</option>
|
||||
<option value="6" ${Number(filter) === 6 ? 'selected' : ''}>Група 6</option>
|
||||
<option value="7" ${Number(filter) === 7 ? 'selected' : ''}>Група 7</option>
|
||||
<option value="8" ${Number(filter) === 8 ? 'selected' : ''}>Група 8</option>
|
||||
</select>
|
||||
</div>
|
||||
`;
|
||||
|
||||
html += `
|
||||
<br>
|
||||
`;
|
||||
|
||||
const accessTemplate = (p) => {
|
||||
let perms = [];
|
||||
if (p.can_view_sheeps) perms.push("View Sheeps");
|
||||
@@ -242,7 +266,11 @@ const Sheeps = {
|
||||
};
|
||||
|
||||
for (const element of list) {
|
||||
if (search_value && !element.name.toLowerCase().includes(search_value)) {
|
||||
if (search && !element.name.toLowerCase().includes(search)) {
|
||||
continue; // пропустити, якщо ім'я не містить рядок пошуку
|
||||
}
|
||||
|
||||
if (filter && element.group_id !== Number(filter) && Number(filter) !== 0) {
|
||||
continue; // пропустити, якщо ім'я не містить рядок пошуку
|
||||
}
|
||||
|
||||
@@ -446,18 +474,42 @@ const Sheeps = {
|
||||
}, 10)
|
||||
}
|
||||
},
|
||||
filter: {
|
||||
open: () => {
|
||||
const sheepFilterForm = document.getElementById("block-sheeps-list-filter");
|
||||
const current = sheepFilterForm.dataset.state;
|
||||
|
||||
if(current === 'closed') Sheeps.search.close();
|
||||
sheepFilterForm.dataset.state = current === 'open' ? 'closed' : 'open';
|
||||
},
|
||||
close: () => {
|
||||
const sheepFilterForm = document.getElementById("block-sheeps-list-filter");
|
||||
sheepFilterForm.dataset.state = 'closed'
|
||||
},
|
||||
input: (value) => {
|
||||
console.log(value);
|
||||
|
||||
filter_value = value || "";
|
||||
Sheeps.sheeps_list.setHTML({filter: filter_value});
|
||||
}
|
||||
},
|
||||
search: {
|
||||
open: () => {
|
||||
const sheepSearchForm = document.getElementById("block-sheeps-list-search");
|
||||
sheepSearchForm.classList.toggle('active');
|
||||
const current = sheepSearchForm.dataset.state;
|
||||
|
||||
if(current === 'closed') Sheeps.filter.close();
|
||||
sheepSearchForm.dataset.state = current === 'open' ? 'closed' : 'open';
|
||||
},
|
||||
close: () => {
|
||||
const sheepSearchForm = document.getElementById("block-sheeps-list-search");
|
||||
sheepSearchForm.dataset.state = 'closed'
|
||||
},
|
||||
input: (value) => {
|
||||
console.log(value);
|
||||
|
||||
search_value = value?.trim()?.toLowerCase() || "";
|
||||
Sheeps.sheeps_list.setHTML(search_value);
|
||||
Sheeps.sheeps_list.setHTML({search: search_value});
|
||||
}
|
||||
},
|
||||
territory: {
|
||||
|
||||
@@ -43,6 +43,7 @@
|
||||
border-radius: calc(var(--border-radius) - 5px);
|
||||
position: relative;
|
||||
z-index: 10;
|
||||
margin-bottom: -10px;
|
||||
}
|
||||
|
||||
#block-sheeps-list>.header>h1 {
|
||||
@@ -83,11 +84,12 @@
|
||||
}
|
||||
|
||||
|
||||
#block-sheeps-list>.filter,
|
||||
#block-sheeps-list>.search {
|
||||
width: calc(100% - 30px);
|
||||
background-color: var(--PrimaryColor);
|
||||
border-radius: 0px 0px 10px 10px;
|
||||
margin: -12px 10px 20px 10px;
|
||||
border-radius: 10px;
|
||||
margin: -2px 10px 0px 10px;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
@@ -102,10 +104,22 @@
|
||||
}
|
||||
|
||||
|
||||
#block-sheeps-list>.filter[data-state="open"],
|
||||
#block-sheeps-list>.search[data-state="open"] {
|
||||
max-height: 60px;
|
||||
padding: 22px 5px 5px 5px;
|
||||
opacity: 1;
|
||||
border-radius: 0px 0px 10px 10px;
|
||||
}
|
||||
|
||||
#block-sheeps-list>.filter>select{
|
||||
width: 100%;
|
||||
padding: 0 5px;
|
||||
border-radius: calc(var(--border-radius) - 5px - 4px);
|
||||
height: 30px;
|
||||
background-color: var(--ColorThemes2);
|
||||
color: var(--ColorThemes3);
|
||||
font-size: var(--FontSize2);
|
||||
}
|
||||
|
||||
#block-sheeps-list>.search>input {
|
||||
|
||||
@@ -77,7 +77,7 @@
|
||||
.page-territory>.list-controls>button {
|
||||
display: flex;
|
||||
position: relative;
|
||||
background: var(--ColorThemes3);
|
||||
background: var(--PrimaryColor);
|
||||
font-size: 18px;
|
||||
cursor: pointer;
|
||||
min-width: 30px;
|
||||
@@ -93,7 +93,7 @@
|
||||
.page-territory>.list-controls>button>svg {
|
||||
width: 25px;
|
||||
height: 25px;
|
||||
fill: var(--ColorThemes0);
|
||||
fill: var(--PrimaryColorText);
|
||||
}
|
||||
|
||||
#page-territory-search {
|
||||
|
||||
Reference in New Issue
Block a user