// js/calendar.js document.addEventListener('DOMContentLoaded', function () { const calendarEl = getElementOrThrow('calendar'); const modal = getElementOrThrow('event_modal'); let selected_start_string = null; const calendar = new FullCalendar.Calendar(calendarEl, { editable: true, locale: 'fr', //timeZone: 'local', // à modifier pour être à l'heure d'un autre pays initialView: 'dayGridMonth', headerToolbar: { left: 'prev,next today', center: 'title', //right: 'dayGridMonth,timeGridWeek,timeGridDay,listWeek' right: 'dayGridMonth,timeGridWeek,listWeek' }, slotMinWidth: 70, defaultAllDay: false, // numéros de semaine //weekNumbers: true, //weekText: 's', // vue mois contentHeight: 600, // après initialisation: calendar.setOption('contentHeight', 650); //aspectRatio: 1.5, // après initialisation: calendar.setOption('aspectRatio', 1.8); // pour recalculer la taille au redimensionnement du parent, exécuter: calendar.updateSize() stickyHeaderDates: true, // garder les en-tête de colonnes lors du scroll fixedWeekCount: false, // avec false, affiche 4, 5 ou 6 semaines selon le mois selectable: true, // sélection de jours en cliquant dessus longPressDelay: 300, // 1000ms par défaut navLinks: true, // numéros de jour et de semaines clicables // vue semaine slotEventOverlap: true, // superposition (limitée) de deux évènements simultanés allDayContent: 'Journée', // texte dans la case "toute la journée" nowIndicator: true, // barre rouge pour maintenant // params en plus: https://fullcalendar.io/docs/events-json-feed events: 'index.php?action=get_events', // fichier PHP qui retourne les événements select: function (info) { selected_start_string = info.startStr; // variable "globale" hideModal(); }, // sélection d'une date simple sur mobile, évite des problèmes de conflit avec eventClick dateClick: function (info) { if (window.matchMedia('(pointer: coarse)').matches) { const end = new Date(info.date.getTime()); calendar.view.type === 'dayGridMonth' ? end.setDate(end.getDate() + 1) : end.setMinutes(end.getMinutes() + 30); // vue date: la fin est une date exclue // vue semaine: durée de 30min par défaut calendar.select(info.date, end); // appeler select() avec un seul paramètre ne marche pas avec la vue "mois" } }, //unselect: function(event, view){}, eventClick: function (info) { if (!info.event.start || !info.event.end) { throw new Error('modale non conforme'); } const modal_view = new CalendarModalView({ mode: 'show', title: info.event.title, description: info.event.extendedProps.description, color: info.event.backgroundColor, all_day: info.event.allDay, start: info.event.start, end: info.event.end }); modal.innerHTML = modal_view.getView(); calendar.updateSize(); }, viewDidMount: function (_info) { hideModal(); if (selected_start_string) { calendar.gotoDate(new Date(selected_start_string)); } }, //datesSet: function(info){}, // déclenché lorsque des dates affichées sont chargées (= comme viewDidMount + changement de date) }); function hideModal() { modal.innerHTML = ''; calendar.updateSize(); } document.addEventListener('keydown', function (event) { if (event.key === 'Escape') { hideModal(); } }); // technique de la délégation d'événements pour utiliser un bouton ajouté dynamiquement document.addEventListener('click', function (event) { if (!event.target) { throw new Error('évènement click non conforme'); } assertElementType(event.target, HTMLElement); if (event.target.classList.contains('event_close_button')) { hideModal(); } }); calendar.render(); });