fix: Manual accordion toggle without Bootstrap events
- Removed data-bs-toggle="collapse" to prevent Bootstrap interference - Handle click manually: toggle class "show" and update icon - Cookie stores 'expanded'/'collapsed' state per group - Chevron icon updates correctly on click
This commit is contained in:
parent
68cb135322
commit
32894447f3
|
|
@ -82,8 +82,8 @@
|
||||||
{% set groupSlug = groupName|lower|replace({' ': '-'}) %}
|
{% set groupSlug = groupName|lower|replace({' ': '-'}) %}
|
||||||
<div class="card mb-3 border-0 shadow-sm">
|
<div class="card mb-3 border-0 shadow-sm">
|
||||||
<div class="card-header text-white py-2 accordion-header"
|
<div class="card-header text-white py-2 accordion-header"
|
||||||
data-bs-toggle="collapse"
|
data-group="{{ groupSlug }}"
|
||||||
data-bs-target="#group-{{ loop.index }}"
|
data-target="#group-{{ loop.index }}"
|
||||||
style="cursor: pointer; background-color: {{ group.color|default('#6c757d') }};">
|
style="cursor: pointer; background-color: {{ group.color|default('#6c757d') }};">
|
||||||
<div class="d-flex justify-content-between align-items-center">
|
<div class="d-flex justify-content-between align-items-center">
|
||||||
<h5 class="mb-0">
|
<h5 class="mb-0">
|
||||||
|
|
@ -94,7 +94,7 @@
|
||||||
<i class="fas accordion-icon"></i>
|
<i class="fas accordion-icon"></i>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div id="group-{{ loop.index }}" class="collapse" data-group-slug="{{ groupSlug }}">
|
<div id="group-{{ loop.index }}" class="collapse" data-group="{{ groupSlug }}">
|
||||||
<div class="card-body p-2">
|
<div class="card-body p-2">
|
||||||
<div class="row g-2">
|
<div class="row g-2">
|
||||||
{% for server in group.servers %}
|
{% for server in group.servers %}
|
||||||
|
|
@ -201,66 +201,59 @@
|
||||||
<script>
|
<script>
|
||||||
(function() {
|
(function() {
|
||||||
const COOKIE_NAME = 'dashboard_accordion';
|
const COOKIE_NAME = 'dashboard_accordion';
|
||||||
|
let accordionState = {};
|
||||||
|
|
||||||
function getAccordionState() {
|
function getCookie(name) {
|
||||||
const cookies = document.cookie.split(';');
|
const match = document.cookie.match(new RegExp('(^| )' + name + '=([^;]+)'));
|
||||||
for (let c of cookies) {
|
return match ? JSON.parse(decodeURIComponent(match[2])) : {};
|
||||||
c = c.trim();
|
|
||||||
if (c.startsWith(COOKIE_NAME + '=')) {
|
|
||||||
try {
|
|
||||||
return JSON.parse(decodeURIComponent(c.substring(COOKIE_NAME.length + 1)));
|
|
||||||
} catch(e) {
|
|
||||||
console.log('Cookie parse error:', e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return {};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function saveAccordionState(state) {
|
function saveCookie(state) {
|
||||||
document.cookie = COOKIE_NAME + '=' + encodeURIComponent(JSON.stringify(state)) +
|
document.cookie = COOKIE_NAME + '=' + encodeURIComponent(JSON.stringify(state)) +
|
||||||
'; path=/; max-age=' + (30 * 24 * 60 * 60);
|
'; path=/; max-age=' + (30 * 24 * 60 * 60);
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateIcon(header, isOpen) {
|
|
||||||
const icon = header ? header.querySelector('.accordion-icon') : null;
|
|
||||||
if (icon) {
|
|
||||||
icon.className = isOpen ? 'fas fa-chevron-up' : 'fas fa-chevron-down';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
document.addEventListener('DOMContentLoaded', function() {
|
document.addEventListener('DOMContentLoaded', function() {
|
||||||
const state = getAccordionState();
|
accordionState = getCookie(COOKIE_NAME);
|
||||||
console.log('Initial state from cookies:', state);
|
|
||||||
|
|
||||||
// Инициализация иконок из cookies
|
// Инициализация: устанавливаем начальное состояние из cookies
|
||||||
document.querySelectorAll('.accordion-header').forEach(header => {
|
document.querySelectorAll('.accordion-header').forEach(function(header) {
|
||||||
const groupId = header.dataset.groupSlug;
|
const groupId = header.dataset.group;
|
||||||
const target = header.dataset.bsTarget;
|
const targetId = header.dataset.target;
|
||||||
const isOpen = state[groupId] === 'open';
|
const target = document.querySelector(targetId);
|
||||||
console.log('Group:', groupId, 'isOpen:', isOpen);
|
|
||||||
|
|
||||||
updateIcon(header, isOpen);
|
if (target) {
|
||||||
|
if (accordionState[groupId] === 'collapsed') {
|
||||||
|
target.classList.remove('show');
|
||||||
|
header.querySelector('.accordion-icon').className = 'fas fa-chevron-down';
|
||||||
|
} else {
|
||||||
|
// По умолчанию открыто
|
||||||
|
target.classList.add('show');
|
||||||
|
header.querySelector('.accordion-icon').className = 'fas fa-chevron-up';
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Слушаем события Bootstrap collapse
|
// Клик на заголовке accordion
|
||||||
document.querySelectorAll('.collapse').forEach(el => {
|
document.querySelectorAll('.accordion-header').forEach(function(header) {
|
||||||
el.addEventListener('hidden.bs.collapse', function() {
|
header.addEventListener('click', function(e) {
|
||||||
const groupId = this.dataset.groupSlug;
|
const groupId = this.dataset.group;
|
||||||
state[groupId] = 'closed';
|
const targetId = this.dataset.target;
|
||||||
saveAccordionState(state);
|
const target = document.querySelector(targetId);
|
||||||
console.log('Hidden:', groupId, 'state:', state);
|
const icon = this.querySelector('.accordion-icon');
|
||||||
const header = document.querySelector('.accordion-header[data-bs-target="#' + this.id + '"]');
|
|
||||||
updateIcon(header, false);
|
|
||||||
});
|
|
||||||
|
|
||||||
el.addEventListener('shown.bs.collapse', function() {
|
if (target.classList.contains('show')) {
|
||||||
const groupId = this.dataset.groupSlug;
|
// Сворачиваем
|
||||||
state[groupId] = 'open';
|
target.classList.remove('show');
|
||||||
saveAccordionState(state);
|
icon.className = 'fas fa-chevron-down';
|
||||||
console.log('Shown:', groupId, 'state:', state);
|
accordionState[groupId] = 'collapsed';
|
||||||
const header = document.querySelector('.accordion-header[data-bs-target="#' + this.id + '"]');
|
} else {
|
||||||
updateIcon(header, true);
|
// Разворачиваем
|
||||||
|
target.classList.add('show');
|
||||||
|
icon.className = 'fas fa-chevron-up';
|
||||||
|
accordionState[groupId] = 'expanded';
|
||||||
|
}
|
||||||
|
saveCookie(accordionState);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue