1document.addEventListener('DOMContentLoaded', function () { 2 // Offer dialogs 3 function openOfferDialog(dialog) { 4 if (!dialog) return; 5 dialog.showModal(); 6 } 7 8 function closeOfferDialog(dialog) { 9 dialog.close(); 10 if (window.location.hash.startsWith('#offer-')) { 11 history.replaceState(null, '', window.location.pathname + window.location.search); 12 } 13 } 14 15 document.querySelectorAll('.offer-view').forEach(function (card) { 16 card.querySelectorAll('a').forEach(function (link) { 17 link.addEventListener('click', function (e) { 18 e.stopPropagation(); 19 }); 20 }); 21 22 card.addEventListener('click', function () { 23 const dialogId = card.getAttribute('data-dialog'); 24 const dialog = document.getElementById(dialogId); 25 if (!dialog) return; 26 const idx = card.getAttribute('data-offer-idx'); 27 if (idx !== null) { 28 history.replaceState(null, '', window.location.pathname + window.location.search + '#offer-' + idx); 29 } 30 openOfferDialog(dialog); 31 }); 32 33 card.addEventListener('keydown', function (e) { 34 if (e.key === 'Enter' || e.key === ' ') { 35 e.preventDefault(); 36 card.click(); 37 } 38 }); 39 }); 40 41 document.querySelectorAll('.offer-dialog').forEach(function (dialog) { 42 const closeBtn = dialog.querySelector('.offer-dialog-close'); 43 if (closeBtn) { 44 closeBtn.addEventListener('click', function () { 45 closeOfferDialog(dialog); 46 }); 47 } 48 49 dialog.addEventListener('click', function (e) { 50 if (e.target === dialog) closeOfferDialog(dialog); 51 }); 52 }); 53 54 // Deep-link: open offer from URL hash (#offer-0, #offer-1, ...) 55 var hashMatch = window.location.hash.match(/^#offer-(\d+)$/); 56 if (hashMatch) { 57 var targetIdx = hashMatch[1]; 58 var targetCard = document.querySelector('.offer-view[data-offer-idx="' + targetIdx + '"]'); 59 if (targetCard) { 60 window.addEventListener('load', function () { 61 var sectionEl = document.getElementById('tenant-offers'); 62 if (sectionEl) { 63 var top = sectionEl.getBoundingClientRect().top + window.scrollY - 80; 64 window.scrollTo({ top: top, behavior: 'instant' }); 65 } 66 var dialogId = targetCard.getAttribute('data-dialog'); 67 var dialog = document.getElementById(dialogId); 68 openOfferDialog(dialog); 69 }); 70 } 71 } 72 73 74 const dropdownWrappers = document.querySelectorAll('.dropdown-wrapper'); 75 76 dropdownWrappers.forEach(function (wrapper) { 77 if (wrapper.closest('.student-subnav')) return; 78 79 const button = wrapper.querySelector('button[class*="btn-filter"], .js-link-dropdown'); 80 const list = wrapper.querySelector('.select-items'); 81 82 if (!button || !list) return; 83 84 button.addEventListener('click', function (e) { 85 e.stopPropagation(); 86 const isOpen = list.classList.contains('is-open'); 87 88 // Close all dropdowns 89 document.querySelectorAll('.select-items.is-open').forEach(function (el) { 90 el.classList.remove('is-open'); 91 const trigger = el.closest('.dropdown-wrapper')?.querySelector('button[aria-expanded]'); 92 if (trigger) trigger.setAttribute('aria-expanded', 'false'); 93 }); 94 95 // Open clicked one if it was closed 96 if (!isOpen) { 97 list.classList.add('is-open'); 98 button.setAttribute('aria-expanded', 'true'); 99 } else { 100 button.setAttribute('aria-expanded', 'false'); 101 } 102 }); 103 }); 104 105 // Close dropdowns on outside click 106 document.addEventListener('click', function () { 107 document.querySelectorAll('.select-items.is-open').forEach(function (el) { 108 el.classList.remove('is-open'); 109 const trigger = el.closest('.dropdown-wrapper')?.querySelector('button[aria-expanded]'); 110 if (trigger) trigger.setAttribute('aria-expanded', 'false'); 111 }); 112 }); 113 114 // ââ Store filtering ââââââââââââââââââââââââââââââââââââââââââââââââââââââ 115 var activeSalesGroup = ''; 116 var activeFloor = ''; 117 var activeSearch = ''; 118 119 var salesGroupList = document.querySelector('.sales-group-list'); 120 var initialSalesGroupOption = document.querySelector('.sales-group-list .option.is-active'); 121 if (initialSalesGroupOption) { 122 activeSalesGroup = initialSalesGroupOption.getAttribute('data-aliases') || initialSalesGroupOption.getAttribute('data-value') || ''; 123 } else if (salesGroupList) { 124 activeSalesGroup = salesGroupList.getAttribute('data-initial-value') || ''; 125 } 126 127 function applyFilters() { 128 var cards = document.querySelectorAll('.store-card'); 129 var activeSalesGroupValues = activeSalesGroup ? activeSalesGroup.split(' ').filter(
129Boolean) : []; 130 131 cards.forEach(function (card) { 132 var salesGroupAttr = card.getAttribute('data-sales-group') || ''; 133 var floorAttr = card.getAttribute('data-floor') || ''; 134 var titleAttr = card.getAttribute('data-title') || ''; 135 var salesGroupValues = salesGroupAttr.split(' '); 136 137 var matchSalesGroup = !activeSalesGroupValues.length || activeSalesGroupValues.some(function (value) { 138 return salesGroupValues.indexOf(value) !== -1; 139 }); 140 var matchFloor = !activeFloor || floorAttr.split(' ').indexOf(activeFloor) !== -1; 141 var matchSearch = !activeSearch || titleAttr.indexOf(activeSearch) !== -1; 142 143 card.style.display = (matchSalesGroup && matchFloor && matchSearch) ? '' : 'none'; 144 }); 145 146 // Hide letter groups that have no visible cards 147 document.querySelectorAll('.stores-letter-group').forEach(function (group) { 148 var hasVisible = Array.from(group.querySelectorAll('.store-card')).some(function (c) { 149 return c.style.display !== 'none'; 150 }); 151 group.style.display = hasVisible ? '' : 'none'; 152 }); 153 154 // Filter offer cards by search 155 var offerCards = document.querySelectorAll('.offer-view'); 156 offerCards.forEach(function (card) { 157 var titleAttr = card.getAttribute('data-title') || ''; 158 var matchSearch = !activeSearch || titleAttr.indexOf(activeSearch) !== -1; 159 card.style.display = matchSearch ? '' : 'none'; 160 }); 161 } 162 163 // Sales Group filter 164 document.querySelectorAll('.sales-group-list .option').forEach(function (btn) { 165 btn.addEventListener('click', function () { 166 activeSalesGroup = btn.getAttribute('data-aliases') || btn.getAttribute('data-value') || ''; 167 168 var trigger = btn.closest('.dropdown-wrapper').querySelector('.btn-filter-sales-group'); 169 if (trigger) { 170 var placeholder = trigger.dataset.placeholder || trigger.firstChild.textContent; 171 if (!trigger.dataset.placeholder) trigger.dataset.placeholder = placeholder; 172 trigger.firstChild.textContent = activeSalesGroup ? btn.textContent : placeholder; 173 } 174 175 btn.closest('.sales-group-list').querySelectorAll('.option').forEach(function (o) { 176 o.classList.toggle('is-active', o === btn); 177 }); 178 179 applyFilters(); 180 }); 181 }); 182 183 if (activeSalesGroup) { 184 applyFilters(); 185 } 186 187 // Floor filter options 188 document.querySelectorAll('.floor-list .option').forEach(function (btn) { 189 btn.addEventListener('click', function () { 190 activeFloor = btn.getAttribute('data-value') || ''; 191 192 var trigger = btn.closest('.dropdown-wrapper').querySelector('.btn-filter-floor'); 193 if (trigger) { 194 var placeholder = trigger.dataset.placeholder || trigger.firstChild.textContent; 195 if (!trigger.dataset.placeholder) trigger.dataset.placeholder = placeholder; 196 trigger.firstChild.textContent = activeFloor ? btn.textContent : placeholder; 197 } 198 199 btn.closest('.floor-list').querySelectorAll('.option').forEach(function (o) { 200 o.classList.toggle('is-active', o === btn); 201 }); 202 203 applyFilters(); 204 }); 205 }); 206 207 // Search input 208 var searchInput = document.querySelector('.listing-search'); 209 if (searchInput) { 210 // Pre-fill from URL on page load 211 var urlParams = new URLSearchParams(window.location.search); 212 var urlSearch = urlParams.get('search'); 213 if (urlSearch) { 214 searchInput.value = urlSearch; 215 activeSearch = urlSearch.toLowerCase().trim(); 216 applyFilters(); 217 } 218 219 searchInput.addEventListener('input', function () { 220 activeSearch = searchInput.value.toLowerCase().trim(); 221 222 // Sync URL query param 223 var params = new URLSearchParams(window.location.search); 224 if (activeSearch) { 225 params.set('search', searchInput.value.trim()); 226 } else { 227 params.delete('search'); 228 } 229 var newUrl = window.location.pathname + (params.toString() ? '?' + params.toString() : ''); 230 history.replaceState(null, '', newUrl); 231 232 applyFilters(); 233 }); 234 } 235 236 // Day tabs â desktop + mobile, with auto-select of today 237 const days = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday']; 238 const todayName = days[new Date().getDay()]; 239 240 function setActiveTab(dayName) { 241 // Desktop 242 const desktopTabs = document.querySelectorAll('.day-tabs-desktop [role="tab"]');
243 desktopTabs.forEach(function (btn) { 244 const isActive = btn.textContent.trim() === dayName; 245 btn.setAttribute('aria-selected', String(isActive)); 246 if (isActive) { 247 btn.classList.remove('bg-transparent'); 248 btn.classList.add('bg-black', 'text-white'); 249 } else { 250 btn.classList.remove('bg-black', 'text-white'); 251 btn.classList.add('bg-transparent'); 252 } 253 }); 254 255 // Mobile options 256 const mobileOptions = document.querySelectorAll('.day-tabs-mobile__option'); 257 mobileOptions.forEach(function (opt) { 258 opt.setAttribute('aria-selected', String(opt.textContent.trim() === dayName)); 259 }); 260 261 // Mobile label 262 const label = document.querySelector('.day-tabs-mobile__label'); 263 if (label) label.textContent = dayName; 264 } 265 266 // Set today on load (fallback to Monday if weekend) 267 const workdays = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday']; 268 const initialDay = workdays.includes(todayName) ? todayName : 'Monday'; 269 setActiveTab(initialDay); 270 271 // Desktop tab clicks 272 document.querySelectorAll('.day-tabs-desktop [role="tab"]').forEach(function (btn) { 273 btn.addEventListener('click', function () { 274 setActiveTab(btn.textContent.trim()); 275 }); 276 }); 277 278 // Day tabs mobile dropdown 279 const dayTabsMobile = document.querySelector('.day-tabs-mobile'); 280 if (dayTabsMobile) { 281 const trigger = dayTabsMobile.querySelector('.day-tabs-mobile__trigger'); 282 const dropdown = dayTabsMobile.querySelector('.day-tabs-mobile__dropdown'); 283 284 trigger.addEventListener('click', function (e) { 285 e.stopPropagation(); 286 const isOpen = dropdown.classList.contains('is-open'); 287 dropdown.classList.toggle('is-open', !isOpen); 288 trigger.setAttribute('aria-expanded', String(!isOpen)); 289 }); 290 291 dayTabsMobile.querySelectorAll('.day-tabs-mobile__option').forEach(function (option) { 292 option.addEventListener('click', function () { 293 setActiveTab(option.textContent.trim()); 294 dropdown.classList.remove('is-open'); 295 trigger.setAttribute('aria-expanded', 'false'); 296 }); 297 }); 298 299 document.addEventListener('click', function () { 300 dropdown.classList.remove('is-open'); 301 trigger.setAttribute('aria-expanded', 'false'); 302 }); 303 } 304 305 // Menu nav mobile dropdown 306 const menuNavMobile = document.querySelector('.menu-nav-mobile'); 307 if (menuNavMobile) { 308 const menuTrigger = menuNavMobile.querySelector('.menu-nav-mobile__trigger'); 309 const menuDropdown = menuNavMobile.querySelector('.menu-nav-mobile__dropdown'); 310 311 menuTrigger.addEventListener('click', function (e) { 312 e.stopPropagation(); 313 const isOpen = menuDropdown.classList.contains('is-open'); 314 menuDropdown.classList.toggle('is-open', !isOpen); 315 menuTrigger.setAttribute('aria-expanded', String(!isOpen)); 316 }); 317 318 menuNavMobile.querySelectorAll('.menu-nav-mobile__option').forEach(function (option) { 319 option.addEventListener('click', function () { 320 const url = option.getAttribute('data-url'); 321 if (url) window.location.href = url; 322 }); 323 }); 324 325 document.addEventListener('click', function () { 326 menuDropdown.classList.remove('is-open'); 327 menuTrigger.setAttribute('aria-expanded', 'false'); 328 }); 329 } 330});
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.