Tuto JS niveau 4 contact: createElement/append, fetch+async/await+JSON, setInterval, evenements clavier

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-19 16:24:05 +02:00
parent c2979534f1
commit f42eb51b41
+239
View File
@@ -0,0 +1,239 @@
# 🚀 Niveau 4 — DOM propre, données distantes & temps réel
Salut Mélissa ! 👋
Suite logique de ce que tu sais déjà faire (tableaux, boucles, `localStorage`, `classList`, événements…). Quatre modules, du plus simple au plus costaud. Comme d'habitude : un exo à la fois, et **✅ teste** avant de passer au suivant.
| Module | Notion nouvelle | Exos |
|---|---|---|
| **A. Construire le DOM proprement** | `createElement` / `append` (au lieu de `innerHTML`) | 1 → 2 |
| **B. Aller chercher des données ailleurs** | `fetch`, `async`/`await`, JSON | 3 → 5 |
| **C. Le temps réel** | `setInterval` | 6 → 7 |
| **D. Le clavier** | événements clavier (`keydown`, `event.key`) | 8 |
---
# 🧱 Module A — Construire le HTML sans `innerHTML`
Pour ton tableau d'équipe, tu utilises `corps.innerHTML = lignes`. Ça marche très bien pour **tes** données. Mais `innerHTML` a deux limites :
- si tu y mets du texte tapé par un **inconnu**, il peut injecter du code (faille de sécurité dite *XSS*) ;
- ça remplace **tout** d'un coup, difficile de modifier une seule ligne ensuite.
La méthode « propre » consiste à fabriquer chaque élément **un par un**.
## 🧩 La notion : `createElement` + `textContent` + `append`
```js
const ligne = document.createElement("tr"); // on crée une balise <tr> (vide, pas encore dans la page)
const caseNom = document.createElement("td");
caseNom.textContent = "Mélissa"; // textContent = du texte pur, jamais interprété comme du HTML
ligne.append(caseNom); // on range la <td> dans la <tr>
```
> 🔎 `createElement` fabrique l'élément **en mémoire** ; il n'apparaît à l'écran qu'une fois **rattaché** à la page avec `append`. `textContent` (et non `innerHTML`) garantit que le contenu reste du **texte**, même si quelqu'un tape `<script>`.
## 🧪 Exo 1 — Réécrire une ligne du tableau « proprement »
Dans `equipe.js`, écris une fonction qui fabrique **une** ligne à partir d'un membre :
```js
function creerLigne(membre) {
const tr = document.createElement("tr");
const tdNom = document.createElement("td");
tdNom.textContent = membre.nom;
const tdJob = document.createElement("td");
tdJob.textContent = membre.job;
const tdPartie = document.createElement("td");
tdPartie.textContent = membre.partie;
tr.append(tdNom, tdJob, tdPartie); // append accepte plusieurs éléments d'un coup
return tr;
}
```
## 🧪 Exo 2 — Remplir le tableau avec cette fonction
```js
const corps = document.getElementById("corps_equipe");
corps.innerHTML = ""; // on vide d'abord
for (const membre of equipe) {
corps.append(creerLigne(membre)); // on ajoute chaque ligne fabriquée
}
```
**✅ Teste :** le tableau s'affiche comme avant. La différence est invisible à l'écran, mais ton code est maintenant plus sûr et chaque ligne est un vrai objet manipulable.
> 💡 **À retenir :** `innerHTML` = rapide, pour **tes** données fixes. `createElement` + `textContent` = la méthode propre, surtout dès qu'il y a du contenu venant de l'**utilisateur**.
---
# 🌐 Module B — Aller chercher des données ailleurs (`fetch`)
Jusqu'ici tes données (`equipe`) sont **écrites dans le code**. Dans la vraie vie, elles arrivent **d'un serveur**, sous forme de **JSON** (un format texte très proche des objets/tableaux que tu connais déjà).
## ⚠️ À lire avant de commencer : il faut un petit serveur
`fetch` **ne fonctionne pas** si tu ouvres ta page en double-cliquant (adresse en `file://`). Il faut servir le dossier. Dans un terminal, place-toi dans le dossier du projet et lance :
```bash
python3 -m http.server 8000
```
Puis ouvre **http://localhost:8000/pages/contact.html** dans le navigateur. (C'est exactement ce que fait un vrai site : un serveur qui envoie les fichiers.)
## 🧪 Exo 3 — Créer un fichier de données JSON
Crée `vehicules.json` à la racine du projet :
```json
[
{ "modele": "Renault Kangoo", "immatriculation": "AB-123-CD", "km": 45200 },
{ "modele": "Peugeot Partner", "immatriculation": "EF-456-GH", "km": 78900 },
{ "modele": "Citroën Berlingo", "immatriculation": "IJ-789-KL", "km": 12300 }
]
```
> 🔎 Le JSON ressemble à un tableau d'objets JS, avec **deux règles strictes** : toutes les clés sont **entre guillemets doubles**, et **pas de virgule** après le dernier élément. Une erreur ici et tout casse — colle-le dans un validateur si besoin.
## 🧪 Exo 4 — Récupérer ce fichier avec `fetch`
> 🆕 Nouvelles notions : `fetch`, `async`/`await`. `fetch` va chercher un fichier/des données **sur le réseau** ; comme ça prend un peu de temps, on **attend** la réponse avec `await`.
Dans un nouveau fichier `flotte.js` (branché dans la page) :
```js
async function chargerFlotte() {
const reponse = await fetch("../vehicules.json"); // on demande le fichier
const vehicules = await reponse.json(); // on le transforme en tableau JS
console.log(vehicules); // pour vérifier
}
chargerFlotte();
```
**✅ Teste :** via http://localhost:8000/…, ouvre la Console → tu dois voir ton tableau de 3 véhicules. Si tu vois une erreur, relis la partie « petit serveur » ci-dessus.
> 🧩 **À retenir :**
> - `async` devant une fonction = « cette fonction contient de l'attente ».
> - `await` = « attends que ce soit prêt avant de continuer ».
> - `fetch(...)` rapporte une **réponse**, et `reponse.json()` la transforme en données JS utilisables.
## 🧪 Exo 5 — Afficher la flotte + gérer les erreurs
Ajoute un tableau dans le HTML :
```html
<h3>Notre flotte</h3>
<p id="message_flotte">Chargement…</p>
<table border="1"><tbody id="corps_flotte"></tbody></table>
```
Puis complète `flotte.js` :
```js
async function chargerFlotte() {
const message = document.getElementById("message_flotte");
const corps = document.getElementById("corps_flotte");
try {
const reponse = await fetch("../vehicules.json");
const vehicules = await reponse.json();
message.textContent = vehicules.length + " véhicules :";
for (const v of vehicules) {
const tr = document.createElement("tr");
tr.textContent = `${v.modele}${v.immatriculation}${v.km} km`;
corps.append(tr);
}
} catch (erreur) {
message.textContent = "Impossible de charger la flotte 😕";
console.error(erreur);
}
}
chargerFlotte();
```
**✅ Teste :** la liste des véhicules s'affiche. Renomme exprès `vehicules.json` en `vehicule.json` (faute) et recharge → tu dois voir le message d'erreur au lieu d'un plantage.
> 🧩 **À retenir :** `try { … } catch (erreur) { … }` = « **essaie** ce code ; **si** ça rate, fais ça plutôt ». Indispensable avec le réseau, où ça peut toujours échouer (pas de connexion, fichier absent…).
---
# ⏱️ Module C — Le temps réel avec `setInterval`
## 🧪 Exo 6 — Une horloge dans le pied de page
> 🆕 Nouvelle notion : `setInterval(fonction, durée)` répète une action toutes les *durée* millisecondes.
```html
<span id="horloge"></span>
```
```js
const horloge = document.getElementById("horloge");
function afficherHeure() {
const maintenant = new Date();
horloge.textContent = maintenant.toLocaleTimeString(); // ex. "14:05:32"
}
afficherHeure(); // une fois tout de suite
setInterval(afficherHeure, 1000); // puis toutes les 1000 ms = 1 seconde
```
**✅ Teste :** l'heure s'affiche et **avance toute seule** chaque seconde.
> 🔎 `1000` est en **millisecondes** (1 s). `setInterval` ne s'arrête jamais tout seul ; pour le stopper un jour, on garde son résultat (`const id = setInterval(...)`) et on fait `clearInterval(id)`.
## 🧪 Exo 7 — Mettre à jour le badge « Ouvert / Fermé » en direct
Ton badge horaires est calculé **une seule fois** au chargement. Range ce calcul dans une fonction `rafraichirBadge()` puis appelle-la dans ton `setInterval` (par exemple toutes les 60 s). Ainsi, si la page reste ouverte à 18h pile, le badge passera tout seul à « Fermé ».
**✅ Teste :** pour vérifier sans attendre, mets temporairement l'intervalle à `1000` et change les heures d'ouverture autour de l'heure actuelle.
---
# ⌨️ Module D — Réagir au clavier
## 🧪 Exo 8 — Envoyer avec Ctrl+Entrée, effacer avec Échap
> 🆕 Nouvelle notion : l'événement `keydown` et la propriété `event.key`.
```js
zoneMessage.addEventListener("keydown", function (event) {
// Ctrl + Entrée → on déclenche l'envoi du formulaire
if (event.key === "Enter" && event.ctrlKey) {
formulaire.requestSubmit(); // comme cliquer sur "Envoyer"
}
// Touche Échap → on vide la zone
if (event.key === "Escape") {
zoneMessage.value = "";
rafraichirCompteur();
}
});
```
**✅ Teste :** écris un message, fais **Ctrl+Entrée** → l'envoi se déclenche. Appuie sur **Échap** → la zone se vide.
> 🔎 `event.key` te donne le **nom** de la touche (`"Enter"`, `"Escape"`, `"a"`…). `event.ctrlKey` est vrai si Ctrl est maintenue. C'est comme ça qu'on crée des raccourcis clavier.
---
## 🗺️ Ce que ce niveau ajoute à ta boîte à outils
- **DOM propre** : `createElement`, `textContent`, `append`
- **Données distantes** : `fetch`, `async`/`await`, JSON, `try`/`catch`
- **Temps réel** : `setInterval` / `clearInterval`
- **Clavier** : `keydown`, `event.key`, raccourcis
Prochaine étape possible : organiser ton code en plusieurs fichiers/modules, ou afficher des données depuis une **vraie API publique** en ligne. Dis-moi vers quoi tu veux aller.
Note tes questions au fur et à mesure.