1( function () { 2 'use strict'; 3 4 document.querySelectorAll( '.section-resource-index' ).forEach( function ( section ) { 5 initResourceIndex( section ); 6 } ); 7 8 function initResourceIndex( section ) { 9 var grid = section.querySelector( '.ri-grid' ); 10 if ( ! grid ) return; 11 12 var searchInput = section.querySelector( '.ri-search' ); 13 var categorySelect = section.querySelector( '.ri-category' ); 14 var clearBtn = section.querySelector( '.ri-clear' ); 15 var countEl = section.querySelector( '.ri-count' ); 16 var noResults = section.querySelector( '.ri-no-results' ); 17 var sourceBtns = section.querySelectorAll( '.ri-source-btn' ); 18 var cards = grid.querySelectorAll( '.ri-card' ); 19 20 var activeSources = new Set(); 21 22 function filter() { 23 var searchVal = searchInput ? searchInput.value.toLowerCase().trim() : ''; 24 var categoryVal = categorySelect ? categorySelect.value : ''; 25 var visibleCount = 0; 26 27 cards.forEach( function ( card ) { 28 var titleMatch = ! searchVal || 29 ( card.dataset.title && card.dataset.title.indexOf( searchVal ) !== -1 ) || 30 ( card.dataset.excerpt && card.dataset.excerpt.indexOf( searchVal ) !== -1 ); 31 32 var sourceMatch = activeSources.size === 0; 33 if ( ! sourceMatch && card.dataset.sources ) { 34 var cardSources = card.dataset.sources.split( ' ' ); 35 for ( var i = 0; i < cardSources.length; i++ ) { 36 if ( activeSources.has( cardSources[ i ] ) ) { 37 sourceMatch = true; 38 break; 39 } 40 } 41 } 42 43 var categoryMatch = ! categoryVal; 44 if ( ! categoryMatch && card.dataset.categories ) { 45 categoryMatch = card.dataset.categories.split( ' ' ).indexOf( categoryVal ) !== -1; 46 } 47 48 var visible = titleMatch && sourceMatch && categoryMatch; 49 card.style.display = visible ? '' : 'none'; 50 if ( visible ) visibleCount++; 51 } ); 52 53 if ( countEl ) countEl.textContent = visibleCount; 54 if ( noResults ) noResults.style.display = visibleCount === 0 ? '' : 'none'; 55 } 56 57 if ( searchInput ) searchInput.addEventListener( 'input', filter ); 58 if ( categorySelect ) categorySelect.addEventListener( 'change', filter ); 59 60 sourceBtns.forEach( function ( btn ) { 61 btn.addEventListener( 'click', function () { 62 var src = this.dataset.source; 63 if ( activeSources.has( src ) ) { 64 activeSources.delete( src ); 65 this.classList.remove( 'is-active' ); 66 } else { 67 activeSources.add( src ); 68 this.classList.add( 'is-active' ); 69 } 70 filter(); 71 } ); 72 } ); 73 74 if ( clearBtn ) { 75 clearBtn.addEventListener( 'click', function () { 76 if ( searchInput ) searchInput.value = ''; 77 if ( categorySelect ) categorySelect.value = ''; 78 activeSources.clear(); 79 sourceBtns.forEach( function ( b ) { b.classList.remove( 'is-active' ); } ); 80 filter(); 81 } ); 82 } 83 } 84} )();
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.