Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
6.3 KiB
✅ Solutions — Niveau 5 contact (PROCHAINE_ETAPE_contact_4.md)
🛑 À NE REGARDER QU'EN DERNIER RECOURS. Cherche d'abord par toi-même (au moins 10–15 min, doc MDN à l'appui). Quand tu lis une réponse : lis-la, ferme le fichier, et réécris-la de mémoire. C'est comme ça que ça rentre.
Le code ci-dessous est un exemple correct. Le tien peut être différent et tout aussi valable.
🧪 Exo 1 — map
const noms = equipe.map(function (membre) {
return membre.nom;
});
console.log(noms); // ["Mélissa", "Guillaume"]
💬 «
mapoufilter? »filtergarde/jette des éléments (la liste rétrécit).maptransforme chaque élément (la liste garde la même taille). Ici on veut transformer chaque objet en son nom →map.
🧪 Exo 2 — find
const personne = equipe.find(function (membre) {
return membre.partie === "Page contact";
});
if (personne) {
console.log(personne.nom);
} else {
console.log("Personne ne correspond.");
}
💬 « Pourquoi le
if (personne)? » Si aucun élément ne correspond,findrenvoieundefined. Fairepersonne.nomplanterait. On vérifie d'abord. (Variante moderne :personne?.nom— chercheoptional chaining.)
🧪 Exo 3 — reduce
Avec une boucle (plus lisible pour commencer) :
let totalKm = 0;
for (const v of vehicules) {
totalKm = totalKm + v.km;
}
La même chose en reduce :
const totalKm = vehicules.reduce(function (somme, v) {
return somme + v.km;
}, 0); // ← 0 = la valeur de départ
console.log(totalKm);
💬 « À quoi sert le
0à la fin ? » C'est la valeur de départ de l'accumulateur (somme). Pour une somme on part de 0 ; pour multiplier on partirait de 1.
🧪 Exo 4 — Délégation d'événements
Quand tu génères les lignes, marque chaque ligne avec le nom (un attribut data-…) :
function creerLigne(membre) {
const tr = document.createElement("tr");
tr.dataset.nom = membre.nom; // devient data-nom="..." dans le HTML
// ... (les <td> comme avant)
return tr;
}
Puis un seul écouteur, sur le parent qui ne bouge pas :
const corps = document.getElementById("corps_equipe");
corps.addEventListener("click", function (event) {
const ligne = event.target.closest("tr"); // la <tr> cliquée, peu importe la <td>
if (ligne) {
alert("Membre : " + ligne.dataset.nom);
}
});
💬 « Pourquoi ne pas mettre l'écouteur sur chaque
<tr>? » Parce que tes lignes sont recréées à chaque recherche/tri : il faudrait tout réattacher à chaque fois. En écoutant le parent (qui, lui, ne change pas), ça marche même pour les lignes créées plus tard. 💬 « À quoi sertclosest("tr")? » Le clic peut tomber sur une<td>;closestremonte jusqu'à la<tr>qui la contient.
🧪 Exo 5 — Debounce sur la recherche
let minuteur; // garde la trace du minuteur en cours
champRecherche.addEventListener("input", function () {
clearTimeout(minuteur); // on annule le précédent
minuteur = setTimeout(function () { // on en relance un
const mot = champRecherche.value.toLowerCase();
const resultats = equipe.filter(m => m.nom.toLowerCase().includes(mot));
afficherEquipe(resultats);
}, 300); // 300 ms après la DERNIÈRE frappe
});
💬 « Comment ça « attend » ? » À chaque frappe, on annule le minuteur précédent (
clearTimeout) et on en repart un de 300 ms. Tant que tu tapes, il est sans cesse annulé ; il ne se déclenche que quand tu fais une pause.
🧪 Exo 6 — Modules export / import
navbar.js :
export function creerNavbar(pageActive) {
return `... ton HTML de navbar ...`;
}
contact.js (tout en haut) :
import { creerNavbar } from "./navbar.js";
document.body.insertAdjacentHTML("afterbegin", creerNavbar("contact"));
HTML :
<script type="module" src="../contact.js"></script>
💬 « Depuis que j'utilise
type="module", mes autres scripts ne se voient plus ! » Normal : chaque module a son propre espace. Une variable d'un fichier n'est plus visible ailleurs sauf si tu l'exportes et l'importes. C'est justement le but : plus de variables globales qui se marchent dessus. 💬 « Erreur CORS au chargement du module. » Commefetch, les modules exigent un serveur :python3 -m http.serverpuishttp://localhost:8000/...(pasfile://).
🧪 Exo 7 — Vraie API en ligne
async function chargerUtilisateurs() {
const liste = document.getElementById("liste_users");
try {
const reponse = await fetch("https://jsonplaceholder.typicode.com/users");
const users = await reponse.json();
for (const u of users) {
const li = document.createElement("li");
li.textContent = `${u.name} — ${u.email}`;
liste.append(li);
}
} catch (erreur) {
console.error(erreur);
}
}
chargerUtilisateurs();
💬 « Comment je sais que les clés s'appellent
nameethttps://jsonplaceholder.typicode.com/usersdans le navigateur pour voir la forme des données. Fais toujours ça avant d'afficher. 💬 « Ça marche sur le web mais mon fichier local non ? » Une API en ligne autorise les requêtes externes (CORS) ; un fichier local ouvert enfile://non. D'où le serveur local pour tes propres fichiers.
🧪 Exo 8 — FormData
formulaire.addEventListener("submit", function (evenement) {
evenement.preventDefault();
const data = new FormData(formulaire);
const valeurs = Object.fromEntries(data);
console.log(valeurs); // { prenom: "...", email: "...", contacter: "..." }
});
💬 «
FormDatame renvoie du vide ! » Vérifie que chaque champ a un attributname(pas seulementid).FormDatalit les champs par leurname. 💬 « C'est mieux quegetElementByIdpartout ? » Pour lire tout un formulaire d'un coup, oui : une ligne au lieu d'ungetElementByIdpar champ. Pour un seul champ ponctuel,getElementByIdreste très bien.
🆘 Encore bloquée après la solution ?
Note : ce que tu attendais, ce qui se passe à la place, et ce qu'affiche la Console (F12). Avec ces 3 infos, on débloque vite.