From bce9fda51d334a547ec5a48f0b7699ed3b5d7944 Mon Sep 17 00:00:00 2001 From: polo Date: Wed, 29 Oct 2025 21:42:39 +0100 Subject: =?UTF-8?q?classe=20Fetcher,=20gestion=20r=C3=A9seaux=20sociaux=20?= =?UTF-8?q?pr=C3=A9sents/absents,=20partie=202?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- public/css/head.css | 2 +- public/js/Fetcher.js | 51 +++++++++++++++++++++++++ public/js/Input.js | 105 ++++++++++++++++++++++----------------------------- public/js/main.js | 21 +++++++++++ 4 files changed, 119 insertions(+), 60 deletions(-) create mode 100644 public/js/Fetcher.js (limited to 'public') diff --git a/public/css/head.css b/public/css/head.css index b5f1bd1..1844f93 100644 --- a/public/css/head.css +++ b/public/css/head.css @@ -87,7 +87,7 @@ header a gap: 4px; flex-wrap: wrap; } -#header_social_content img +#header_social_content a img { width: 28px; background-color: #ffffffb3; diff --git a/public/js/Fetcher.js b/public/js/Fetcher.js new file mode 100644 index 0000000..0f56628 --- /dev/null +++ b/public/js/Fetcher.js @@ -0,0 +1,51 @@ +class Fetcher{ + constructor(options = {}) { + this.endpoint = options.endpoint || 'index.php'; + this.method = options.method || 'POST'; // normalement c'est GET par défaut + + // Callbacks optionnels + this.onSuccess = options.onSuccess || null; + this.onFailure = options.onFailure || null; + //this.onError = options.onError || null; // Pour les erreurs réseau/parsing + } + + send(body){ + const options = { method: this.method }; + + if(this.method !== 'GET'){ // si GET, ni body ni headers + if(body instanceof FormData){ // pas de headers + options.body = body; + } + else if(body !== null && typeof body === 'object'){ // objet => json + options.headers = { 'Content-Type': 'application/json' }; + options.body = JSON.stringify(body); + } + else{ // blob? + options.body = body; + } + } + + return fetch(this.endpoint, options) + .then(response => response.json()) + .then(data => this.onResponse(data)) + .catch(error => { + console.error('Erreur:', error); + }); + } + + onResponse(data){ + if(data.success){ + if(this.onSuccess){ + this.onSuccess(data); + } + return{ success: true, data }; + } + else{ + if(this.onFailure){ + this.onFailure(data); + } + console.error(data.message || "Erreur serveur"); + return { success: false, data }; + } + } +} \ No newline at end of file diff --git a/public/js/Input.js b/public/js/Input.js index 54872d1..0ebbbbb 100644 --- a/public/js/Input.js +++ b/public/js/Input.js @@ -1,9 +1,10 @@ +// mère class InputToggler{ constructor(name, options = {}){ this.name = name; this.parent = document.getElementById(name); - // ids alternatifs optionnels + // des ids alternatifs sont possibles this.content_elem = this.parent.querySelector(options.content_selector || `#${name}_content`); this.input_elem = this.parent.querySelector(options.input_selector || `#${name}_input`); this.open_elem = this.parent.querySelector(options.open_selector || `#${name}_open`); @@ -39,34 +40,26 @@ class InputToggler{ } } + +// enfants class InputText extends InputToggler{ constructor(name, options = {}){ super(name, options); - this.fetch_endpoint = options.endpoint || 'index.php'; - this.fetch_key = options.fetch_key || 'head_foot_text'; + this.fetcher = new Fetcher({ + endpoint: (options.endpoint || 'index.php?') + (options.fetch_key || 'head_foot_text=') + this.name, + method: 'POST', + onSuccess: (data) => this.onSuccess(data) + }); } submit(){ - fetch(this.fetch_endpoint + '?' + this.fetch_key + '=' + this.name, { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({new_text: this.input_elem.value}) - }) - .then(response => response.json()) - .then(data => { - if(data.success){ - this.onSuccess(data); - this.close(); - } - else{ - console.error("Erreur: le serveur n'a pas enregistré le nouveau texte."); - } - }) - .catch(error => { - console.error('Erreur:', error); - }); + this.fetcher.send({new_text: this.input_elem.value}) + .then(result => { + toastNotify(result.success ? 'texte modifié avec succès' : "erreur: la modification des données côté serveur a échoué"); + }); } onSuccess(data){ this.content_elem.innerHTML = this.input_elem.value; + this.close(); } cancel(){ this.input_elem.value = this.content_elem.innerHTML; @@ -74,29 +67,15 @@ class InputText extends InputToggler{ } } -class InputTextSocialNetwork extends InputText{ - open(){ - const elem_parent = this.content_elem.parentNode; - if(elem_parent.tagName.toLowerCase() === 'a'){ - this.input_elem.value = elem_parent.href; - } - super.open(); - } - onSuccess(data){ - if(this.input_elem.value){ - this.content_elem.parentNode.href = this.input_elem.value; - } - else{ - this.content_elem.parentNode.removeAttribute('href'); - } - } -} - class InputFile extends InputToggler{ constructor(name, options = {}){ super(name, options); - this.fetch_endpoint = options.endpoint || 'index.php'; - this.fetch_key = options.fetch_key || 'head_foot_image'; + this.fetcher = new Fetcher({ + endpoint: (options.endpoint || 'index.php?') + (options.fetch_key || 'head_foot_image=') + this.name, + method: 'POST', + onSuccess: (data) => this.onSuccess(data), + onFailure: (data) => this.onFailure(data) + }); } submit(){ const file = this.input_elem.files[0]; @@ -108,27 +87,14 @@ class InputFile extends InputToggler{ const form_data = new FormData(); form_data.append('file', file); - fetch(this.fetch_endpoint + '?' + this.fetch_key + '=' + this.name, { - method: 'POST', // apparemment il faudrait utiliser PUT - body: form_data - }) - .then(response => response.json()) - .then(data => { - if(data.success){ - this.onSuccess(data); - this.close(); - } - else{ - this.onFailure(data); - console.error(data.message); - } - }) - .catch(error => { - console.error('Erreur:', error); - }); + this.fetcher.send(form_data) + .then(result => { + toastNotify(result.success ? 'fichier téléchargé avec succès' : "erreur: la modification des données côté serveur a échoué"); + }); } onSuccess(data){ this.content_elem.src = data.location; + this.close(); } onFailure(data){ if(data.format === 'ico'){ @@ -137,6 +103,8 @@ class InputFile extends InputToggler{ } } + +// petits enfants class InputFileFavicon extends InputFile{ onSuccess(data){ const link = document.querySelector('link[rel="icon"]'); @@ -150,4 +118,23 @@ class InputFileHeaderBackground extends InputFile{ document.querySelector('header').style.backgroundImage = `url('${data.location}')`; super.onSuccess(data); } +} + +class InputTextSocialNetwork extends InputText{ + open(){ + const elem_parent = this.content_elem.parentNode; + if(elem_parent.tagName.toLowerCase() === 'a'){ + this.input_elem.value = elem_parent.href; + } + super.open(); + } + onSuccess(data){ + if(this.input_elem.value){ + this.content_elem.parentNode.href = this.input_elem.value; + } + else{ + this.content_elem.parentNode.removeAttribute('href'); + } + this.close(); // vu qu'on n'appelle pas super.onSuccess + } } \ No newline at end of file diff --git a/public/js/main.js b/public/js/main.js index 59a9331..3cc144a 100644 --- a/public/js/main.js +++ b/public/js/main.js @@ -199,6 +199,27 @@ function findParentByTagName(element, tag_name){ return null; } +function checkSocialNetwork(id){ + const checkbox = document.getElementById(id).querySelector('input[type="checkbox"]'); + + new Fetcher({ + endpoint: 'index.php?head_foot_social_check=' + id, + method: 'POST', + onSuccess: (data) => { + console.log(data); + + checkbox.checked = data.checked; + + /*const color = checkbox.checked ? "#ff1d04" : "grey"; + clicked_menu_entry.querySelector("button").style.color = color;*/ + }, + onFailure: (data) => { + console.log(data); + } + }) + .send({checked: checkbox.checked}); +} + /* -- fonctions spécifiques à la gestion des dates -- */ -- cgit v1.2.3