Skip to content
Snippets Groups Projects
Commit 3990758d authored by Torben Böhnke's avatar Torben Böhnke
Browse files

Kalender Demo Update

- weniger buttons und nur listYear-view auf kleinen displays (>= 768px width)
- - passt sich auch nachträglichen width veränderungen an
- scrollt automatisch hoch, wenn contactform erscheint nach Klick
parent 0029f6e6
No related branches found
No related tags found
No related merge requests found
......@@ -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);
}
});
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment