PageSourceSearch

https://www.roccaalmare.ee/app/themes/citycon2026_03_09_21_26/assets/js/stores.js?ver=1779892724

js roccaalmare.ee collected 2026-10-02 12:52:24 UTC 11,742 bytes, 330 lines download raw bytes

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.