From e3a42c8342bba0db15e2ca9a78911121e5d539da Mon Sep 17 00:00:00 2001 From: polo Date: Thu, 29 Jan 2026 22:51:19 +0100 Subject: =?UTF-8?q?classe=20CalendarModalView,=20contr=C3=B4les=20getEleme?= =?UTF-8?q?ntOrThrow=20et=20assertElementType?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- public/js/calendar.js | 110 +++++++++++++++++++++----------------------------- 1 file changed, 46 insertions(+), 64 deletions(-) (limited to 'public/js/calendar.js') diff --git a/public/js/calendar.js b/public/js/calendar.js index a092632..ff1a401 100644 --- a/public/js/calendar.js +++ b/public/js/calendar.js @@ -1,115 +1,97 @@ // js/calendar.js -document.addEventListener('DOMContentLoaded', function(){ - const calendarEl = document.getElementById('calendar'); +document.addEventListener('DOMContentLoaded', function () { + const calendarEl = getElementOrThrow('calendar'); + const modal = getElementOrThrow('event_modal'); let selected_start_string = null; - - const calendar = new FullCalendar.Calendar(calendarEl,{ + const calendar = new FullCalendar.Calendar(calendarEl, { editable: true, locale: 'fr', //timeZone: 'local', // à modifier pour être à l'heure d'un autre pays initialView: 'dayGridMonth', - headerToolbar:{ + headerToolbar: { left: 'prev,next today', center: 'title', - right: 'dayGridMonth,timeGridWeek,timeGridDay,listWeek' - //right: 'dayGridMonth,timeGridWeek' + //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 multiples + 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){ + select: function (info) { selected_start_string = info.startStr; // variable "globale" hideModal(); }, - //unselect: function(event, view){}, - - eventClick: function(info){ - const aside = document.querySelector('aside'); - const checked = info.event.allDay ? 'checked' : ''; - - // change des objets Date en chaînes compatibles avec les input - function formatDate(date){ - return date.getFullYear() + '-' + (date.getMonth() + 1).toString().padStart(2, '0') + '-' + date.getDate().toString().padStart(2, '0') - + (info.event.allDay ? '' : 'T' + date.getHours().toString().padStart(2, '0') + ':' + date.getMinutes().toString().padStart(2, '0')); - } - function minusOneDay(date){ - date.setDate(date.getDate() - 1); // jour de fin modifié pour ne pas faire bizarre pour l'utilisateur - return date; - } - - const start = formatDate(info.event.start); - const start_date = start.split('T')[0]; - const start_hour = (info.event.allDay ? '' : '
à ' + start.split('T')[1]).replace(":", "h"); - const formated_start = start_date.split('-')[2] + '/' + start_date.split('-')[1] + '/' + start_date.split('-')[0] + start_hour; - const end = formatDate(info.event.allDay ? minusOneDay(info.event.end) : info.event.end, info.event.allDay); - const end_date = end.split('T')[0]; - const end_hour = (info.event.allDay ? '' : '
à ' + end.split('T')[1]).replace(":", "h"); - const formated_end = end_date.split('-')[2] + '/' + end_date.split('-')[1] + '/' + end_date.split('-')[0] + end_hour; - - let aside_content = `
-

` + info.event.title + `

-

` + info.event.extendedProps.description + `

`; - if(checked && (formated_start === formated_end)){ // affichage simplifié évènement d'un jour - aside_content = aside_content + `

le ` + formated_start + `

-
`; + // 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" } - else{ - aside_content = aside_content + `

du ` + formated_start + `

-

au ` + formated_end + `

- `; + }, + //unselect: function(event, view){}, + eventClick: function (info) { + if (!info.event.start || !info.event.end) { + throw new Error('modale non conforme'); } - - aside.innerHTML = aside_content; + 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){ // déclenché lorsque qu'une nouvelle vue est chargée (mois, semaine...) - if(selected_start_string){ + 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(){ - const aside = document.querySelector('aside'); - aside.innerHTML = ''; + function hideModal() { + modal.innerHTML = ''; calendar.updateSize(); } - - document.addEventListener('keydown', function(event){ - if(event.key === 'Escape') { + 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.classList.contains('event_close_button')){ + 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(); }); \ No newline at end of file -- cgit v1.2.3