1// Handle navbar scroll effect 2const navbar = document.querySelector('.navbar-container'); 3const categoriesNav = document.querySelector('.categories-nav'); 4const topNav = document.querySelector('.top-nav'); 5const announcementBar = document.getElementById('announcementBar'); 6 7let isScrolled = false; 8let lastScrollState = false; 9let ticking = false; 10 11function updateNavbar() { 12 const y = window.scrollY; 13 const previousState = isScrolled; 14 15 // hysteresis thresholds - wider gap for more stability 16 if (!isScrolled && y > 50) { 17 isScrolled = true; 18 } 19 else if (isScrolled && y < 15) { 20 isScrolled = false; 21 } 22 23 // Only update DOM if state actually changed 24 if (isScrolled !== previousState) { 25 navbar.classList.toggle('scrolled', isScrolled); 26 27 if (window.innerWidth <= 767) { 28 topNav.style.display = isScrolled ? 'none' : 'flex'; 29 } 30 } 31 32 categoriesNav.style.top = navbar.offsetHeight + "px"; 33 34 ticking = false; 35} 36 37window.addEventListener('scroll', () => { 38 if (!ticking) { 39 window.requestAnimationFrame(updateNavbar); 40 ticking = true; 41 } 42}, { passive: true }); 43 44 45 46//Sidenav 47const toggleMenuElements = document.querySelectorAll('.burger-menu'); 48const sideOverlay = document.getElementById('sideOverlay'); 49const sidenav = document.getElementById('sidenav'); 50const container = document.getElementById('container'); 51const menuIcon = document.getElementById('menuIcon'); 52const subMenu = document.getElementById('subMenu'); 53const nestedSubmenu = document.getElementById('nestedSubmenu'); 54 55let currentPosition = 0; 56let isNavOpen = false; 57 58// Add event listeners to all burger menu elements 59toggleMenuElements.forEach(toggleMenu => { 60 toggleMenu.addEventListener('click', (e) => { 61 e.preventDefault(); 62 isNavOpen = !isNavOpen; 63 if (isNavOpen) { 64 sidenav.classList.add('open'); 65 sideOverlay.classList.add('show'); 66 menuIcon.src = '/images/close-icon.png'; 67 } else { 68 closeNav(); 69 } 70 }); 71}); 72 73function closeNav() { 74 sidenav.classList.remove('open'); 75 sideOverlay.classList.remove('show'); 76 container.style.transform = 'translateX(0)'; 77 currentPosition = 0; 78 menuIcon.src = '/images/menu-icon.png'; 79 isNavOpen = false; 80 subMenu.style.display = 'none'; 81} 82 83async function delay(ms) { 84 return new Promise(resolve => setTimeout(resolve, ms)); 85} 86 87async function showSubmenu() { 88 container.style.transform = 'translateX(-300px)'; 89 currentPosition = 1; 90 subMenu.style.display = 'block'; 91} 92 93function toggleNestedSubmenu(id) { 94 const allSubmenus = document.querySelectorAll('.nested-submenu'); 95 allSubmenus.forEach(submenu => { 96 if (submenu.id !== id) { 97 submenu.classList.remove('active'); // Collapse other submenus 98 } 99 }); 100 101 const submenu = document.getElementById(id); 102 submenu.classList.toggle('active'); 103} 104 105function goBack() { 106 if (currentPosition === 2) { 107 container.style.transform = 'translateX(-300px)'; 108 currentPosition = 1; 109 nestedSubmenu.style.display = 'none'; 110 } else if (currentPosition === 1) { 111 subMenu.style.display = 'none'; 112 container.style.transform = 'translateX(0)'; 113 currentPosition = 0; 114 } 115} 116 117 118// Quantity control logic 119document.querySelectorAll('.quantity-control').forEach(control => { 120 const minusBtn = control.querySelectorAll('.quantity-btn')[0]; 121 const plusBtn = control.querySelectorAll('.quantity-btn')[1]; 122 const input = control.querySelector('.quantity-input'); 123 124 minusBtn.addEventListener('click', () => { 125 let value = parseInt(input.value, 10) || 1; 126 if (value > 1) { 127 input.value = value - 1; 128 } 129 }); 130 131 plusBtn.addEventListener('click', () => { 132 let value = parseInt(input.value, 10) || 1; 133 input.value = value + 1; 134 }); 135 136 input.addEventListener('input', () => { 137 if (parseInt(input.value, 10) < 1 || isNaN(parseInt(input.value, 10))) { 138 input.value = 1; 139 } 140 }); 141}); 142 143// Function to close the announcement bar 144// Function to close the announcement bar and set a cookie 145function closeAnnouncement() { 146 var bar = document.getElementById('announcementBar'); 147 var categoriesNav = document.getElementById('categoriesNav'); // Add this if not globally defined 148 149 if (bar) { 150 bar.style.display = 'none'; 151 152 // Adjust navigation positioning 153 if (categoriesNav) { 154 categoriesNav.style.top = '6.7rem'; 155 } 156 157 // Set cookie to remember dismissal 158 var expiryDate = new Date(); 159 expiryDate.setTime(expiryDate.getTime() + (7 * 24 * 60 * 60 * 1000)); // 7 days 160 document.cookie = "announcementClosed=true; expires=" + expiryDate.toUTCString() + "; path=/"; 161 } 162} 163 164 165// Tooltip 166$(document).ready(function () { 167 168 $('.product-link').hover( 169 function () { 170 $(this).find('.product-tooltip').css("display", "flex"); 171 }, 172 function () { 173 $(this).find('.product-tooltip').css("display", "none"); 174 } 175 ); 176}); 177 178// HEART FILL 179function toggleHeart(element) { 180 // Get the product ID from the element's ID (e.g., favorite_123)
181 var idParts = element.id.split("_"); 182 var productID = idParts.length > 1 ? idParts[1] : null; 183 184 if (!productID) { 185 console.error("Missing product ID in heart element."); 186 return; 187 } 188 189 // Determine action based on whether it's already liked 190 var isLiked = element.classList.contains("liked"); 191 var actionType = isLiked ? 0 : 1; 192 193 // Optimistically toggle heart UI 194 element.classList.toggle("liked"); 195 196 // Call backend to set favorite status 197 fetch("/set-favorite.aspx?pid=" + productID + "&actiontype=" + actionType, { 198 method: "GET", 199 credentials: "include" 200 }) 201 .then(response => response.text()) 202 .then(result => { 203 if (!result.includes("SUCCESSFUL")) { 204 // If backend fails, revert UI change 205 element.classList.toggle("liked"); 206 console.error("Failed to update favorite:"); 207 alert("There was an issue updating your favorites."); 208 } else { 209 alert("Favorites updated!"); 210 } 211 }) 212 .catch(error => { 213 // Revert UI if AJAX fails 214 element.classList.toggle("liked"); 215 console.error("AJAX error:", error); 216 alert("Error communicating with the server."); 217 }); 218} 219
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.