1// Custom JavaScript Functions 2function is_touch_device() { 3 return !!('ontouchstart' in window); 4} 5/* Owners */ 6function owners_hover(id){ 7 if(id == 'owner-manuals'){ 8 if(is_touch_device()){ 9 document.getElementById('owner-manuals').style.opacity=0.5; 10 document.getElementById('owner-manuals-mob').style.opacity=0.5; 11 } 12 else { 13 document.getElementById('owner-manuals').style.opacity=1.0; 14 document.getElementById('owner-manuals-mob').style.opacity=1.0; 15 } 16 } 17 else if(id == 'owner-parts'){ 18 if(is_touch_device()){ 19 document.getElementById('owner-parts').style.opacity=0.5; 20 document.getElementById('owner-parts-mob').style.opacity=0.5; 21 } 22 else { 23 document.getElementById('owner-parts').style.opacity=1.0; 24 document.getElementById('owner-parts-mob').style.opacity=1.0; 25 } 26 } 27 else { 28 if(is_touch_device()){ 29 document.getElementById(id).style.opacity=0.5; 30 } 31 else { 32 document.getElementById(id).style.opacity=1.0; 33 } 34 } 35} 36function owners_out(id){ 37 if(id == 'owner-manuals'){ 38 document.getElementById('owner-manuals').style.opacity=0.5; 39 document.getElementById('owner-manuals-mob').style.opacity=0.5; 40 } 41 else if(id == 'owner-parts'){ 42 document.getElementById('owner-parts').style.opacity=0.5; 43 document.getElementById('owner-parts-mob').style.opacity=0.5; 44 } 45 else 46 document.getElementById(id).style.opacity=0.5; 47} 48/* Lineup */ 49function lineup_hover(id){ 50 // Deal with mobile version 51 var mobid = id.concat('-mob'); 52 if(is_touch_device()){ 53 document.getElementById(id).style.opacity=1.0; 54 document.getElementById(mobid).style.opacity=1.0; 55 } 56 else { 57 document.getElementById(id).style.opacity=0.5; 58 document.getElementById(id).style.filter = 'filter:alpha(opacity=50)'; 59 document.getElementById(id).style.transition = 'opacity 500ms ease-in-out'; 60 document.getElementById(mobid).style.opacity=0.5; 61 document.getElementById(mobid).style.filter = 'filter:alpha(opacity=50)'; 62 document.getElementById(mobid).style.transition = 'opacity 500ms ease-in-out'; 63 } 64} 65function lineup_out(id){ 66 // Deal with mobile version 67 var mobid = id.concat('-mob'); 68 document.getElementById(id).style.opacity=1.0; 69 document.getElementById(mobid).style.opacity=1.0; 70} 71/* Feature */ 72function feature_hover(id){ 73 // Deal with mobile version 74 var mobid = id.concat('-mob'); 75 if(is_touch_device()){ 76 document.getElementById(id).style.opacity=1.0; 77 document.getElementById(mobid).style.opacity=1.0; 78 } 79 else { 80 document.getElementById(id).style.opacity=0.8; 81 document.getElementById(id).style.transform = "scale(1.1)"; 82 document.getElementById(id).style.webkitTransform = "scale(1.1)"; 83 document.getElementById(id).style.MozTransfrom = "scale(1.1)"; 84 document.getElementById(mobid).style.opacity=0.8; 85 document.getElementById(mobid).style.transform = "scale(1.1)"; 86 document.getElementById(mobid).style.webkitTransform = "scale(1.1)"; 87 document.getElementById(mobid).style.MozTransfrom = "scale(1.1)"; 88 } 89} 90function feature_out(id){ 91 // Deal with mobile version 92 var mobid = id.concat('-mob'); 93 document.getElementById(id).style.opacity=1.0; 94 document.getElementById(id).style.transform = "scale(1.0)"; 95 document.getElementById(mobid).style.opacity=1.0; 96 document.getElementById(mobid).style.transform = "scale(1.0)"; 97} 98// Instructions/Videos/FAQ Show/Hide Function 99function showhidetext(question) { 100 var $hidelink = ""; 101 if(question === 'moreproducts'){ 102 $hidelink = 'showproductvideos'; 103 } 104 else if(question === 'moreinstall'){ 105 $hidelink = 'showinstallvideos'; 106 } 107 else if(question === 'moreaccessories'){ 108 $hidelink = 'showaccessoriesvideos'; 109 } 110 // Set the vars 111 var x = document.getElementById(question); 112 var y = document.getElementById($hidelink); 113 114 if (x.style.display === "block"){ 115 x.style.display = "none"; 116 } 117 else{ 118 x.style.display = "block"; 119 if(question === 'moreproducts' || question === 'moreinstall' || question === 'moreaccessories'){ 120 y.style.display = "none"; 121 } 122 } 123} 124 125// Show free shipping icon and banner when subtotal is over $100 126const originalAdditemToolProcessSuccessful = ECCAddItemTool.prototype.processSuccessful; 127 128ECCAddItemTool.prototype.processSuccessful = function(data) { 129 var tool = this; 130 if (data && data.data && data.data.cart && data.data.cart.subtotal) { 131 132 // Show the new subtotal 133 $(tool.successModal).find('.ACIFreeShipping .ACICartSubtotal').html(ECCUserMiscTool.formatCurrency(data.data.cart.subtotal)); 134 135 // Show the free shipping banner if the subtotal is over $100 136 if (data.data.cart.subtotal >= 100) { 137 $(tool.successModal).find('.ACIFreeShipping .ACINeededForFreeShipping').hide(); 138 $(tool.successModal).find('.ACIFreeShipping .ACIFreeShippingBanner').show(); 139 } else { 140 $(tool.successModal).find('.ACIFreeShipping .ACIFreeShippingBanner').hide(); 141 $(tool.successModal).find('.ACIFreeShipping .ACINeededForFreeShipping-amount').html(ECCUserMiscTool.formatCurrency(100 - data.data.cart.subtotal)); 142 $(tool.successModal).find('.ACIFreeShipping .ACINeededForFreeShipping').show(); 143 } 144 } 145 originalAdditemToolProcessSuccessful.call(this, data); 146}; 147 148/* FAQ - Show/Hide Answer */ 149document.querySelectorAll(".faq-question").forEach(q => { 150 q.addEventListener("click", () => { 151 document.querySelectorAll(".faq-item").forEach(item => { 152 if (item !== q.parentElement) { 153 item.classList.remove("open"); 154 } 155 }); 156 q.parentElement.classList.toggle("open"); 157 }); 158}); 159 160/* New Video Slider */ 161document.addEventListener('DOMContentLoaded', function () { 162 const sliderRoot = document.querySelector('#videosection .snow-video-slider'); 163 if (!sliderRoot) return; 164 165 const viewport = sliderRoot.querySelector('.slider-viewport'); 166 const track = sliderRoot.querySelector('.slider-track'); 167 const prevBtn = sliderRoot.querySelector('.slider-nav.prev'); 168 const nextBtn = sliderRoot.querySelector('.slider-nav.next'); 169 170 const modalEl = document.getElementById('videoLightboxModal'); 171 const modalFrame = document.getElementById('youtubeLightboxFrame'); 172 const videoModal = new bootstrap.Modal(modalEl); 173 174 const originalSlides = Array.from(track.querySelectorAll('.video-slide')); 175 const totalOriginal = originalSlides.length; 176 177 let currentIndex = 1; 178 let slideWidth = 0; 179 let gap = 16; 180 let isTransitioning = false;
181 182 let startX = 0; 183 let currentTranslate = 0; 184 let prevTranslate = 0; 185 let isDragging = false; 186 187 function getSlidesPerView() { 188 const width = window.innerWidth; 189 190 if (width >= 1400) return 2.6; 191 if (width >= 1200) return 2.45; 192 if (width >= 992) return 2.2; 193 if (width >= 768) return 1.7; 194 if (width >= 576) return 1.25; 195 return 1.05; 196 } 197 198 function cloneSlides() { 199 track.innerHTML = ''; 200 201 const firstClone = originalSlides[0].cloneNode(true); 202 firstClone.classList.add('clone'); 203 204 const lastClone = originalSlides[totalOriginal - 1].cloneNode(true); 205 lastClone.classList.add('clone'); 206 207 track.appendChild(lastClone); 208 209 originalSlides.forEach(slide => { 210 track.appendChild(slide.cloneNode(true)); 211 }); 212 213 track.appendChild(firstClone); 214 } 215 216 function setSlideWidths() { 217 const slides = track.querySelectorAll('.video-slide'); 218 gap = parseFloat(window.getComputedStyle(track).gap) || 16; 219 220 const slidesPerView = getSlidesPerView(); 221 slideWidth = (viewport.clientWidth - (gap * (slidesPerView - 1))) / slidesPerView; 222
223 slides.forEach(slide => { 224 slide.style.width = slideWidth + 'px'; 225 }); 226 } 227 228 function getTranslateForIndex(index) { 229 return -index * (slideWidth + gap); 230 } 231 232 function setTrackPosition(animate = true) { 233 if (!animate) { 234 track.style.transition = 'none'; 235 } else { 236 track.style.transition = 'transform 0.45s ease'; 237 } 238 239 const translate = getTranslateForIndex(currentIndex); 240 track.style.transform = 'translateX(' + translate + 'px)'; 241 currentTranslate = translate; 242 prevTranslate = translate; 243 } 244 245 function nextSlide() { 246 if (isTransitioning) return; 247 isTransitioning = true; 248 currentIndex++; 249 setTrackPosition(true); 250 } 251 252 function prevSlide() { 253 if (isTransitioning) return; 254 isTransitioning = true; 255 currentIndex--; 256 setTrackPosition(true); 257 } 258 259 function handleLoopReset() { 260 const slides = track.querySelectorAll('.video-slide'); 261 262 if (currentIndex === slides.length - 1) { 263 currentIndex = 1; 264 setTrackPosition(false); 265 } 266 267 if (currentIndex === 0) { 268 currentIndex = totalOriginal; 269 setTrackPosition(false); 270 } 271 272 isTransitioning = false; 273 } 274 275 function rebuildSlider() { 276 cloneSlides(); 277 setSlideWidths(); 278 currentIndex = 1; 279 setTrackPosition(false); 280 bindSlideClicks(); 281 } 282 283 function bindSlideClicks() { 284 const slides = track.querySelectorAll('.video-slide'); 285
286 slides.forEach(slide => { 287 slide.addEventListener('click', function (e) { 288 if (isDragging) return; 289 290 const videoId = this.getAttribute('data-video-id'); 291 if (!videoId) return; 292 293 modalFrame.src = 'https://www.youtube.com/embed/' + videoId + '?autoplay=1&rel=0'; 294 videoModal.show(); 295 }); 296 }); 297 } 298 299 function pointerDown(x) { 300 isDragging = true; 301 startX = x; 302 prevTranslate = currentTranslate; 303 track.style.transition = 'none'; 304 } 305 306 function pointerMove(x) { 307 if (!isDragging) return; 308 const delta = x - startX; 309 currentTranslate = prevTranslate + delta; 310 track.style.transform = 'translateX(' + currentTranslate + 'px)'; 311 } 312 313 function pointerUp(x) { 314 if (!isDragging) return; 315 316 isDragging = false; 317 const movedBy = x - startX; 318 const threshold = 60; 319 320 if (movedBy < -threshold) { 321 currentIndex++; 322 } else if (movedBy > threshold) { 323 currentIndex--; 324 } 325 326 isTransitioning = true; 327 setTrackPosition(true); 328 } 329 330 nextBtn.addEventListener('click', nextSlide); 331 prevBtn.addEventListener('click', prevSlide); 332 333 track.addEventListener('transitionend', handleLoopReset); 334 335 viewport.addEventListener('touchstart', function (e) { 336 pointerDown(e.touches[0].clientX); 337 }, { passive: true }); 338 339 viewport.addEventListener('touchmove', function (e) { 340 pointerMove(e.touches[0].clientX); 341 }, { passive: true }); 342 343 viewport.addEventListener('touchend', function (e) { 344 pointerUp(e.changedTouches[0].clientX); 345 }); 346 347 viewport.addEventListener('mousedown', function (e) { 348 pointerDown(e.clientX); 349 }); 350 351 window.addEventListener('mousemove', function (e) { 352 if (!isDragging) return; 353 pointerMove(e.clientX); 354 }); 355 356 window.addEventListener('mouseup', function (e) { 357 if (!isDragging) return; 358 pointerUp(e.clientX); 359 }); 360 361 viewport.addEventListener('mouseleave', function (e) { 362 if (!isDragging) return; 363 pointerUp(e.clientX); 364 }); 365 366 modalEl.addEventListener('hidden.bs.modal', function () { 367 modalFrame.src = ''; 368 }); 369 370 let resizeTimer; 371 window.addEventListener('resize', function () { 372 clearTimeout(resizeTimer); 373 resizeTimer = setTimeout(function () { 374 setSlideWidths(); 375 setTrackPosition(false); 376 }, 120); 377 }); 378 379 rebuildSlider(); 380}); 381 382/* Open Youtube Playlist in Lightbox */ 383document.addEventListener('DOMContentLoaded', function () { 384 385 const playlistModalEl = document.getElementById('playlistModal'); 386 const playlistFrame = document.getElementById('playlistFrame'); 387 const playlistModal = new bootstrap.Modal(playlistModalEl); 388 389 // Handle ALL playlist buttons dynamically 390 document.addEventListener('click', function (e) { 391 const btn = e.target.closest('.open-playlist-btn'); 392 if (!btn) return; 393 394 e.preventDefault(); 395 396 const playlistId = btn.getAttribute('data-playlist'); 397 if (!playlistId) return; 398 399 playlistFrame.src = 400 "https://www.youtube.com/embed/videoseries?list=" + 401 playlistId + 402 "&autoplay=1"; 403 404 playlistModal.show(); 405 }); 406 407 // Stop playback when modal closes 408 playlistModalEl.addEventListener('hidden.bs.modal', function () { 409 playlistFrame.src = ""; 410 }); 411 412});
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.