1document.addEventListener("DOMContentLoaded", function() { 2 3 const typeFilter = document.getElementById("filter-type"); 4 const categoryFilter = document.getElementById("filter-category"); 5 const tagFilter = document.getElementById("filter-tag"); 6 const yearFilter = document.getElementById("filter-year"); 7 const textFilter = document.getElementById("filter-text"); 8 const refreshBtn = document.getElementById("refresh-filters"); 9 const news = document.querySelectorAll(".news-feed-article"); 10 const resultsCount = document.getElementById("results-count"); 11 12 function applyFilters() { 13 let visibleCount = 0; 14 15 news.forEach(post => { 16 const type = post.dataset.type; 17 const category = post.dataset.category.split(' '); 18 const tag = post.dataset.tag.split(' '); 19 const year = post.dataset.year; 20 const title = post.dataset.title; 21 22 const typeVal = typeFilter.value; 23 const categoryVal = categoryFilter.value; 24 const tagVal = tagFilter.value; 25 const yearVal = yearFilter.value; 26 const textVal = textFilter.value.toLowerCase(); 27 28 let show = true; 29 30 if (typeVal && type !== typeVal) show = false; 31 if (categoryVal && !category.includes(categoryVal)) show = false; 32 if (tagVal && !tag.includes(tagVal)) show = false; 33 if (yearVal && year !== yearVal) show = false; 34 if (textVal && !title.includes(textVal)) show = false; 35 36 post.style.display = show ? "block" : "none"; 37 if (show) visibleCount++; 38 }); 39 40 resultsCount.textContent = visibleCount + " items found"; 41 42 // Update dropdowns dynamically 43 updateFilterDropdowns(); 44 45 // Show/hide no-results message 46 const noResultsMessage = document.getElementById("no-results-message"); 47 noResultsMessage.style.display = visibleCount === 0 ? "block" : "none"; 48 } 49 50 51 function updateFilterDropdowns() { 52 const visiblePosts = Array.from(news).filter(post => post.style.display !== "none"); 53 54 // --- Categories --- 55 const visibleCategories = new Set(); 56 visiblePosts.forEach(post => post.dataset.category.split(' ').forEach(c => visibleCategories.add(c))); 57 Array.from(categoryFilter.options).forEach(opt => { 58 opt.style.display = (opt.value === "" || visibleCategories.has(opt.value)) ? "block" : "none"; 59 }); 60 61 // --- Tags --- 62 const visibleTags = new Set(); 63 visiblePosts.forEach(post => post.dataset.tag.split(' ').forEach(t => visibleTags.add(t))); 64 Array.from(tagFilter.options).forEach(opt => { 65 opt.style.display = (opt.value === "" || visibleTags.has(opt.value)) ? "block" : "none"; 66 }); 67 68 // --- Years --- 69 const visibleYears = new Set(); 70 visiblePosts.forEach(post => visibleYears.add(post.dataset.year)); 71 Array.from(yearFilter.options).forEach(opt => { 72 opt.style.display = (opt.value === "" || visibleYears.has(opt.value)) ? "block" : "none"; 73 }); 74 } 75 76 77 typeFilter.addEventListener("change", applyFilters); 78 categoryFilter.addEventListener("change", applyFilters); 79 tagFilter.addEventListener("change", applyFilters); 80 yearFilter.addEventListener("change", applyFilters); 81 textFilter.addEventListener("input", applyFilters); 82 83 refreshBtn.addEventListener("click", function() { 84 typeFilter.value = ""; 85 categoryFilter.value = ""; 86 tagFilter.value = ""; 87 yearFilter.value = ""; 88 textFilter.value = ""; 89 applyFilters(); 90 }); 91 92 applyFilters(); 93});
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.