'; return html; } function renderGrid() { let filtered = state.filter(b => { const matchesSearch = (b.name + ' ' + b.note + ' ' + b.category + ' ' + b.directory).toLowerCase().includes(searchTerm.toLowerCase()); const matchesDir = directoryFilter === "All" || b.directory === directoryFilter; const matchesCat = categoryFilter === "All" || b.category === categoryFilter; return matchesSearch && matchesDir && matchesCat; }); if (sortBy === "rating") { filtered.sort((a, b) => b.rating - a.rating); } else if (sortBy === "name") { filtered.sort((a, b) => a.name.localeCompare(b.name)); } else { filtered.sort((a, b) => a.directory.localeCompare(b.directory) || a.category.localeCompare(b.category) || a.name.localeCompare(b.name)); } countLine.textContent = filtered.length + ' of ' + state.length + ' listings shown'; if (filtered.length === 0) { grid.innerHTML = '
No listings match your search. Try a different term, or clear the directory/category filters.
'; return; } let html = ''; filtered.forEach((item) => { const realIdx = state.indexOf(item); html += '
'; html += '
' + item.name + '
' + item.directory + '' + item.category + '
'; html += starsHTML(item, realIdx); html += '
' + (item.rating > 0 ? item.rating + ' / 5' : 'Not yet rated — click to rate') + '
'; html += '
' + item.note + '
'; html += '
'; html += '
'; }); grid.innerHTML = html; grid.querySelectorAll('.stars').forEach(starGroup => { const idx = parseInt(starGroup.getAttribute('data-idx'), 10); starGroup.querySelectorAll('.star').forEach(star => { star.addEventListener('click', () => { const val = parseInt(star.getAttribute('data-star'), 10); state[idx].rating = (state[idx].rating === val) ? 0 : val; renderGrid(); }); }); }); } function renderAll() { renderChips(); renderSubchips(); renderGrid(); } document.getElementById('search-input').addEventListener('input', (e) => { searchTerm = e.target.value; const cursorPos = e.target.selectionStart; renderGrid(); const el = document.getElementById('search-input'); el.focus(); el.setSelectionRange(cursorPos, cursorPos); }); document.getElementById('sort-select').addEventListener('change', (e) => { sortBy = e.target.value; renderGrid(); }); document.getElementById('copy-btn').addEventListener('click', () => { let code = " const BUSINESSES = [\n"; let lastDir = null; state.forEach(b => { if (b.directory !== lastDir) { code += " // ============ " + b.directory + " ============\n"; lastDir = b.directory; } code += ' { name: "' + b.name.replace(/"/g, '\\"') + '", directory: "' + b.directory + '", category: "' + b.category.replace(/"/g, '\\"') + '", phone: "' + b.phone + '", note: "' + b.note.replace(/"/g, '\\"') + '", rating: ' + b.rating + ' },\n'; }); code += " ];"; const btn = document.getElementById('copy-btn'); navigator.clipboard.writeText(code).then(() => { btn.textContent = "Copied! Paste into the file"; setTimeout(() => { btn.textContent = "Copy updated list"; }, 2200); }).catch(() => { alert(code); }); }); renderAll(); })();