/* DWK vNext – Wijnhuis filters/sort (lightweight, no deps) */ (function () { const winesWrap = document.querySelector('[data-dwk-wines]'); if (!winesWrap) return; const drawer = document.querySelector('[data-dwk-drawer]'); const openBtn = document.querySelector('[data-dwk-open-filters]'); const closeBtn = document.querySelector('[data-dwk-close-filters]'); const applyBtn = document.querySelector('[data-dwk-apply]'); const clearBtn = document.querySelector('[data-dwk-clear]'); const sortSel = document.querySelector('[data-dwk-sort]'); const countEl = document.querySelector('[data-dwk-count]'); const noResults = document.querySelector('[data-dwk-noresults]'); const yearMinInput = document.querySelector('[data-dwk-year-min]'); const yearMaxInput = document.querySelector('[data-dwk-year-max]'); const cards = Array.from(winesWrap.querySelectorAll('.dwk-wine')); function getCheckedValues(type) { return Array.from(document.querySelectorAll(`input[data-dwk-filter="${type}"]:checked`)) .map(i => i.value); } function getTopicOn(type) { const el = document.querySelector(`input[data-dwk-filter="${type}"]`); return el ? el.checked : false; } function openDrawer() { if (!drawer) return; drawer.hidden = false; document.body.style.overflow = 'hidden'; } function closeDrawer() { if (!drawer) return; drawer.hidden = true; document.body.style.overflow = ''; } function parseIntSafe(v) { const n = parseInt(v, 10); return Number.isFinite(n) ? n : 0; } function parseFloatSafe(v) { const n = parseFloat(v); return Number.isFinite(n) ? n : 0; } function matchesAny(val, selected) { if (!selected.length) return true; return selected.includes(val); } function applyFilters() { const colors = getCheckedValues('color'); const countries = getCheckedValues('country'); const regions = getCheckedValues('region'); const yearMin = yearMinInput ? parseIntSafe(yearMinInput.value) : 0; const yearMax = yearMaxInput ? parseIntSafe(yearMaxInput.value) : 0; const reqAppearance = getTopicOn('appearance'); const reqNosePalate = getTopicOn('nosepalate'); const reqAi = getTopicOn('ai'); let visibleCount = 0; cards.forEach(card => { const c = card.dataset; const year = parseIntSafe(c.year); const okYearMin = yearMin ? (year && year >= yearMin) : true; const okYearMax = yearMax ? (year && year <= yearMax) : true; const okColor = matchesAny((c.color || ''), colors); const okCountry = matchesAny((c.country || ''), countries); const okRegion = matchesAny((c.region || ''), regions); const okAppearance = reqAppearance ? (c.appearance === '1') : true; const okNose = reqNosePalate ? (c.nosepalate === '1') : true; const okAi = reqAi ? (c.ai === '1') : true; const ok = okYearMin && okYearMax && okColor && okCountry && okRegion && okAppearance && okNose && okAi; card.style.display = ok ? '' : 'none'; if (ok) visibleCount++; }); if (countEl) countEl.textContent = String(visibleCount); if (noResults) noResults.hidden = visibleCount !== 0; } function sortCards() { const mode = sortSel ? sortSel.value : 'new'; const visible = cards.filter(c => c.style.display !== 'none'); const hidden = cards.filter(c => c.style.display === 'none'); function cmp(a, b) { const da = a.dataset, db = b.dataset; const dateA = parseIntSafe(da.date), dateB = parseIntSafe(db.date); const priceA = parseFloatSafe(da.price), priceB = parseFloatSafe(db.price); const scoreA = parseFloatSafe(da.score), scoreB = parseFloatSafe(db.score); const yearA = parseIntSafe(da.year), yearB = parseIntSafe(db.year); switch (mode) { case 'old': return dateA - dateB; case 'score': return scoreB - scoreA || dateB - dateA; case 'price_asc': return priceA - priceB || dateB - dateA; case 'price_desc': return priceB - priceA || dateB - dateA; case 'year_asc': return yearA - yearB || dateB - dateA; case 'year_desc': return yearB - yearA || dateB - dateA; case 'new': default: return dateB - dateA; } } visible.sort(cmp); // Re-append in order: visible sorted, then hidden (keeps DOM stable) const frag = document.createDocumentFragment(); visible.forEach(el => frag.appendChild(el)); hidden.forEach(el => frag.appendChild(el)); winesWrap.appendChild(frag); } function applyAll() { applyFilters(); sortCards(); } function clearAll() { document.querySelectorAll('input[data-dwk-filter]').forEach(i => (i.checked = false)); if (yearMinInput) yearMinInput.value = ''; if (yearMaxInput) yearMaxInput.value = ''; applyAll(); } // Events if (openBtn) openBtn.addEventListener('click', openDrawer); if (closeBtn) closeBtn.addEventListener('click', closeDrawer); if (drawer) drawer.addEventListener('click', (e) => { if (e.target === drawer) closeDrawer(); }); if (applyBtn) applyBtn.addEventListener('click', () => { applyAll(); closeDrawer(); }); if (clearBtn) clearBtn.addEventListener('click', clearAll); if (sortSel) sortSel.addEventListener('change', sortCards); // Keyboard document.addEventListener('keydown', (e) => { if (e.key === 'Escape' && drawer && !drawer.hidden) closeDrawer(); }); // Initial applyAll(); })(); XML-RPC server accepts POST requests only.