1document.addEventListener('alpine:init', () => { 2 Alpine.data('filters', (productUid, rawShingles) => ({ 3 productUid: productUid, 4 blends: [], 5 selectedBlends: [], 6 shingles: {}, 7 favorites: {}, 8 cookieName: `global-product-color-favorites`, 9 activePlant: window.getCookie('atlas_active_plant') || null, 10 activePlantTitle: window.getCookie('atlas_active_plant_title') || '', 11 zipInput: window.getCookie('atlas_active_zip') || '', 12 zipError: '', 13 14 init () { 15 const shingles = JSON.parse(rawShingles) 16 17 this.shingles = shingles.reduce((acc, i) => { 18 acc[i.uid] = i 19 return acc 20 }, {}) 21 22 this.restoreFavorites() 23 }, 24 25 toggleFav (uid) { 26 if (uid in this.favorites) { 27 delete this.favorites[uid] 28 } else { 29 this.favorites[uid] = this.shingles[uid].title 30 } 31 32 this.persistFavoritesInCookies() 33 }, 34 35 restoreFavorites () { 36 const cookie = window.getCookie(this.cookieName) 37 38 if (!cookie.length) { 39 return 40 } 41 42 const favs = JSON.parse(cookie) 43 favs.map(i => { 44 if (i in this.shingles) { 45 this.favorites[i] = this.shingles[i]?.title 46 } else { 47 delete this.favorites[i] 48 } 49 }, {}) 50 this.persistFavoritesInCookies() 51 }, 52 53 persistFavoritesInCookies () { 54 window.setCookie( 55 this.cookieName, 56 JSON.stringify(Object.keys(this.favorites)), 57 30 58 ) 59 }, 60 61 canDisplay(blends) { 62 blends = JSON.parse(blends) 63 return !this.selectedBlends.length || blends.some(b => this.selectedBlends.includes(b)) 64 }, 65 66 _zipDebounce: null, 67 isSearching: false, 68 69 onZipInput() { 70 clearTimeout(this._zipDebounce); 71 this.zipError = ''; 72 const zip = (this.zipInput || '').replace(/\D/g, ''); 73 this.zipInput = zip; 74 75 if (zip.length === 0) { 76 this.clearLocation(); 77 return; 78 } 79 80 if (zip.length < 5 && this.activePlant) { 81 this.activePlant = null; 82 this.activePlantTitle = ''; 83 window.setCookie('atlas_active_plant', '', -1); 84 window.setCookie('atlas_active_plant_title', '', -1); 85 window.setCookie('atlas_active_zip', '', -1); 86 } 87 88 if (zip.length >= 5) { 89 this._zipDebounce = setTimeout(() => this.lookupZip(), 150); 90 } 91 }, 92 93 async lookupZip() { 94 this.zipError = ''; 95 const zip = (this.zipInput || '').trim().slice(0, 5); 96 if (zip.length < 5) return; 97 this.isSearching = true; 98 try { 99 const res = await fetch(`/api/zip-lookup/${zip}`); 100 const data = await res.json(); 101 if (data.success && data.plant) { 102 this.activePlant = data.plant.slug; 103 this.activePlantTitle = data.plant.title; 104 window.setSessionCookie('atlas_active_plant', data.plant.slug); 105 window.setSessionCookie('atlas_active_plant_title', data.plant.title); 106 window.setSessionCookie('atlas_active_zip', zip); 107 } else if (data.success) { 108 // ZIP resolved to no active plant â silently fall back to All Locations 109 this.activePlant = null; 110 this.activePlantTitle = ''; 111 window.setCookie('atlas_active_plant', '', -1); 112 window.setCookie('atlas_active_plant_title', '', -1); 113 window.setCookie('atlas_active_zip', '', -1); 114 } else { 115 this.zipError = data.error || 'No results found for this ZIP code.'; 116 } 117 } catch (e) { 118 this.zipError = 'Unable to look up location. Please try again.'; 119 } finally { 120 this.isSearching = false;
121 } 122 }, 123 124 clearLocation() { 125 this.activePlant = null; 126 this.activePlantTitle = ''; 127 this.zipInput = ''; 128 this.zipError = ''; 129 window.setCookie('atlas_active_plant', '', -1); 130 window.setCookie('atlas_active_plant_title', '', -1); 131 window.setCookie('atlas_active_zip', '', -1); 132 }, 133 134 getColorImage(nationalUrl, regionalJson) { 135 if (this.activePlant) { 136 try { 137 const regional = JSON.parse(regionalJson || '{}'); 138 if (regional[this.activePlant] && regional[this.activePlant].colorImage) { 139 return regional[this.activePlant].colorImage; 140 } 141 } catch (e) {} 142 } 143 return nationalUrl; 144 }, 145 146 getHoverImage(nationalUrl, regionalJson) { 147 if (this.activePlant) { 148 try { 149 const regional = JSON.parse(regionalJson || '{}'); 150 if (regional[this.activePlant] && regional[this.activePlant].hoverColorImage) { 151 return regional[this.activePlant].hoverColorImage; 152 } 153 } catch (e) {} 154 } 155 return nationalUrl; 156 }, 157 158 // Whether this swatch has any image to display. 159 // Hides swatches with no national image and no regional match 160 // to avoid broken-image renders. 161 hasImage(nationalUrl, regionalJson) { 162 if (nationalUrl && nationalUrl.length) return true; 163 if (this.activePlant) { 164 try { 165 const regional = JSON.parse(regionalJson || '{}'); 166 if (regional[this.activePlant] && regional[this.activePlant].colorImage) { 167 return true; 168 } 169 } catch (e) {} 170 } 171 return false; 172 }, 173 })) 174}) 175 176// video modal 177// autofilling modal on watch video button click 178$('#productVideoModal').on('show.bs.modal', function (event) { 179 var action = $(event.relatedTarget) // Button that triggered the modal 180 var videoUrl = action.data('video') 181 var imageUrl=action.data('image') 182 var youtubeMedia = action.data('youtube') 183 if(imageUrl!=''){ 184 $('#videoDiv').empty() 185 $('#videoDiv').append('<img src='+imageUrl+' class="w-100 rounded-1" height="540px">') 186 } 187 if (videoUrl!=='') { 188 $('#videoDiv').empty() 189 $('#videoDiv').append( 190 '<video width="100%" height="540px" controls><source src="' + 191 videoUrl + 192 '">Your browser does not support the video tag.</video>' 193 ) 194 } 195 if(youtubeMedia!=''){ 196 $('#videoDiv').empty() 197 $('#videoDiv').append( 198 '<iframe class="w-100 rounded-1" height="540px" src="https://youtube.com/embed/' + 199 youtubeMedia + 200 '" frameborder="0" allowfullscreen></iframe>' 201 ) 202 } 203 204}) 205$('#productVideoModal').on('hide.bs.modal', () => { 206 $('#videoDiv').empty() 207})
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.