document.addEventListener('DOMContentLoaded', () => { const dataElement = document.getElementById('calendar-events-data'); const modalElement = document.getElementById('dayEventsModal'); let calendarEvents = {}; const escapeHtml = (value) => String(value || '') .replace(/&/g, '&') .replace(//g, '>') .replace(/"/g, '"') .replace(/'/g, '''); const safeExternalUrl = (value) => { if (!value) return ''; try { const url = new URL(value, window.location.origin); return ['http:', 'https:'].includes(url.protocol) ? url.href : ''; } catch (error) { return ''; } }; if (dataElement) { try { calendarEvents = JSON.parse(dataElement.textContent); } catch (error) { calendarEvents = {}; } } if (modalElement && window.bootstrap) { if (modalElement.parentElement !== document.body) { document.body.appendChild(modalElement); } const modal = new window.bootstrap.Modal(modalElement); const titleNode = modalElement.querySelector('[data-calendar-title]'); const bodyNode = modalElement.querySelector('[data-calendar-body]'); const renderEvents = (isoDate) => { const selectedEvents = calendarEvents[isoDate] || []; const titleDate = new Date(`${isoDate}T12:00:00`); titleNode.textContent = titleDate.toLocaleDateString(undefined, { weekday: 'long', month: 'long', day: 'numeric', year: 'numeric', }); if (!selectedEvents.length) { bodyNode.innerHTML = ` `; return; } bodyNode.innerHTML = selectedEvents .map((event) => { const name = escapeHtml(event.name); const time = escapeHtml(event.time); const location = escapeHtml(event.location || 'Location announced soon'); const summary = event.summary ? `

${escapeHtml(event.summary)}

` : ''; const detailUrl = escapeHtml(event.detail_url || '#'); const eventUrl = safeExternalUrl(event.event_url); return ` `; }) .join(''); }; document.querySelectorAll('[data-calendar-date]').forEach((button) => { button.addEventListener('click', () => { renderEvents(button.dataset.calendarDate); modal.show(); }); }); } document.querySelectorAll('[data-copy-snippet]').forEach((button) => { button.addEventListener('click', async () => { const target = document.querySelector(button.dataset.copyTarget); if (!target) return; try { await navigator.clipboard.writeText(target.textContent.trim()); const original = button.textContent; button.textContent = 'Copied'; window.setTimeout(() => { button.textContent = original; }, 1600); } catch (error) { button.textContent = 'Copy manually'; } }); }); const escapeAttribute = (value) => String(value || '') .replace(/&/g, '&') .replace(/"/g, '"') .replace(//g, '>'); document.querySelectorAll('[data-embed-settings]').forEach((form) => { const baseUrl = form.dataset.embedBaseUrl || ''; const urlOutput = document.getElementById('dashboardEmbedUrl'); const iframeOutput = document.getElementById('dashboardIframeSnippet'); const previewLink = document.querySelector('[data-embed-preview]'); if (!baseUrl || !urlOutput || !iframeOutput) return; const updateEmbedOutput = () => { const formData = new FormData(form); const params = new URLSearchParams(); const month = String(formData.get('month') || '').trim(); const header = String(formData.get('header') || '1'); const title = String(formData.get('title') || 'Where to find us calendar').trim() || 'Where to find us calendar'; const width = String(formData.get('width') || '100%').trim() || '100%'; const height = Math.max(parseInt(String(formData.get('height') || '760'), 10) || 760, 360); const radius = Math.max(parseInt(String(formData.get('radius') || '24'), 10) || 24, 0); if (/^\d{4}-\d{2}$/.test(month)) { params.set('month', month); } if (header === '0') { params.set('header', '0'); } const widgetUrl = params.toString() ? `${baseUrl}?${params.toString()}` : baseUrl; const iframeSnippet = ``; urlOutput.textContent = widgetUrl; iframeOutput.textContent = iframeSnippet; if (previewLink) { previewLink.href = widgetUrl; } }; ['input', 'change'].forEach((eventName) => { form.addEventListener(eventName, updateEmbedOutput); }); updateEmbedOutput(); }); });