aboutsummaryrefslogtreecommitdiff
path: root/public/js
diff options
context:
space:
mode:
authorpolo <ordipolo@gmx.fr>2026-01-15 23:14:05 +0100
committerpolo <ordipolo@gmx.fr>2026-01-15 23:14:05 +0100
commit600fbca86951c28b4cf96a93b1a5fe5ba6149161 (patch)
tree8035923f595cce6ef98598c072ec3297569c0dde /public/js
parent972d0c1e95894898f6d34bebb811a2637b4e1c5a (diff)
downloadcms-600fbca86951c28b4cf96a93b1a5fe5ba6149161.tar.gz
cms-600fbca86951c28b4cf96a93b1a5fe5ba6149161.tar.bz2
cms-600fbca86951c28b4cf96a93b1a5fe5ba6149161.zip
amélioration code calendar.jsHEADmain
Diffstat (limited to 'public/js')
-rw-r--r--public/js/calendar.js27
-rw-r--r--public/js/calendar_admin.js82
-rw-r--r--public/js/main.js17
3 files changed, 94 insertions, 32 deletions
diff --git a/public/js/calendar.js b/public/js/calendar.js
index 8809246..b3aa927 100644
--- a/public/js/calendar.js
+++ b/public/js/calendar.js
@@ -1,7 +1,7 @@
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 let selected_start_string = null; 5 let selected_start_string = null;
6 6
7 const calendar = new FullCalendar.Calendar(calendarEl,{ 7 const calendar = new FullCalendar.Calendar(calendarEl,{
@@ -58,7 +58,10 @@ document.addEventListener('DOMContentLoaded', function(){
58 //unselect: function(event, view){}, 58 //unselect: function(event, view){},
59 59
60 eventClick: function(info){ 60 eventClick: function(info){
61 const aside = document.querySelector('aside'); 61 const modal = getElementOrThrow('event_modal');
62 if(!info.event.start || !info.event.end){
63 throw new Error('modale non conforme');
64 }
62 const checked = info.event.allDay ? 'checked' : ''; 65 const checked = info.event.allDay ? 'checked' : '';
63 66
64 // change des objets Date en chaînes compatibles avec les input 67 // change des objets Date en chaînes compatibles avec les input
@@ -75,25 +78,25 @@ document.addEventListener('DOMContentLoaded', function(){
75 const start_date = start.split('T')[0]; 78 const start_date = start.split('T')[0];
76 const start_hour = (info.event.allDay ? '' : '<br>à ' + start.split('T')[1]).replace(":", "h"); 79 const start_hour = (info.event.allDay ? '' : '<br>à ' + start.split('T')[1]).replace(":", "h");
77 const formated_start = start_date.split('-')[2] + '/' + start_date.split('-')[1] + '/' + start_date.split('-')[0] + start_hour; 80 const formated_start = start_date.split('-')[2] + '/' + start_date.split('-')[1] + '/' + start_date.split('-')[0] + start_hour;
78 const end = formatDate(info.event.allDay ? minusOneDay(info.event.end) : info.event.end, info.event.allDay); 81 const end = formatDate(info.event.allDay ? minusOneDay(info.event.end) : info.event.end);
79 const end_date = end.split('T')[0]; 82 const end_date = end.split('T')[0];
80 const end_hour = (info.event.allDay ? '' : '<br>à ' + end.split('T')[1]).replace(":", "h"); 83 const end_hour = (info.event.allDay ? '' : '<br>à ' + end.split('T')[1]).replace(":", "h");
81 const formated_end = end_date.split('-')[2] + '/' + end_date.split('-')[1] + '/' + end_date.split('-')[0] + end_hour; 84 const formated_end = end_date.split('-')[2] + '/' + end_date.split('-')[1] + '/' + end_date.split('-')[0] + end_hour;
82 85
83 let aside_content = `<div id="event" style="border-color: ` + info.event.backgroundColor +`;"> 86 let modal_content = `<div id="event" style="border-color: ` + info.event.backgroundColor +`;">
84 <h3>` + info.event.title + `</h3> 87 <h3>` + info.event.title + `</h3>
85 <p><i>` + info.event.extendedProps.description + `</i></p>`; 88 <p><i>` + info.event.extendedProps.description + `</i></p>`;
86 if(checked && (formated_start === formated_end)){ // affichage simplifié évènement d'un jour 89 if(checked && (formated_start === formated_end)){ // affichage simplifié évènement d'un jour
87 aside_content = aside_content + `<p>le ` + formated_start + `</p>`; 90 modal_content = modal_content + `<p>le ` + formated_start + `</p>`;
88 } 91 }
89 else{ 92 else{
90 aside_content = aside_content + `<p>du ` + formated_start + `</p> 93 modal_content = modal_content + `<p>du ` + formated_start + `</p>
91 <p>au ` + formated_end + `</p>`; 94 <p>au ` + formated_end + `</p>`;
92 } 95 }
93 aside_content += `<button class="event_close_button">Fermer</button> 96 modal_content += `<button class="event_close_button">Fermer</button>
94 </div>`; 97 </div>`;
95 98
96 aside.innerHTML = aside_content; 99 modal.innerHTML = modal_content;
97 calendar.updateSize(); 100 calendar.updateSize();
98 }, 101 },
99 viewDidMount: function(info){ // déclenché lorsque qu'une nouvelle vue est chargée (mois, semaine...) 102 viewDidMount: function(info){ // déclenché lorsque qu'une nouvelle vue est chargée (mois, semaine...)
@@ -105,8 +108,8 @@ document.addEventListener('DOMContentLoaded', function(){
105 }); 108 });
106 109
107 function hideModal(){ 110 function hideModal(){
108 const aside = document.querySelector('aside'); 111 const modal = getElementOrThrow('event_modal');
109 aside.innerHTML = ''; 112 modal.innerHTML = '';
110 calendar.updateSize(); 113 calendar.updateSize();
111 } 114 }
112 115
@@ -118,6 +121,10 @@ document.addEventListener('DOMContentLoaded', function(){
118 121
119 // technique de la délégation d'événements pour utiliser un bouton ajouté dynamiquement 122 // technique de la délégation d'événements pour utiliser un bouton ajouté dynamiquement
120 document.addEventListener('click', function(event){ 123 document.addEventListener('click', function(event){
124 if(!event.target){
125 throw new Error('évènement click non conforme');
126 }
127 assertElementType(event.target, HTMLElement);
121 if(event.target.classList.contains('event_close_button')){ 128 if(event.target.classList.contains('event_close_button')){
122 hideModal(); 129 hideModal();
123 } 130 }
diff --git a/public/js/calendar_admin.js b/public/js/calendar_admin.js
index 17ae0c2..0600954 100644
--- a/public/js/calendar_admin.js
+++ b/public/js/calendar_admin.js
@@ -1,7 +1,7 @@
1// js/calendar_admin.js 1// js/calendar_admin.js
2 2
3document.addEventListener('DOMContentLoaded', function(){ 3document.addEventListener('DOMContentLoaded', function(){
4 const calendarEl = document.getElementById('calendar'); 4 const calendarEl = getElementOrThrow('calendar');
5 let selected_start_string = null; 5 let selected_start_string = null;
6 let event_selected = false; // pour event.remove() 6 let event_selected = false; // pour event.remove()
7 7
@@ -44,7 +44,7 @@ document.addEventListener('DOMContentLoaded', function(){
44 select: function(info){ 44 select: function(info){
45 selected_start_string = info.startStr; // variable "globale" 45 selected_start_string = info.startStr; // variable "globale"
46 event_selected = false; 46 event_selected = false;
47 const aside = document.querySelector('aside'); 47 const modal = getElementOrThrow('event_modal');
48 let checked = ''; 48 let checked = '';
49 let input = 'datetime-local'; 49 let input = 'datetime-local';
50 50
@@ -81,7 +81,7 @@ document.addEventListener('DOMContentLoaded', function(){
81 } 81 }
82 } 82 }
83 83
84 const aside_content = `<div id="form_event"> 84 const modal_content = `<div id="form_event">
85 <div class="event_title_box"> 85 <div class="event_title_box">
86 <h2>Nouvel évènement</h2> 86 <h2>Nouvel évènement</h2>
87 </div> 87 </div>
@@ -112,7 +112,7 @@ document.addEventListener('DOMContentLoaded', function(){
112 <button class="submit_new_event">Enregistrer</button> 112 <button class="submit_new_event">Enregistrer</button>
113 <button class="event_close_button">Annuler</button> 113 <button class="event_close_button">Annuler</button>
114 </div>`; 114 </div>`;
115 aside.innerHTML = aside_content; 115 modal.innerHTML = modal_content;
116 calendar.updateSize(); 116 calendar.updateSize();
117 }, 117 },
118 // sélection d'une date simple sur mobile, évite des problèmes de conflit avec eventClick 118 // sélection d'une date simple sur mobile, évite des problèmes de conflit avec eventClick
@@ -138,7 +138,7 @@ document.addEventListener('DOMContentLoaded', function(){
138 //unselect: function(event, view){}, 138 //unselect: function(event, view){},
139 eventClick: function(info){ 139 eventClick: function(info){
140 event_selected = true; // variable "globale" 140 event_selected = true; // variable "globale"
141 const aside = document.querySelector('aside'); 141 const modal = getElementOrThrow('event_modal');
142 const checked = info.event.allDay ? 'checked' : ''; 142 const checked = info.event.allDay ? 'checked' : '';
143 const input = info.event.allDay ? 'date' : 'datetime-local'; 143 const input = info.event.allDay ? 'date' : 'datetime-local';
144 144
@@ -153,9 +153,9 @@ document.addEventListener('DOMContentLoaded', function(){
153 } 153 }
154 154
155 const formated_start = formatDate(info.event.start); 155 const formated_start = formatDate(info.event.start);
156 const formated_end = formatDate(info.event.allDay ? minusOneDay(info.event.end) : info.event.end, info.event.allDay); 156 const formated_end = formatDate(info.event.allDay ? minusOneDay(info.event.end) : info.event.end);
157 157
158 const aside_content = `<div id="form_event" style="border-color: ` + info.event.backgroundColor +`;"> 158 const modal_content = `<div id="form_event" style="border-color: ` + info.event.backgroundColor +`;">
159 <div class="event_title_box"> 159 <div class="event_title_box">
160 <h2>Modifier un évènement</h2> 160 <h2>Modifier un évènement</h2>
161 </div> 161 </div>
@@ -188,7 +188,7 @@ document.addEventListener('DOMContentLoaded', function(){
188 <button class="event_close_button">Annuler</button> 188 <button class="event_close_button">Annuler</button>
189 <button class="delete_event">Supprimer</button> 189 <button class="delete_event">Supprimer</button>
190 </div>`; 190 </div>`;
191 aside.innerHTML = aside_content; 191 modal.innerHTML = modal_content;
192 calendar.updateSize(); 192 calendar.updateSize();
193 }, 193 },
194 viewDidMount: function(info){ // déclenché lorsque qu'une nouvelle vue est chargée (mois, semaine...) 194 viewDidMount: function(info){ // déclenché lorsque qu'une nouvelle vue est chargée (mois, semaine...)
@@ -200,21 +200,41 @@ document.addEventListener('DOMContentLoaded', function(){
200 }); 200 });
201 201
202 function hideModal(){ 202 function hideModal(){
203 const aside = document.querySelector('aside'); 203 const modal = getElementOrThrow('event_modal');
204 event_selected = false; 204 event_selected = false;
205 aside.innerHTML = ''; 205 modal.innerHTML = '';
206 calendar.updateSize(); 206 calendar.updateSize();
207 } 207 }
208 208
209 function submitEvent(new_event){ 209 function submitEvent(new_event){
210 const event_title = document.getElementById('event_title').value; 210 const event_title_input = getElementOrThrow('event_title');
211 const event_description = document.getElementById('event_description').value; 211 const event_description_input = getElementOrThrow('event_description');
212 const event_all_day = document.getElementById('event_all_day').checked; 212 const event_all_day_input = getElementOrThrow('event_all_day');
213 let event_start = document.getElementById('event_start').value; 213 const event_start_input = getElementOrThrow('event_start');
214 let event_end = document.getElementById('event_end').value; 214 const event_end_input = getElementOrThrow('event_end');
215 const event_color = document.getElementById('event_color').value; // #3788d8 par défaut 215 const event_color_input = getElementOrThrow('event_color');
216 const event_id = new_event ? '' : document.getElementById('event_id').value; 216 assertElementType(event_title_input, HTMLInputElement);
217 assertElementType(event_description_input, HTMLTextAreaElement);
218 assertElementType(event_all_day_input, HTMLInputElement);
219 assertElementType(event_start_input, HTMLInputElement);
220 assertElementType(event_end_input, HTMLInputElement);
221 assertElementType(event_color_input, HTMLInputElement);
217 222
223 const event_title = event_title_input.value;
224 const event_description = event_description_input.value;
225 const event_all_day = event_all_day_input.checked;
226 let event_start = event_start_input.value;
227 let event_end = event_end_input.value;
228 const event_color = event_color_input.value; // #3788d8 par défaut
229
230 let event_id = '';
231 if(!new_event){
232 const event_id_input = getElementOrThrow('event_id');
233 assertElementType(event_id_input, HTMLInputElement);
234 event_id = event_id_input.value;
235 }
236
237 // contrôle de saisie
218 if(event_title.length !== 0 && event_start.length !== 0 && event_end.length !== 0 && event_color.length !== 0 238 if(event_title.length !== 0 && event_start.length !== 0 && event_end.length !== 0 && event_color.length !== 0
219 && (new_event || event_id.length !== 0)) 239 && (new_event || event_id.length !== 0))
220 { 240 {
@@ -238,6 +258,7 @@ document.addEventListener('DOMContentLoaded', function(){
238 // création 258 // création
239 if(new_event){ 259 if(new_event){
240 const event = { 260 const event = {
261 id: '',
241 title: event_title, 262 title: event_title,
242 description: event_description, 263 description: event_description,
243 allDay: event_all_day, 264 allDay: event_all_day,
@@ -269,7 +290,9 @@ document.addEventListener('DOMContentLoaded', function(){
269 // modification 290 // modification
270 else{ 291 else{
271 const event = calendar.getEventById(event_id); 292 const event = calendar.getEventById(event_id);
272 293 if(!event){
294 throw new Error("Événement non trouvé !");
295 }
273 if(event){ 296 if(event){
274 const event_copy = { 297 const event_copy = {
275 id: parseInt(event.id), 298 id: parseInt(event.id),
@@ -316,13 +339,17 @@ document.addEventListener('DOMContentLoaded', function(){
316 } 339 }
317 340
318 function checkAllDay(){ 341 function checkAllDay(){
319 const event_start_input = document.getElementById('event_start'); 342 const event_start_input = getElementOrThrow('event_start');
320 const event_end_input = document.getElementById('event_end'); 343 const event_end_input = getElementOrThrow('event_end');
344 const event_all_day = getElementOrThrow('event_all_day');
345 assertElementType(event_start_input, HTMLInputElement);
346 assertElementType(event_end_input, HTMLInputElement);
347 assertElementType(event_all_day, HTMLInputElement);
321 348
322 const start = event_start_input.value; 349 const start = event_start_input.value;
323 const end = event_end_input.value; 350 const end = event_end_input.value;
324 351
325 if(document.getElementById('event_all_day').checked){ 352 if(event_all_day.checked){
326 event_start_input.type = 'date'; 353 event_start_input.type = 'date';
327 event_end_input.type = 'date'; 354 event_end_input.type = 'date';
328 355
@@ -341,8 +368,15 @@ document.addEventListener('DOMContentLoaded', function(){
341 if(!confirm("Voulez-vous vraiment supprimer cet évènement du calendrier?")){ 368 if(!confirm("Voulez-vous vraiment supprimer cet évènement du calendrier?")){
342 return; 369 return;
343 } 370 }
344 const event_id = document.getElementById('event_id').value; 371 const event_tag = document.getElementById('event_id'); // cible input hidden
372 if(!event_tag || !(event_tag instanceof HTMLInputElement)){
373 return;
374 }
375 const event_id = event_tag.value;
345 const event = calendar.getEventById(event_id); 376 const event = calendar.getEventById(event_id);
377 if(!event){
378 throw new Error("Événement non trouvé !");
379 }
346 380
347 fetch('index.php?action=remove_event', { 381 fetch('index.php?action=remove_event', {
348 method: 'POST', 382 method: 'POST',
@@ -377,6 +411,10 @@ document.addEventListener('DOMContentLoaded', function(){
377 // boutons dans la "modale" 411 // boutons dans la "modale"
378 // technique de la délégation d'événements pour utiliser un bouton ajouté dynamiquement 412 // technique de la délégation d'événements pour utiliser un bouton ajouté dynamiquement
379 document.addEventListener('click', function(event){ 413 document.addEventListener('click', function(event){
414 if(!event.target){
415 throw new Error('évènement click non conforme');
416 }
417 assertElementType(event.target, HTMLElement);
380 if(event.target.classList.contains('event_close_button')){ 418 if(event.target.classList.contains('event_close_button')){
381 hideModal(); 419 hideModal();
382 } 420 }
diff --git a/public/js/main.js b/public/js/main.js
index c8e10b0..825699f 100644
--- a/public/js/main.js
+++ b/public/js/main.js
@@ -36,6 +36,23 @@ function toastNotify(message){
36 setTimeout(function(){ toast.className = toast.className.replace('show', ''); }, 5000); 36 setTimeout(function(){ toast.className = toast.className.replace('show', ''); }, 5000);
37} 37}
38 38
39
40// réussite de getElementById
41function getElementOrThrow(id) {
42 const elem = document.getElementById(id);
43 if (!elem) {
44 throw new Error("l'élément d'id: " + id + " non trouvé");
45 }
46 return elem;
47}
48// l'erreur attribut "value" non trouvé devient l'élement attrapé n'a pas le bon type (c'est un peu plus clair)
49function assertElementType(elem, ctor) {
50 if (!(elem instanceof ctor)) {
51 throw new Error(`l'élement attrapé n'a pas le bon type. type attendu: ${ctor.name}, type obtenu: ${elem.tagName}`);
52 }
53}
54
55
39function controlURL(input){ 56function controlURL(input){
40 const url = input.value.trim(); 57 const url = input.value.trim();
41 if(!url){ 58 if(!url){