diff --git a/docs/javascripts/ics_calendar2.js b/docs/javascripts/ics_calendar2.js index 1710f96b101ee4fa6f144f545d5121cc4dbef270..9f0f8c10d7116a7fd768e04d2b302d93bf24b8a1 100644 --- a/docs/javascripts/ics_calendar2.js +++ b/docs/javascripts/ics_calendar2.js @@ -14,11 +14,6 @@ document.addEventListener('DOMContentLoaded', function() { }); }); -window.addEventListener('message', function(event) { - adjustHeight(); - adjustWidth(); -}, false); - // Load iCalendar data async function fetchAndParseICS() { const response = await fetch('./data/calendar.ics'); @@ -54,226 +49,287 @@ fetchAndParseICS() }); } - // Determine the initial view based on screen width - let isMobile = window.innerWidth <= 768; - let initialViewType = isMobile ? 'listYear' : 'listYear'; - - var calendarEl = document.getElementById('calendar'); - var debounceTimer; - var calendar = new FullCalendar.Calendar(calendarEl, { - locale: 'de', // German locale - initialView: initialViewType, - customButtons: { - togglePastEvents: { - text: 'Zeige/Verstecke vergangene Termine', - click: function() { - showPastEvents = !showPastEvents; - handlePastEventsVisibility(); - } +// defines toolbar based on width +function getToolbarConfig() { + const width = window.innerWidth; + + // Define breakpoints + const mobileWidth = 768; + + if (width <= mobileWidth) { + return { + toolbar: { + start: 'prev', + center: 'title', + end: 'next' + }, + view: 'listYear' + }; + } else { + return { + toolbar: { + start: 'prev,next,today', + center: 'title', + end: 'dayGridMonth,listYear' + } + }; + } +} + +// Determine the initial view based on screen width +let isMobile = window.innerWidth <= 768; +let initialViewType = isMobile ? 'listYear' : 'listYear'; +let calendar; + +function initializeCalendar() { + if (!calendar) { + let config = getToolbarConfig(); + var calendarEl = document.getElementById('calendar'); + calendar = new FullCalendar.Calendar(calendarEl, { + locale: 'de', // German locale + initialView: initialViewType, + customButtons: { + togglePastEvents: { + text: 'Zeige/Verstecke vergangene Termine', + click: function() { + showPastEvents = !showPastEvents; + handlePastEventsVisibility(); + } + } + }, + headerToolbar: config.toolbar, + footerToolbar: { + start: 'togglePastEvents' + }, + views: { + dayGridMonth: { buttonText: 'Kalender'}, + listYear: { buttonText: 'Liste' }, + }, + contentHeight: "auto", + events: calendarEvents, + eventDisplay: 'block', + + eventContent: function(arg) { + var start = arg.event.start; + var end = arg.event.end; + var title = arg.event.title; + + // Format time as "[start time] - [end time] Uhr: [title]" + var startTime = start.getHours() + ':' + (start.getMinutes()<10?'0':'') + start.getMinutes(); + var endTime = end.getHours() + ':' + (end.getMinutes()<10?'0':'') + end.getMinutes(); + var formattedTime = startTime + ' - ' + endTime + ' Uhr: '; + + var tooltipContent = formattedTime + title; + + return { + html: `<div title="${tooltipContent}">${title}</div>` } - }, - headerToolbar: { - start: 'prev,next,today', - center: 'title', - end: 'dayGridMonth,listYear' - }, - footerToolbar: { - start: 'togglePastEvents' - }, - views: { - dayGridMonth: { buttonText: 'Kalender'}, - listYear: { buttonText: 'Liste' }, - }, - contentHeight: "auto", - events: calendarEvents, - eventDisplay: 'block', - - eventContent: function(arg) { - var start = arg.event.start; - var end = arg.event.end; - var title = arg.event.title; + }, - // Format time as "[start time] - [end time] Uhr: [title]" - var startTime = start.getHours() + ':' + (start.getMinutes()<10?'0':'') + start.getMinutes(); - var endTime = end.getHours() + ':' + (end.getMinutes()<10?'0':'') + end.getMinutes(); - var formattedTime = startTime + ' - ' + endTime + ' Uhr: '; + eventDidMount: function(info) { + handlePastEventsVisibility(); + }, - var tooltipContent = formattedTime + title; - - return { - html: `<div title="${tooltipContent}">${title}</div>` - } - }, - - eventDidMount: function(info) { - handlePastEventsVisibility(); - }, - - //Opens the contact form with event specific informations after clicking an event - eventClick: function showContactForm(info) { - let currentDate = new Date(); - let startDate = info.event.start; - let endDate = info.event.end; - - // Check if the event's start date is in the past - if (startDate < currentDate) { - alert("Du kannst Dich nicht für ein Ereignis in der Vergangenheit anmelden."); - return; // Exit the function early - } + //Opens the contact form with event specific informations after clicking an event + eventClick: function showContactForm(info) { + let currentDate = new Date(); + let startDate = info.event.start; + let endDate = info.event.end; + + // Check if the event's start date is in the past + if (startDate < currentDate) { + alert("Du kannst Dich nicht für ein Ereignis in der Vergangenheit anmelden."); + return; // Exit the function early + } - // Format the date using German locale - let formattedDate = new Intl.DateTimeFormat('de-DE', { - year: 'numeric', - month: 'long', - day: '2-digit' - }).format(startDate); - - // Format the start time using German locale - let formattedStartTime = new Intl.DateTimeFormat('de-DE', { - hour: '2-digit', - minute: '2-digit', - second: '2-digit', - hour12: false // Use 24-hour format - }).format(startDate); - - // Format the end time using German locale - let formattedEndTime = new Intl.DateTimeFormat('de-DE', { - hour: '2-digit', - minute: '2-digit', - second: '2-digit', - hour12: false // Use 24-hour format - }).format(endDate); + // Format the date using German locale + let formattedDate = new Intl.DateTimeFormat('de-DE', { + year: 'numeric', + month: 'long', + day: '2-digit' + }).format(startDate); + + // Format the start time using German locale + let formattedStartTime = new Intl.DateTimeFormat('de-DE', { + hour: '2-digit', + minute: '2-digit', + hour12: false // Use 24-hour format + }).format(startDate); + + // Format the end time using German locale + let formattedEndTime = new Intl.DateTimeFormat('de-DE', { + hour: '2-digit', + minute: '2-digit', + hour12: false // Use 24-hour format + }).format(endDate); + + function generateEventHTML (info, formattedDate, formattedStartTime, formattedEndTime) { + return ` + <form id="event-form" class="form" style="display: none;" method="post" action="https://feedback.ruhr-uni-bochum.de/formmailer.php" ... > + <input type="hidden" name="subject" value="Teilnahmeanfrage von der Makerspace-Homepage" /> + <div class="form-field"> + <input type="button" id="close-button" class="md-button" value="Teilnahmeanfrage abbrechen" name="abbrechen" /> + </div> + <div class="event-subject"> + <label for="event-info"><strong>Deine Teilnahmeanfrage für:</strong></label> + <textarea name="event-info" id="event-info" readonly>${info.event.title + '\nam ' + formattedDate + ' von ' + formattedStartTime + ' bis ' + formattedEndTime + ' Uhr'}</textarea> + </div> + <input type="hidden" name="recipients" value="Torben.Boehnke-makerspace@ruhr-uni-bochum.de"/> + <input type="hidden" name="mail_options" value="charset=UTF-8,Exclude=realname;honigtopf;schicken;FromAddr"/> + <input type="hidden" name="good_url" value="https://makerspace.io.noc.ruhr-uni-bochum.de/homepage/danke/" /> + <input type="hidden" name="good_template" value="https://makerspace.io.noc.ruhr-uni-bochum.de/homepage/danke/" /> + + <div class="form-field"> + <label for="nachname"><strong>Name:</strong></label> + <input name="nachname" id="nachname" type="text" maxlength="30" required/> + </div> + + <div class="form-field"> + <label for="vorname"><strong>Vorname:</strong></label> + <input name="vorname" id="vorname" type="text" maxlength="30" required/> + </div> + + <div class="form-field"> + <label for="email"><strong>E-Mail:</strong></label> + <input name="email" id="email" type="email" maxlength="60" required/> + </div> + + <div class="form-field"> + <label for="tel"><strong>Telefonnummer:</strong></label> + <input name="tel" id="tel" type="tel" maxlength="40" placeholder="Optional" /> + </div> + + <div class="form-field"> + <label for="nachricht" id="nachricht-text"><strong>Deine Nachricht:</strong><span class='large'></span></label> + <textarea name="nachricht" id="nachricht" placeholder="Hier kannst Du Deine Nachricht schreiben (Limit: 2000 Zeichen)" rows="10"></textarea> + </div> + + <div class="honey" style="display: none;"> + <label for="honigtopf"><strong>Please do not fill this field:</strong></label> + <input name="honigtopf" id="honigtopf" type="text" maxlength="50" value="" /> + </div> + + <p>Bitte beachte: Diese Anfrage allein berechtigt Dich noch nicht zur Teilnahme. Die Teilnahme ist erst nach Erhalt einer Bestätigungsmail von uns gültig!</p> - function generateEventHTML (info, formattedDate, formattedStartTime, formattedEndTime) { - return ` - <form id="event-form" class="form" style="display: none;" method="post" action="https://feedback.ruhr-uni-bochum.de/formmailer.php" ... > - <input type="hidden" name="subject" value="Teilnahmeanfrage von der Makerspace-Homepage" /> - <div class="form-field"> - <input type="button" id="close-button" class="md-button" value="Teilnahmeanfrage abbrechen" name="abbrechen" /> + <div class="form-field"> + <input type="submit" class="md-button" value="Teilnahmeanfrage abschicken" name="schicken" /> + </div> + </form> </div> - <div class="event-subject"> - <label for="event-info"><strong>Deine Teilnahmeanfrage für:</strong></label> - <textarea name="event-info" id="event-info" readonly>${info.event.title + '\nam ' + formattedDate + ' von ' + formattedStartTime + ' bis ' + formattedEndTime + ' Uhr'} Uhr</textarea> - </div> - <input type="hidden" name="recipients" value="Torben.Boehnke-makerspace@ruhr-uni-bochum.de"/> - <input type="hidden" name="mail_options" value="charset=UTF-8,Exclude=realname;honigtopf;schicken;FromAddr"/> - <input type="hidden" name="good_url" value="https://makerspace.io.noc.ruhr-uni-bochum.de/homepage/danke/" /> - <input type="hidden" name="good_template" value="https://makerspace.io.noc.ruhr-uni-bochum.de/homepage/danke/" /> - - <div class="form-field"> - <label for="nachname"><strong>Name:</strong></label> - <input name="nachname" id="nachname" type="text" maxlength="30" required/> - </div> - - <div class="form-field"> - <label for="vorname"><strong>Vorname:</strong></label> - <input name="vorname" id="vorname" type="text" maxlength="30" required/> - </div> - - <div class="form-field"> - <label for="email"><strong>E-Mail:</strong></label> - <input name="email" id="email" type="email" maxlength="60" required/> - </div> - - <div class="form-field"> - <label for="tel"><strong>Telefonnummer:</strong></label> - <input name="tel" id="tel" type="tel" maxlength="40" placeholder="Optional" /> - </div> - - <div class="form-field"> - <label for="nachricht" id="nachricht-text"><strong>Deine Nachricht:</strong><span class='large'></span></label> - <textarea name="nachricht" id="nachricht" placeholder="Hier kannst Du Deine Nachricht schreiben (Limit: 2000 Zeichen)" rows="10"></textarea> - </div> - - <div class="honey" style="display: none;"> - <label for="honigtopf"><strong>Please do not fill this field:</strong></label> - <input name="honigtopf" id="honigtopf" type="text" maxlength="50" value="" /> - </div> - - <p>Bitte beachte: Diese Anfrage allein berechtigt Dich noch nicht zur Teilnahme. Die Teilnahme ist erst nach Erhalt einer Bestätigungsmail von uns gültig!</p> - - <div class="form-field"> - <input type="submit" class="md-button" value="Teilnahmeanfrage abschicken" name="schicken" /> - </div> - </form> - </div> - `}; - - - document.getElementById('form-container').innerHTML = generateEventHTML(info, formattedDate, formattedStartTime, formattedEndTime); - let form = document.getElementById(`event-form`); - form.style.display = 'block'; - }, - - eventClassNames: function(arg) { - if (arg.event.start < new Date()) { - return ['past-event']; - } else { - return []; - } - }, + `}; + - allDaySlot: false, // Remove the "all-day" section from the calendar - slotMinTime: '07:00:00', // Beginning at 7am - slotMaxTime: '20:00:00', // Ending at 8pm - }); + document.getElementById('form-container').innerHTML = generateEventHTML(info, formattedDate, formattedStartTime, formattedEndTime); + let form = document.getElementById(`event-form`); + form.style.display = 'block'; + form.scrollIntoView({ behavior: 'smooth', block: 'center' }); + }, + + eventClassNames: function(arg) { + if (arg.event.start < new Date()) { + return ['past-event']; + } else { + return []; + } + }, + + allDaySlot: false, // Remove the "all-day" section from the calendar + slotMinTime: '07:00:00', // Beginning at 7am + slotMaxTime: '20:00:00', // Ending at 8pm + }); + + calendar.render(); + } else { + updateToolbarConfig(); + } +} + +// Initialize the calendar on page load +initializeCalendar(); + +// sets the toolbar and view depending on the width +function updateToolbarConfig() { + const config = getToolbarConfig(); + calendar.setOption('headerToolbar', config.toolbar); + +// If the configuration has the "view" key and it's set to "listYear", change the view + if (config.view === 'listYear') { + calendar.changeView(config.view); + } +} + +// adds a slight delay so that the change only occurs when the resize has been finished +function debounce(func, wait) { + let timeout; + return function() { + const context = this, args = arguments; + clearTimeout(timeout); + timeout = setTimeout(function() { + func.apply(context, args); + }, wait); + }; +} + +// Add the resize event listener +window.addEventListener('resize', debounce(function() { + updateToolbarConfig(); +}, 150)); // Waits for 150ms after the last resize event to re-initialize the calendar - calendar.render(); - //adjusts the height of the iframe to the height of the calendar or contact form (whatever is higher) - function adjustHeight() { - - var wrapper = document.querySelector('.calendar-wrapper'); +//adjusts the height of the iframe to the height of the calendar or contact form (whatever is higher) +function adjustHeight() { + + var wrapper = document.querySelector('.calendar-wrapper'); - // Initialize default height to 400 - var newHeight = 400; - var wrapperHeight = 400; + // Initialize default height to 400 + var newHeight = 400; + var wrapperHeight = 400; - if (wrapper) { - wrapperHeight = wrapper.offsetHeight; - } + if (wrapper) { + wrapperHeight = wrapper.offsetHeight; + } - newHeight = wrapperHeight + 10; + newHeight = wrapperHeight + 10; - console.log("newHeight:", newHeight) + console.log("newHeight:", newHeight) - // Directly set the height of the iframe in the parent - var iframeInParent = window.parent.document.getElementById('calendar'); - if (iframeInParent) { - iframeInParent.style.height = newHeight + 'px'; - } + // Directly set the height of the iframe in the parent + var iframeInParent = window.parent.document.getElementById('calendar'); + if (iframeInParent) { + iframeInParent.style.height = newHeight + 'px'; } +} - // triggers adjustHeight whenever calendar-wrapper changes height - var wrapper = document.querySelector('.calendar-wrapper'); - if (wrapper) { - var resizeObserver = new ResizeObserver(adjustHeight); - resizeObserver.observe(wrapper); - } - - // Show/Hide past events - function handlePastEventsVisibility() { - var view = calendar.view; - var displayStyle = view.type.includes('list') ? 'table-row' : 'block'; - var pastEvents = document.querySelectorAll('.past-event'); - pastEvents.forEach(function(eventEl) { - eventEl.style.display = showPastEvents ? displayStyle : 'none'; - }); - if (view.type.includes('list')) { - var pastDays = document.querySelectorAll('.fc-day-past'); - pastDays.forEach(function(dayEl) { - dayEl.style.display = showPastEvents ? 'table-row' : 'none'; - }); - } - var visibleEvents = calendar.getEvents(); - console.log("All visible events:", visibleEvents); - var multiDayEvents = visibleEvents.filter(function(event) { - var start = event.start; - var end = event.end || start; - return (end.getTime() - start.getTime()) > 86400000; +// triggers adjustHeight whenever calendar-wrapper changes height +var wrapper = document.querySelector('.calendar-wrapper'); + if (wrapper) { + var resizeObserver = new ResizeObserver(adjustHeight); + resizeObserver.observe(wrapper); + } + +// Show/Hide past events +function handlePastEventsVisibility() { + var view = calendar.view; + var displayStyle = view.type.includes('list') ? 'table-row' : 'block'; + var pastEvents = document.querySelectorAll('.past-event'); + pastEvents.forEach(function(eventEl) { + eventEl.style.display = showPastEvents ? displayStyle : 'none'; }); - console.log("Filtered multi-day events:", multiDayEvents); - + if (view.type.includes('list')) { + var pastDays = document.querySelectorAll('.fc-day-past'); + pastDays.forEach(function(dayEl) { + dayEl.style.display = showPastEvents ? 'table-row' : 'none'; + }); } + var visibleEvents = calendar.getEvents(); + console.log("All visible events:", visibleEvents); + var multiDayEvents = visibleEvents.filter(function(event) { + var start = event.start; + var end = event.end || start; + return (end.getTime() - start.getTime()) > 86400000; +}); +console.log("Filtered multi-day events:", multiDayEvents); + +} });