Add sturdy-slab image asset to the crafts directory
This commit is contained in:
@@ -331,6 +331,101 @@ const topLinks = [
|
||||
});
|
||||
};
|
||||
|
||||
const normalizeCraftSearch = (value) =>
|
||||
stripDecorativeSymbols(value)
|
||||
.toLowerCase()
|
||||
.replace(/ё/g, 'е')
|
||||
.replace(/\s+/g, ' ')
|
||||
.trim();
|
||||
|
||||
const bindCraftCatalogFilters = () => {
|
||||
const catalogNodes = document.querySelectorAll('[data-craft-catalog]');
|
||||
|
||||
catalogNodes.forEach((catalogNode) => {
|
||||
if (!(catalogNode instanceof HTMLElement)) return;
|
||||
if (catalogNode.dataset.craftBound === 'true') return;
|
||||
catalogNode.dataset.craftBound = 'true';
|
||||
|
||||
const searchInput = catalogNode.querySelector('[data-craft-search]');
|
||||
const filterButtons = Array.from(catalogNode.querySelectorAll('[data-craft-filter]')).filter(
|
||||
(node) => node instanceof HTMLButtonElement
|
||||
);
|
||||
const groupNodes = Array.from(catalogNode.querySelectorAll('[data-craft-group]')).filter(
|
||||
(node) => node instanceof HTMLElement
|
||||
);
|
||||
const emptyState = catalogNode.querySelector('[data-craft-empty]');
|
||||
|
||||
let activeFilter = 'all';
|
||||
const activeButton = filterButtons.find(
|
||||
(buttonNode) =>
|
||||
buttonNode.classList.contains('is-active') ||
|
||||
buttonNode.getAttribute('aria-pressed') === 'true'
|
||||
);
|
||||
|
||||
if (activeButton?.dataset.craftFilter) {
|
||||
activeFilter = activeButton.dataset.craftFilter;
|
||||
}
|
||||
|
||||
const applyFilters = () => {
|
||||
const searchQuery =
|
||||
searchInput instanceof HTMLInputElement ? normalizeCraftSearch(searchInput.value) : '';
|
||||
|
||||
filterButtons.forEach((buttonNode) => {
|
||||
const isActive = (buttonNode.dataset.craftFilter || 'all') === activeFilter;
|
||||
buttonNode.classList.toggle('is-active', isActive);
|
||||
buttonNode.setAttribute('aria-pressed', String(isActive));
|
||||
});
|
||||
|
||||
let visibleCount = 0;
|
||||
|
||||
groupNodes.forEach((groupNode) => {
|
||||
const defaultCategory = groupNode.dataset.craftCategory || '';
|
||||
const itemNodes = Array.from(groupNode.querySelectorAll('[data-craft-item]')).filter(
|
||||
(node) => node instanceof HTMLElement
|
||||
);
|
||||
|
||||
let groupVisibleCount = 0;
|
||||
|
||||
itemNodes.forEach((itemNode) => {
|
||||
const itemCategory = itemNode.dataset.craftCategory || defaultCategory;
|
||||
const itemName =
|
||||
itemNode.dataset.craftName || itemNode.querySelector('h3')?.textContent || '';
|
||||
const normalizedName = normalizeCraftSearch(itemName);
|
||||
const matchesCategory = activeFilter === 'all' || itemCategory === activeFilter;
|
||||
const matchesSearch = !searchQuery || normalizedName.includes(searchQuery);
|
||||
const isVisible = matchesCategory && matchesSearch;
|
||||
|
||||
itemNode.hidden = !isVisible;
|
||||
if (isVisible) groupVisibleCount += 1;
|
||||
});
|
||||
|
||||
groupNode.hidden = groupVisibleCount === 0;
|
||||
visibleCount += groupVisibleCount;
|
||||
});
|
||||
|
||||
if (emptyState instanceof HTMLElement) {
|
||||
emptyState.hidden = visibleCount > 0;
|
||||
}
|
||||
};
|
||||
|
||||
filterButtons.forEach((buttonNode) => {
|
||||
buttonNode.addEventListener('click', () => {
|
||||
const nextFilter = buttonNode.dataset.craftFilter || 'all';
|
||||
if (nextFilter === activeFilter) return;
|
||||
activeFilter = nextFilter;
|
||||
applyFilters();
|
||||
});
|
||||
});
|
||||
|
||||
if (searchInput instanceof HTMLInputElement) {
|
||||
searchInput.addEventListener('input', applyFilters);
|
||||
searchInput.addEventListener('search', applyFilters);
|
||||
}
|
||||
|
||||
applyFilters();
|
||||
});
|
||||
};
|
||||
|
||||
const enhanceSidebarGroupLinks = () => {
|
||||
const targets = [{ label: 'Алкоголь', href: '/alcohol/' }];
|
||||
const labelNodes = document.querySelectorAll('.sidebar-content details > summary .group-label .large');
|
||||
@@ -407,6 +502,7 @@ const topLinks = [
|
||||
decorateSectionIcons();
|
||||
annotateLinkDestinations();
|
||||
bindCopyIpChips();
|
||||
bindCraftCatalogFilters();
|
||||
setReadProgress();
|
||||
window.addEventListener('scroll', setReadProgress, { passive: true });
|
||||
window.addEventListener('resize', setReadProgress);
|
||||
@@ -425,6 +521,7 @@ const topLinks = [
|
||||
decorateSectionIcons();
|
||||
annotateLinkDestinations();
|
||||
bindCopyIpChips();
|
||||
bindCraftCatalogFilters();
|
||||
setReadProgress();
|
||||
});
|
||||
</script>
|
||||
|
||||
Reference in New Issue
Block a user