- Introduced a new 'shops' category in the build script and README. - Implemented badge filtering in the filter functionality, allowing users to filter entries by badge.
213 lines
6.4 KiB
JavaScript
213 lines
6.4 KiB
JavaScript
// Ursprung Sverige - Filtering functionality
|
|
|
|
(function() {
|
|
'use strict';
|
|
|
|
const categoryFilter = document.getElementById('category-filter');
|
|
const regionFilter = document.getElementById('region-filter');
|
|
const badgeFilter = document.getElementById('badge-filter');
|
|
const tagFilter = document.getElementById('tag-filter');
|
|
const searchInput = document.getElementById('search-input');
|
|
const clearFiltersBtn = document.getElementById('clear-filters');
|
|
const entriesGrid = document.getElementById('entries-grid');
|
|
const visibleCount = document.getElementById('visible-count');
|
|
const noResults = document.getElementById('no-results');
|
|
|
|
if (!entriesGrid) return;
|
|
|
|
const entries = Array.from(entriesGrid.querySelectorAll('.entry-card'));
|
|
|
|
// Update URL with current filter state
|
|
function updateURL() {
|
|
const params = new URLSearchParams();
|
|
|
|
if (categoryFilter?.value) {
|
|
params.set('category', categoryFilter.value);
|
|
}
|
|
if (regionFilter?.value) {
|
|
params.set('region', regionFilter.value);
|
|
}
|
|
if (badgeFilter?.value) {
|
|
params.set('badge', badgeFilter.value);
|
|
}
|
|
if (tagFilter?.value) {
|
|
params.set('tag', tagFilter.value);
|
|
}
|
|
if (searchInput?.value.trim()) {
|
|
params.set('search', searchInput.value.trim());
|
|
}
|
|
|
|
const queryString = params.toString();
|
|
const newURL = queryString
|
|
? `${window.location.pathname}?${queryString}`
|
|
: window.location.pathname;
|
|
|
|
window.history.replaceState({}, '', newURL);
|
|
}
|
|
|
|
// Apply filters from URL on page load
|
|
function applyFiltersFromURL() {
|
|
const params = new URLSearchParams(window.location.search);
|
|
|
|
if (params.has('category') && categoryFilter) {
|
|
categoryFilter.value = params.get('category');
|
|
}
|
|
if (params.has('region') && regionFilter) {
|
|
regionFilter.value = params.get('region');
|
|
}
|
|
if (params.has('badge') && badgeFilter) {
|
|
badgeFilter.value = params.get('badge');
|
|
}
|
|
if (params.has('tag') && tagFilter) {
|
|
tagFilter.value = params.get('tag');
|
|
}
|
|
if (params.has('search') && searchInput) {
|
|
searchInput.value = params.get('search');
|
|
}
|
|
|
|
filterEntries(false); // Don't update URL on initial load
|
|
}
|
|
|
|
function filterEntries(shouldUpdateURL = true) {
|
|
const categoryValue = categoryFilter?.value.toLowerCase() || '';
|
|
const regionValue = regionFilter?.value.toLowerCase() || '';
|
|
const badgeValue = badgeFilter?.value.toLowerCase() || '';
|
|
const tagValue = tagFilter?.value.toLowerCase() || '';
|
|
const searchValue = searchInput?.value.toLowerCase().trim() || '';
|
|
|
|
let visibleEntries = 0;
|
|
|
|
entries.forEach(entry => {
|
|
const entryCategory = (entry.dataset.category || '').toLowerCase();
|
|
const entryRegion = (entry.dataset.region || '').toLowerCase();
|
|
const entryBadge = (entry.dataset.badge || '').toLowerCase();
|
|
const entryTags = (entry.dataset.tags || '').toLowerCase().split(',');
|
|
const entryText = entry.textContent.toLowerCase();
|
|
|
|
const matchesCategory = !categoryValue || entryCategory === categoryValue;
|
|
const matchesRegion = !regionValue || entryRegion === regionValue;
|
|
const matchesBadge = !badgeValue || entryBadge === badgeValue;
|
|
const matchesTag = !tagValue || entryTags.includes(tagValue);
|
|
const matchesSearch = !searchValue || entryText.includes(searchValue);
|
|
|
|
const isVisible = matchesCategory && matchesRegion && matchesBadge && matchesTag && matchesSearch;
|
|
|
|
entry.hidden = !isVisible;
|
|
if (isVisible) visibleEntries++;
|
|
});
|
|
|
|
if (visibleCount) {
|
|
visibleCount.textContent = visibleEntries;
|
|
}
|
|
|
|
if (noResults) {
|
|
noResults.hidden = visibleEntries > 0;
|
|
}
|
|
|
|
if (entriesGrid) {
|
|
entriesGrid.hidden = visibleEntries === 0;
|
|
}
|
|
|
|
updateClearButtonVisibility();
|
|
|
|
if (shouldUpdateURL) {
|
|
updateURL();
|
|
}
|
|
}
|
|
|
|
function updateClearButtonVisibility() {
|
|
if (!clearFiltersBtn) return;
|
|
|
|
const hasFilters =
|
|
(categoryFilter?.value || '') !== '' ||
|
|
(regionFilter?.value || '') !== '' ||
|
|
(badgeFilter?.value || '') !== '' ||
|
|
(tagFilter?.value || '') !== '' ||
|
|
(searchInput?.value || '') !== '';
|
|
|
|
clearFiltersBtn.hidden = !hasFilters;
|
|
}
|
|
|
|
function clearFilters() {
|
|
if (categoryFilter) categoryFilter.value = '';
|
|
if (regionFilter) regionFilter.value = '';
|
|
if (badgeFilter) badgeFilter.value = '';
|
|
if (tagFilter) tagFilter.value = '';
|
|
if (searchInput) searchInput.value = '';
|
|
|
|
filterEntries(); // This will also clear the URL
|
|
}
|
|
|
|
// Handle clicking on filter buttons in cards
|
|
function handleFilterClick(e) {
|
|
const btn = e.target.closest('.filter-btn');
|
|
if (!btn) return;
|
|
|
|
const filterType = btn.dataset.filterType;
|
|
const filterValue = btn.dataset.filterValue;
|
|
|
|
if (filterType === 'category' && categoryFilter) {
|
|
categoryFilter.value = filterValue;
|
|
} else if (filterType === 'region' && regionFilter) {
|
|
regionFilter.value = filterValue;
|
|
} else if (filterType === 'badge' && badgeFilter) {
|
|
badgeFilter.value = filterValue;
|
|
} else if (filterType === 'tag' && tagFilter) {
|
|
tagFilter.value = filterValue;
|
|
}
|
|
|
|
filterEntries();
|
|
|
|
// Scroll to top to see filtered results
|
|
window.scrollTo({ top: 0, behavior: 'smooth' });
|
|
}
|
|
|
|
// Handle browser back/forward
|
|
window.addEventListener('popstate', () => {
|
|
applyFiltersFromURL();
|
|
});
|
|
|
|
// Debounce for search input
|
|
function debounce(func, wait) {
|
|
let timeout;
|
|
return function(...args) {
|
|
clearTimeout(timeout);
|
|
timeout = setTimeout(() => func.apply(this, args), wait);
|
|
};
|
|
}
|
|
|
|
// Event listeners
|
|
if (categoryFilter) {
|
|
categoryFilter.addEventListener('change', () => filterEntries());
|
|
}
|
|
|
|
if (regionFilter) {
|
|
regionFilter.addEventListener('change', () => filterEntries());
|
|
}
|
|
|
|
if (badgeFilter) {
|
|
badgeFilter.addEventListener('change', () => filterEntries());
|
|
}
|
|
|
|
if (tagFilter) {
|
|
tagFilter.addEventListener('change', () => filterEntries());
|
|
}
|
|
|
|
if (searchInput) {
|
|
searchInput.addEventListener('input', debounce(() => filterEntries(), 300));
|
|
}
|
|
|
|
if (clearFiltersBtn) {
|
|
clearFiltersBtn.addEventListener('click', clearFilters);
|
|
}
|
|
|
|
// Delegate click events for filter buttons in cards
|
|
if (entriesGrid) {
|
|
entriesGrid.addEventListener('click', handleFilterClick);
|
|
}
|
|
|
|
// Apply URL filters on load
|
|
applyFiltersFromURL();
|
|
updateClearButtonVisibility();
|
|
})();
|