1// Showcase filter functionality for filtering example sites by category 2document.addEventListener('DOMContentLoaded', function() { 3 const filterButtons = document.querySelectorAll('.showcase-filter-btn'); 4 const examplesGrid = document.querySelector('.examples-grid'); 5 6 if (!filterButtons.length || !examplesGrid) return; // Exit if elements not found 7 8 // Map data-filter values to showcaseSites keys 9 const filterToConfigKey = { 10 'default': 'default', 11 'small-business': 'smallBusiness', 12 'nonprofit': 'nonprofit', 13 'personal': 'personal' 14 }; 15 16 // Map config keys to image folder names 17 const configKeyToFolder = { 18 'default': 'default', 19 'smallBusiness': 'small-business', 20 'nonprofit': 'nonprofit', 21 'personal': 'personal' 22 }; 23 24 // Build a single card HTML string 25 function buildCardHTML(site, category) { 26 const folderName = configKeyToFolder[category] || category; 27 return ` 28 <div class="example-card"> 29 <a href="${site.url}" target="_blank" rel="noopener" class="preview-link"> 30 <div class="example-iframe-container"> 31 <div class="site-preview"> 32 <img src="/images/previews/${folderName}/${site.image}" alt="${site.name} website" class="preview-image" loading="lazy"> 33 <div class="preview-overlay"> 34 <span>Visit Site â</span> 35 </div> 36 </div> 37 </div> 38 </a> 39 <div class="example-info"> 40 <h4 class="example-site-title">${site.name}</h4> 41 <a href="${site.url}" target="_blank" rel="noopener">View Site â</a> 42 <a href="#" class="use-template-btn" data-analytics-event="template" data-site="${site.url}">Use as template â</a> 43 </div> 44 </div> 45 `; 46 } 47 48 // Attach click handlers to "Use as template" buttons 49 function attachTemplateHandlers() { 50 const templateButtons = examplesGrid.querySelectorAll('.use-template-btn'); 51 templateButtons.forEach(function(btn) { 52 btn.addEventListener('click', function(e) { 53 e.preventDefault(); 54 const siteUrl = this.getAttribute('data-site'); 55 if (siteUrl) { 56 const inputBar = document.querySelector('#homepage-input-bar textarea, #homepage-input-bar input'); 57 if (inputBar) { 58 inputBar.value = 'Replicate this website ' + siteUrl; 59 inputBar.focus(); 60 inputBar.dispatchEvent(new Event('input', { bubbles: true })); 61 window.scrollTo({ top: 0, behavior: 'smooth' }); 62 } 63 } 64 }); 65 }); 66 } 67 68 // Rebuild the grid with sites from the specified category 69 function rebuildGrid(category) { 70 if (typeof showcaseSites === 'undefined' || !showcaseSites[category]) { 71 console.warn('showcaseSites not found or category missing:', category); 72 return; 73 } 74 75 const sites = showcaseSites[category]; 76 let html = ''; 77 sites.forEach(function(site) { 78 html += buildCardHTML(site, category); 79 }); 80 81 examplesGrid.innerHTML = html; 82 attachTemplateHandlers(); 83 } 84 85 // Handle filter button clicks 86 filterButtons.forEach(function(btn) { 87 btn.addEventListener('click', function() { 88 const filterType = this.getAttribute('data-filter'); 89 const configKey = filterToConfigKey[filterType] || 'default'; 90 91 // Update active state on buttons 92 filterButtons.forEach(function(b) { 93 b.classList.remove('active'); 94 }); 95 this.classList.add('active'); 96 97 // Fade out current cards 98 examplesGrid.style.transition = 'opacity 0.3s ease'; 99 examplesGrid.style.opacity = '0'; 100 101 // After fade out, rebuild and fade in 102 setTimeout(function() { 103 rebuildGrid(configKey); 104 examplesGrid.style.opacity = '1'; 105 }, 300); 106 }); 107 }); 108 109 // Attach handlers to initial template buttons on page load 110 attachTemplateHandlers(); 111});
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.