summaryrefslogtreecommitdiff
path: root/public/js/calendar.js
diff options
context:
space:
mode:
authorpolo <ordipolo@gmx.fr>2026-01-29 22:51:19 +0100
committerpolo <ordipolo@gmx.fr>2026-01-29 22:51:19 +0100
commite3a42c8342bba0db15e2ca9a78911121e5d539da (patch)
treedf2b669452ba82774d741a4b9e48948b8dc45a0a /public/js/calendar.js
parentf007bac3b9172711dc0fcca1306270ab99dbd8a4 (diff)
downloadfullcalendar-e3a42c8342bba0db15e2ca9a78911121e5d539da.tar.gz
fullcalendar-e3a42c8342bba0db15e2ca9a78911121e5d539da.tar.bz2
fullcalendar-e3a42c8342bba0db15e2ca9a78911121e5d539da.zip
classe CalendarModalView, contrôles getElementOrThrow et assertElementTypeHEADmaster
Diffstat (limited to 'public/js/calendar.js')
-rw-r--r--public/js/calendar.js110
1 files changed, 46 insertions, 64 deletions
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 @@
1// js/calendar.js 1// js/calendar.js
2 2
3document.addEventListener('DOMContentLoaded', function(){ 3document.addEventListener('DOMContentLoaded', function () {
4 const calendarEl = document.getElementById('calendar'); 4 const calendarEl = getElementOrThrow('calendar');
5 const modal = getElementOrThrow('event_modal');
5 let selected_start_string = null; 6 let selected_start_string = null;
6 7 const calendar = new FullCalendar.Calendar(calendarEl, {
7 const calendar = new FullCalendar.Calendar(calendarEl,{
8 editable: true, 8 editable: true,
9 locale: 'fr', 9 locale: 'fr',
10 //timeZone: 'local', // à modifier pour être à l'heure d'un autre pays 10 //timeZone: 'local', // à modifier pour être à l'heure d'un autre pays
11 initialView: 'dayGridMonth', 11 initialView: 'dayGridMonth',
12 headerToolbar:{ 12 headerToolbar: {
13 left: 'prev,next today', 13 left: 'prev,next today',
14 center: 'title', 14 center: 'title',
15 right: 'dayGridMonth,timeGridWeek,timeGridDay,listWeek' 15 //right: 'dayGridMonth,timeGridWeek,timeGridDay,listWeek'
16 //right: 'dayGridMonth,timeGridWeek' 16 right: 'dayGridMonth,timeGridWeek,listWeek'
17 }, 17 },
18 slotMinWidth: 70, 18 slotMinWidth: 70,
19 defaultAllDay: false, 19 defaultAllDay: false,
20
21 // numéros de semaine 20 // numéros de semaine
22 //weekNumbers: true, 21 //weekNumbers: true,
23 //weekText: 's', 22 //weekText: 's',
24
25 // vue mois 23 // vue mois
26 contentHeight: 600, // après initialisation: calendar.setOption('contentHeight', 650); 24 contentHeight: 600, // après initialisation: calendar.setOption('contentHeight', 650);
27 //aspectRatio: 1.5, // après initialisation: calendar.setOption('aspectRatio', 1.8); 25 //aspectRatio: 1.5, // après initialisation: calendar.setOption('aspectRatio', 1.8);
28 // pour recalculer la taille au redimensionnement du parent, exécuter: calendar.updateSize() 26 // pour recalculer la taille au redimensionnement du parent, exécuter: calendar.updateSize()
29 stickyHeaderDates: true, // garder les en-tête de colonnes lors du scroll 27 stickyHeaderDates: true, // garder les en-tête de colonnes lors du scroll
30 fixedWeekCount: false, // avec false, affiche 4, 5 ou 6 semaines selon le mois 28 fixedWeekCount: false, // avec false, affiche 4, 5 ou 6 semaines selon le mois
31 selectable: true, // sélection de jours multiples 29 selectable: true, // sélection de jours en cliquant dessus
30 longPressDelay: 300, // 1000ms par défaut
32 navLinks: true, // numéros de jour et de semaines clicables 31 navLinks: true, // numéros de jour et de semaines clicables
33
34 // vue semaine 32 // vue semaine
35 slotEventOverlap: true, // superposition (limitée) de deux évènements simultanés 33 slotEventOverlap: true, // superposition (limitée) de deux évènements simultanés
36 allDayContent: 'Journée', // texte dans la case "toute la journée" 34 allDayContent: 'Journée', // texte dans la case "toute la journée"
37 nowIndicator: true, // barre rouge pour maintenant 35 nowIndicator: true, // barre rouge pour maintenant
38
39 // params en plus: https://fullcalendar.io/docs/events-json-feed 36 // params en plus: https://fullcalendar.io/docs/events-json-feed
40 events: 'index.php?action=get_events', // fichier PHP qui retourne les événements 37 events: 'index.php?action=get_events', // fichier PHP qui retourne les événements
41 38 select: function (info) {
42 select: function(info){
43 selected_start_string = info.startStr; // variable "globale" 39 selected_start_string = info.startStr; // variable "globale"
44 hideModal(); 40 hideModal();
45 }, 41 },
46 //unselect: function(event, view){}, 42 // sélection d'une date simple sur mobile, évite des problèmes de conflit avec eventClick
47 43 dateClick: function (info) {
48 eventClick: function(info){ 44 if (window.matchMedia('(pointer: coarse)').matches) {
49 const aside = document.querySelector('aside'); 45 const end = new Date(info.date.getTime());
50 const checked = info.event.allDay ? 'checked' : ''; 46 calendar.view.type === 'dayGridMonth' ? end.setDate(end.getDate() + 1) : end.setMinutes(end.getMinutes() + 30);
51 47 // vue date: la fin est une date exclue
52 // change des objets Date en chaînes compatibles avec les input 48 // vue semaine: durée de 30min par défaut
53 function formatDate(date){ 49 calendar.select(info.date, end); // appeler select() avec un seul paramètre ne marche pas avec la vue "mois"
54 return date.getFullYear() + '-' + (date.getMonth() + 1).toString().padStart(2, '0') + '-' + date.getDate().toString().padStart(2, '0')
55 + (info.event.allDay ? '' : 'T' + date.getHours().toString().padStart(2, '0') + ':' + date.getMinutes().toString().padStart(2, '0'));
56 }
57 function minusOneDay(date){
58 date.setDate(date.getDate() - 1); // jour de fin modifié pour ne pas faire bizarre pour l'utilisateur
59 return date;
60 }
61
62 const start = formatDate(info.event.start);
63 const start_date = start.split('T')[0];
64 const start_hour = (info.event.allDay ? '' : '<br>à ' + start.split('T')[1]).replace(":", "h");
65 const formated_start = start_date.split('-')[2] + '/' + start_date.split('-')[1] + '/' + start_date.split('-')[0] + start_hour;
66 const end = formatDate(info.event.allDay ? minusOneDay(info.event.end) : info.event.end, info.event.allDay);
67 const end_date = end.split('T')[0];
68 const end_hour = (info.event.allDay ? '' : '<br>à ' + end.split('T')[1]).replace(":", "h");
69 const formated_end = end_date.split('-')[2] + '/' + end_date.split('-')[1] + '/' + end_date.split('-')[0] + end_hour;
70
71 let aside_content = `<div class="event" style="border-color: ` + info.event.backgroundColor +`;">
72 <h3>` + info.event.title + `</h3>
73 <p><i>` + info.event.extendedProps.description + `</i></p>`;
74 if(checked && (formated_start === formated_end)){ // affichage simplifié évènement d'un jour
75 aside_content = aside_content + `<p>le ` + formated_start + `</p>
76 </div>`;
77 } 50 }
78 else{ 51 },
79 aside_content = aside_content + `<p>du ` + formated_start + `</p> 52 //unselect: function(event, view){},
80 <p>au ` + formated_end + `</p> 53 eventClick: function (info) {
81 </div>`; 54 if (!info.event.start || !info.event.end) {
55 throw new Error('modale non conforme');
82 } 56 }
83 57 const modal_view = new CalendarModalView({
84 aside.innerHTML = aside_content; 58 mode: 'show',
59 title: info.event.title,
60 description: info.event.extendedProps.description,
61 color: info.event.backgroundColor,
62 all_day: info.event.allDay,
63 start: info.event.start,
64 end: info.event.end
65 });
66 modal.innerHTML = modal_view.getView();
85 calendar.updateSize(); 67 calendar.updateSize();
86 }, 68 },
87 viewDidMount: function(info){ // déclenché lorsque qu'une nouvelle vue est chargée (mois, semaine...) 69 viewDidMount: function (_info) {
88 if(selected_start_string){ 70 hideModal();
71 if (selected_start_string) {
89 calendar.gotoDate(new Date(selected_start_string)); 72 calendar.gotoDate(new Date(selected_start_string));
90 } 73 }
91 }, 74 },
92 //datesSet: function(info){}, // déclenché lorsque des dates affichées sont chargées (= comme viewDidMount + changement de date) 75 //datesSet: function(info){}, // déclenché lorsque des dates affichées sont chargées (= comme viewDidMount + changement de date)
93 }); 76 });
94 77 function hideModal() {
95 function hideModal(){ 78 modal.innerHTML = '';
96 const aside = document.querySelector('aside');
97 aside.innerHTML = '';
98 calendar.updateSize(); 79 calendar.updateSize();
99 } 80 }
100 81 document.addEventListener('keydown', function (event) {
101 document.addEventListener('keydown', function(event){ 82 if (event.key === 'Escape') {
102 if(event.key === 'Escape') {
103 hideModal(); 83 hideModal();
104 } 84 }
105 }); 85 });
106
107 // technique de la délégation d'événements pour utiliser un bouton ajouté dynamiquement 86 // technique de la délégation d'événements pour utiliser un bouton ajouté dynamiquement
108 document.addEventListener('click', function(event){ 87 document.addEventListener('click', function (event) {
109 if(event.target.classList.contains('event_close_button')){ 88 if (!event.target) {
89 throw new Error('évènement click non conforme');
90 }
91 assertElementType(event.target, HTMLElement);
92 if (event.target.classList.contains('event_close_button')) {
110 hideModal(); 93 hideModal();
111 } 94 }
112 }); 95 });
113
114 calendar.render(); 96 calendar.render();
115}); \ No newline at end of file 97}); \ No newline at end of file