freedzhost.cloud

Développement web module 3 : le JavaScript, la page qui réagit

Niveau DébutantTemps estimé 14 hÀ lire avant Développement web module 2 : le CSS, l'art de la mise en formeUn mot inconnu ? Lexique

Quatorze séances pour rendre vos pages vivantes : les bases du langage JavaScript (variables, conditions, fonctions), puis le DOM — la porte entre JavaScript et la page — et les événements, jusqu'à trois widgets utiles : un compteur, une liste de tâches et une bascule de mode sombre, plus un appel à une API publique. Tout se fait dans le navigateur, sans rien installer.

Jour 29 — JavaScript dans la page, la console

Objectif : brancher un script sur une page, afficher un premier message, et utiliser la console.

Théorie (20 min)

JavaScript est le langage qui s'exécute dans le navigateur et donne un comportement à la page : réagir aux clics, modifier le contenu sans recharger, aller chercher des données. Pas de rapport avec Java malgré le nom — un coup marketing de 1995.

Comme le CSS, le JavaScript vit dans son propre fichier, relié par une balise <script> placée juste avant </body> :

<script src="script.js"></script>

À la fin du body, et pas dans le head : le script s'exécute dès qu'il est lu, et il a besoin que le HTML existe déjà pour le manipuler. (Il existe un attribut defer pour le mettre dans le head — le module 4 l'utilisera.)

Première fonction : console.log(...) affiche ce qu'on lui donne dans la console des outils de développement (F12, onglet Console) — invisible sur la page, c'est votre journal de bord :

console.log("Bonjour depuis JavaScript");
console.log(2 + 2);

La console est aussi un terrain de jeu : on peut y taper du JavaScript directement, ligne par ligne, et voir le résultat immédiatement. C'est le REPL du navigateur, l'équivalent du >>> de Python.

Pratique (30 min)

  1. Dans votre dossier, créez module3, copiez-y votre page moi.html, et créez un fichier vide script.js à côté. Ajoutez la balise <script> avant </body>.
  2. Dans script.js, tapez les deux lignes ci-dessus. Enregistrez, rechargez, ouvrez la console (F12). Critère de réussite : « Bonjour depuis JavaScript » et « 4 » s'affichent dans la console.
  3. Provoquez une erreur : écrivez console.log("test" sans la parenthèse fermante, rechargez. La console affiche une erreur rouge avec le numéro de ligne : c'est elle qui vous parlera chaque fois que quelque chose casse. Lisez-la, corrigez.
  4. Changez le chemin du src pour un nom faux : la console affiche une 404 sur script.js — même diagnostic qu'au jour 15 pour le CSS. Réparez.
  5. Tapez directement dans la console : 2 + 2, puis "bonjour".toUpperCase(). Vous exécutez du JavaScript en direct.

Tips agent : « voici l'erreur rouge de ma console : [collez], et voici la ligne qu'elle indique : [collez] » — le diagnostic est presque toujours immédiat. Piège : sans le texte exact de l'erreur, il devine. Preuve : corrigez vous-même la ligne qu'il nomme, et vérifiez que la console redevient propre.

Synthèse (10 min)

Trois lignes : où vit la balise script et pourquoi, ce qu'est la console, ce que fait console.log. Puis rebranchez un script de mémoire sur une page neuve.

Jour 30 — Variables et types

Objectif : stocker des valeurs avec let et const, et distinguer les trois types de base.

Théorie (20 min)

Une variable est un nom qui pointe vers une valeur — la boîte étiquetée. En JavaScript moderne, on la déclare avec const (la valeur ne sera pas réassignée — le choix par défaut) ou let (elle pourra changer) :

const prenom = "Alice";
let score = 0;
score = score + 10;

Le vieux mot-clé var traîne dans d'anciens tutoriels : ne l'utilisez pas, const et let le remplacent depuis 2015. Réassigner une variable const provoque une erreur — c'est voulu : la machine vous signale que vous vous contredisez.

Trois types de valeurs font l'essentiel : les chaînes de caractères (du texte, entre guillemets : "bonjour"), les nombres (42, 3.14 — JavaScript n'a qu'un seul type de nombre) et les booléens (true ou false, vrai ou faux). L'opérateur typeof dit le type d'une valeur : typeof "bonjour" répond "string".

Attention au piège du débutant : "5" + 3 donne "53" — un texte plus un nombre colle les caractères au lieu d'additionner. "5" avec guillemets est un texte qui ressemble à un nombre, pas un nombre.

Que vaut "5" + 3 en JavaScript ?

  1. 8
  2. Une erreur
  3. "53"
Réponse

"53" : le + avec une chaîne concatène au lieu d'additionner.

Pratique (30 min)

  1. Dans script.js, déclarez const prenom, let annee, const estMembre = true;, et affichez les trois avec console.log. Rechargez, lisez la console.
  2. Essayez de réassigner la const : prenom = "Bob"; — rechargez, lisez l'erreur, supprimez la ligne. Vous savez maintenant ce que « Assignment to constant variable » veut dire.
  3. Testez le piège : console.log("5" + 3) puis console.log(Number("5") + 3). La fonction Number() convertit le texte en nombre. Critère de réussite : la console affiche 53 puis 8, et vous savez expliquer la différence.
  4. Vérifiez les types : console.log(typeof prenom), typeof annee, typeof estMembre.
  5. Au carnet : quand utiliser const, quand utiliser let ? (Réponse : const par défaut, let quand la valeur doit changer.)

Tips agent : « pourquoi ce calcul donne-t-il 53 au lieu de 8 ? » — collez la ligne. Piège : il peut noyer la réponse (coercition, spécification) ; demandez « en une phrase ». Preuve : la correction doit passer par Number() et vous la testez dans la console.

Synthèse (10 min)

Trois lignes : const vs let, les trois types, le piège "5" + 3. Puis réécrivez le mini-programme de mémoire.

Jour 31 — Textes, nombres, gabarits

Objectif : assembler du texte avec les gabarits de chaînes et faire calculer JavaScript.

Théorie (20 min)

Concaténer du texte avec + devient vite illisible. Les gabarits de chaînes (template literals) règlent ça : la chaîne s'écrit entre accents graves `, et les valeurs s'insèrent dans des ${...} :

const prenom = "Alice";
const age = 32;
console.log(`Je m'appelle ${prenom} et j'ai ${age} ans.`);

Entre les ${}, on peut mettre n'importe quelle expression : ${age + 1} affiche 33.

Côté nombres : + - * / font les quatre opérations, % donne le reste de la division (10 % 3 vaut 1 — n % 2 === 0 teste si n est pair), et les parenthèses fixent l'ordre. L'objet Math fournit les outils courants : Math.round(3.6) arrondit (4), Math.floor(3.6) arrondit vers le bas (3), Math.random() donne un nombre entre 0 et 1.

Une chaîne est aussi un objet plein d'outils : texte.length (le nombre de caractères), texte.toUpperCase(), texte.includes("mot") (vrai si le mot est dedans), texte.trim() (enlève les espaces des bords — indispensable sur les saisies utilisateur).

`Total : ${10 + 5}` affiche…

  1. Total : ${10 + 5}
  2. Total : 15
  3. Une erreur
Réponse

Total : 15 — l'expression entre ${} est calculée.

Pratique (30 min)

  1. Écrivez le gabarit ci-dessus avec vos valeurs, rechargez, lisez la console.
  2. Construisez une phrase qui mélange texte et calculs : « L'an prochain j'aurai X ans », avec l'addition faite dans le ${}. Critère de réussite : l'âge affiché est calculé par le code, pas écrit par vous.
  3. Testez " bonjour ".trim() dans la console : les espaces des bords disparaissent.
  4. Écrivez un test de parité : const n = 7; console.log(n % 2 === 0); affiche false. Changez n en 8 : true.
  5. Jouez avec Math.random() : affichez Math.floor(Math.random() * 6) + 1 plusieurs fois — vous venez d'écrire un dé à six faces.

Tips agent : « transforme ces concaténations en gabarits de chaînes » est une refonte parfaite. Piège : il peut changer le texte affiché au passage. Preuve : comparez la sortie console avant/après, identique au caractère près.

Synthèse (10 min)

Trois lignes : la syntaxe des gabarits, les opérateurs, trois outils de Math ou des chaînes. Puis réécrivez le dé à six faces de mémoire.

Jour 32 — Conditions

Objectif : faire décider le programme avec if / else if / else et les opérateurs de comparaison.

Théorie (20 min)

La condition exécute un bloc seulement si un test est vrai :

const age = 17;
if (age >= 18) {
  console.log("majeur");
} else if (age >= 13) {
  console.log("adolescent");
} else {
  console.log("enfant");
}

Le test entre parenthèses est un booléen. Les opérateurs de comparaison : === (égal, à utiliser TOUJOURS — le == historique convertit les types en douce et réserve des surprises : "5" == 5 est vrai !), !== (différent), < <= > >=. Les opérateurs logiques combinent : && (ET : les deux vrais), || (OU : au moins un vrai), ! (NON : inverse).

JavaScript classe chaque valeur en « truthy » ou « falsy » quand on la met dans un test : sont falsy false, 0, "" (chaîne vide), null, undefined, NaN ; tout le reste est truthy. if (texte) veut donc dire « si texte n'est pas vide ».

Pourquoi préférer === à == ?

  1. === compare sans convertir les types : "5" === 5 est faux, sans surprise
  2. === est plus rapide
  3. == n'existe plus en JavaScript moderne
Réponse

=== est strict : pas de conversion cachée. == convertit, et "5" == 5 devient vrai.

Pratique (30 min)

  1. Tapez le programme des âges, testez avec 17, 25, 9 : trois réponses différentes dans la console.
  2. Écrivez un contrôle de saisie : const motDePasse = "chat"; puis un if qui affiche « trop court » si motDePasse.length < 8, « accepté » sinon. Testez avec « chat » puis « girafe-savane ». Critère de réussite : les deux branches s'affichent selon la longueur.
  3. Combinez : un accès autorisé si age >= 18 && estMembre. Testez les quatre combinaisons de vos deux variables.
  4. Testez le falsy : const saisie = ""; if (saisie) { console.log("plein"); } else { console.log("vide"); } — affiche « vide ». Mettez un espace dans la chaîne : « plein » ! Un espace est un caractère. (Vous comprenez maintenant pourquoi on fait trim() avant de tester.)

Tips agent : « relis ces conditions et liste les cas que je n'ai pas testés » est un excellent filet. Piège : il peut « exécuter de tête » et rater le cas de la chaîne d'un espace. Preuve : testez chaque cas qu'il cite, dans la console, vous-même.

Synthèse (10 min)

Trois lignes : la forme if/else if/else, === vs ==, ce que falsy veut dire. Puis réécrivez le contrôle de longueur de mémoire.

Jour 33 — Fonctions

Objectif : écrire des fonctions avec paramètres et valeur de retour, et les réutiliser.

Théorie (20 min)

Une fonction est un bloc de code nommé, qu'on peut appeler autant de fois qu'on veut. On la définit une fois, on l'appelle partout :

function saluer(prenom) {
  return `Bonjour ${prenom} !`;
}
console.log(saluer("Alice"));
console.log(saluer("Bob"));

Les morceaux : prenom est un paramètre — la variable d'entrée, qui n'existe que dans la fonction. return renvoie le résultat à l'appelant et arrête la fonction : ce qui est écrit après ne s'exécute pas. Une fonction sans return renvoie undefined.

Distinction capitale : console.log AFFICHE, return RENVOIE. Afficher ne permet pas de réutiliser la valeur ; renvoyer si. La fonction qui renvoie peut nourrir un calcul, un test, un texte : const message = saluer("Alice");.

Vous croiserez l'écriture « fléchée » : const saluer = (prenom) => `Bonjour ${prenom} !`; — une fonction courte rangée dans une constante. Équivalente pour ce parcours ; sachez juste la lire.

Que renvoie une fonction sans return ?

  1. null
  2. undefined
  3. Une erreur
Réponse

undefined : sans return, la fonction ne renvoie rien, et « rien » s'écrit undefined.

Pratique (30 min)

  1. Tapez saluer, appelez-la avec trois prénoms.
  2. Écrivez function aire(largeur, hauteur) qui renvoie le produit, et affichez aire(3, 4). Critère de réussite : la console affiche 12, calculé par la fonction.
  3. Écrivez function estPair(n) qui renvoie un booléen (return n % 2 === 0;), puis utilisez-la DANS une condition : if (estPair(7)) { ... }. Une fonction qui renvoie un booléen est un test réutilisable.
  4. Écrivez function prixTTC(prixHT, taux) qui renvoie prixHT * (1 + taux), et affichez un gabarit : « Prix TTC : X € ».
  5. Piège volontaire : remplacez le return par un console.log dans aire, puis affichez aire(3, 4) * 2 : la console affiche NaN (Not a Number — undefined ne se multiplie pas). Réparez. Vous avez vu la différence afficher/renvoyer en vrai.

Tips agent : « écris une fonction prixTTC(prixHT, taux) » est un bon ordre, petit et vérifiable. Piège : il peut afficher au lieu de renvoyer. Preuve à exiger : console.log(prixTTC(100, 0.2)) doit afficher 120 — testez-le.

Synthèse (10 min)

Trois lignes : paramètre vs argument, return vs console.log, pourquoi une fonction booléenne est pratique. Puis réécrivez estPair de mémoire.

Jour 34 — Le DOM : lire la page

Objectif : sélectionner un élément de la page depuis JavaScript, lire et modifier son texte.

Théorie (20 min)

Quand le navigateur lit votre HTML, il en construit une représentation en mémoire : le DOM (Document Object Model) — l'arbre des éléments, tel que le montre l'inspecteur. JavaScript voit la page À TRAVERS le DOM : modifier le DOM modifie la page affichée, sans toucher au fichier.

La sélection d'un élément utilise les sélecteurs CSS que vous connaissez :

const titre = document.querySelector("h1");      // le premier h1
const encart = document.querySelector(".encart"); // le premier de la classe
const champ = document.querySelector("#prenom");  // par id
const liens = document.querySelectorAll("a");     // TOUS les liens (une liste)

document est l'objet qui représente la page entière. querySelector renvoie le premier élément qui correspond, ou null si aucun ne correspond — la cause n° 1 de l'erreur « Cannot read properties of null » : le sélecteur ne correspond à rien (faute de frappe, ou script chargé avant le HTML — souvenez-vous du jour 29).

Une fois l'élément en main, on le lit et on le modifie :

console.log(titre.textContent);      // lire son texte
titre.textContent = "Nouveau titre"; // remplacer son texte
encart.classList.add("visible");     // ajouter une classe CSS
encart.classList.remove("encart");

Préférez textContent (du texte, point) à innerHTML (qui interprète du HTML — utile mais dangereux avec du contenu qui vient de l'utilisateur : c'est la porte aux attaques XSS, le module 4 y revient).

Pratique (30 min)

  1. Dans script.js, sélectionnez le h1 de votre page et affichez son texte dans la console.
  2. Modifiez-le : titre.textContent = "Bienvenue";, rechargez. Critère de réussite : le titre affiché est « Bienvenue » alors que votre fichier HTML n'a pas changé — regardez le code source (clic droit → code source) : toujours l'ancien. Le DOM a changé, pas le fichier.
  3. Provoquez le null : sélectionnez ".inexistant" et lisez son textContent : erreur rouge. Lisez-la, elle dit tout. Affichez la variable : null. Corrigez le sélecteur.
  4. Testez querySelectorAll("p") et affichez .length de la liste : le nombre de paragraphes de votre page.
  5. Ajoutez une classe à un élément depuis le script, et donnez à cette classe un style visible dans votre CSS. Le style change sans recharger : c'est le mécanisme du mode sombre de l'autre jour.

Tips agent : « Cannot read properties of null, voici mon sélecteur et mon HTML » — le diagnostic est immédiat. Piège : il peut répondre « ajoute defer » sans vérifier la faute de frappe du sélecteur. Preuve : affichez d'abord la variable sélectionnée dans la console — null ou élément, la console tranche.

Synthèse (10 min)

Trois lignes : ce qu'est le DOM, querySelector vs querySelectorAll, pourquoi textContent plutôt qu'innerHTML. Puis modifiez un texte de mémoire.

Jour 35 — Événements : le compteur

Objectif : réagir aux clics avec addEventListener et construire un compteur.

Théorie (20 min)

La page émet des événements en permanence : clic, frappe au clavier, envoi de formulaire, défilement… JavaScript peut écouter un événement sur un élément et exécuter une fonction quand il arrive :

const bouton = document.querySelector("#plus");
bouton.addEventListener("click", function () {
  console.log("cliqué !");
});

Les morceaux : l'élément écouté, le nom de l'événement ("click"), et la fonction à exécuter — qu'on appelle un écouteur (listener). Elle ne s'exécute pas maintenant : elle s'exécutera à chaque clic. C'est le renversement du module précédent : votre code ne tourne plus de haut en bas une fois, il attend et réagit.

Tout s'assemble dans le premier widget du parcours, le compteur :

let compte = 0;
const bouton = document.querySelector("#plus");
const affichage = document.querySelector("#compte");
bouton.addEventListener("click", function () {
  compte = compte + 1;
  affichage.textContent = compte;
});

Le HTML qui va avec : <button id="plus">+1</button> <p>Compte : <span id="compte">0</span></p>. Notez le cycle : l'état vit dans une variable JavaScript, et l'affichage n'en est que le reflet, mis à jour à chaque changement.

Pratique (30 min)

  1. Ajoutez le bouton et le paragraphe ci-dessus à votre page, puis le script du compteur. Rechargez, cliquez. Critère de réussite : chaque clic incrémente le nombre affiché, sans recharger la page (regardez l'onglet : pas de rechargement).
  2. Ajoutez un bouton « -1 » avec son propre écouteur.
  3. Ajoutez un bouton « Remise à zéro ».
  4. Défi : le compteur ne doit pas descendre sous zéro — une condition dans l'écouteur du « -1 ».
  5. Stylez les boutons avec votre CSS (classe, hover) : un widget est du HTML + CSS + JS, les trois langages ensemble.

Tips agent : « écris un compteur +1/-1/reset en JS vanilla » donne ce code d'un coup. Piège : il peut sélectionner les boutons par leur texte ou oublier que le HTML n'existe pas encore. Preuve : cliquez chaque bouton trois fois, dont -1 à zéro — le comportement doit être exactement celui prévu.

Synthèse (10 min)

Trois lignes : les trois morceaux d'addEventListener, pourquoi l'état vit dans une variable, ce qu'est un écouteur. Puis refaites le compteur de mémoire.

EOF_MARKER_NEVER echo written

Jour 36 — Tableaux et boucles

Objectif : stocker des collections dans un tableau et les parcourir avec une boucle.

Théorie (20 min)

Un tableau (array) est une liste ordonnée de valeurs, écrite entre crochets :

const courses = ["pommes", "pain", "riz"];
console.log(courses[0]);        // "pommes" — on compte à partir de ZÉRO
console.log(courses.length);    // 3
courses.push("café");           // ajoute à la fin
courses[1] = "pain complet";    // modifie la case 1

L'index commence à zéro : le premier élément est [0], et le dernier est [length - 1]. Demander une case au-delà donne undefined, pas une erreur — une source de bugs silencieux.

Pour parcourir, la boucle for...of :

for (const article of courses) {
  console.log(article);
}

« pour chaque article du tableau courses, fais… ». Elle visite chaque élément, dans l'ordre, une fois. (La boucle for (let i = 0; i < courses.length; i++) classique existe toujours ; for...of suffit dans la plupart des cas et se lit mieux.)

Les tableaux ont des méthodes qui transforment : courses.map(...) crée un nouveau tableau en transformant chaque élément, courses.filter(...) garde ceux qui passent un test. Notez leur existence ; for...of couvre vos besoins du mois.

Avec const t = ["a", "b", "c"];, que vaut t[1] ?

  1. "a"
  2. undefined
  3. "b"
Réponse

"b" : l'index commence à zéro, donc [1] est le deuxième élément.

Pratique (30 min)

  1. Créez un tableau de cinq prénoms, affichez le premier, le dernier (avec length - 1), et la taille.
  2. Parcourez-le avec for...of et affichez « Bonjour X » pour chacun.
  3. Tableau de nombres : calculez la somme avec une boucle (une variable let total = 0; avant la boucle, total = total + n; dedans). Critère de réussite : affichez la somme ET la moyenne, calculées par le code.
  4. Filtrez à la main : une boucle qui n'affiche que les prénoms de plus de cinq lettres (p.length > 5).
  5. Demandez courses[99] : undefined, silencieusement. Notez-le au carnet : une case qui n'existe pas ne crie pas.

Tips agent : « pourquoi ma boucle affiche-t-elle undefined en dernière ligne ? » — collez la boucle. Piège classique : i <= length au lieu de <. Preuve : la correction est UNE inégalité ; refusez la réécriture complète.

Synthèse (10 min)

Trois lignes : l'index qui commence à zéro, for...of, push. Puis refaites le calcul de moyenne de mémoire.

Jour 37 — Créer des éléments dans la page

Objectif : générer du HTML depuis JavaScript : créer des éléments et les ajouter à la page.

Théorie (20 min)

Hier, vous avez parcouru un tableau dans la console. Aujourd'hui, chaque élément parcouru devient un élément de la page. Trois méthodes suffisent :

const liste = document.querySelector("#courses");
for (const article of ["pommes", "pain", "riz"]) {
  const li = document.createElement("li"); // crée l'élément (en mémoire)
  li.textContent = article;                 // remplit son texte
  liste.appendChild(li);                    // l'accroche à la page
}

Le trio créer → remplir → accrocher est LE geste du DOM. L'élément créé n'existe qu'en mémoire tant qu'appendChild ne l'a pas rattaché à un élément de la page.

On peut aussi retirer : li.remove() supprime l'élément de la page.

Comparez avec l'alternative liste.innerHTML = "<li>" + article + "</li>"; : plus court, mais la chaîne est interprétée comme du HTML — si article vient d'une saisie utilisateur et contient <script>, le script s'exécute. C'est la faille XSS. Règle du parcours : du contenu qui vient de l'extérieur (saisie, API) passe par textContent et createElement, jamais par innerHTML.

Pratique (30 min)

  1. Dans votre page, ajoutez <ul id="courses"></ul> vide, et le script ci-dessus. Rechargez : la liste apparaît, construite par JavaScript. Critère de réussite : l'inspecteur montre les trois <li> alors que votre fichier HTML a un <ul> vide.
  2. Remplacez le tableau en dur par votre tableau de prénoms d'hier : la page affiche la liste.
  3. Ajoutez à chaque li un bouton « × » (créé avec createElement, accroché au li) dont l'écouteur fait li.remove() : chaque ligne devient supprimable.
  4. Testez le piège XSS, en connaissance de cause, dans un fichier jetable : injectez "<img src=x onerror=alert(1)>" via innerHTML, puis via textContent. Le premier exécute, le second affiche le texte tel quel. Vous n'utiliserez plus innerHTML sur une saisie.

Tips agent : « génère une liste ul depuis ce tableau en JS » est un ordre classique. Piège : la solution rendue utilise souvent innerHTML. Preuve à exiger : createElement + textContent, et testez avec une valeur qui contient des chevrons.

Synthèse (10 min)

Trois lignes : le trio créer/remplir/accrocher, ce que fait remove, pourquoi pas innerHTML sur une saisie. Puis regénérez une liste de mémoire.

Jour 38 — Lire un formulaire en JavaScript

Objectif : intercepter l'envoi d'un formulaire, lire la saisie, et l'utiliser dans la page.

Théorie (20 min)

Au jour 9, envoyer le formulaire rechargeait la page. JavaScript peut intercepter cet envoi :

const form = document.querySelector("#mon-form");
form.addEventListener("submit", function (event) {
  event.preventDefault();              // empêche le rechargement
  const champ = document.querySelector("#prenom");
  const saisie = champ.value.trim();   // .value lit le contenu d'un champ
  if (saisie === "") {
    return;                            // on sort sans rien faire
  }
  console.log(`Saisi : ${saisie}`);
  champ.value = "";                    // vide le champ pour la prochaine fois
});

Trois notions : event est l'objet que le navigateur donne à l'écouteur pour décrire ce qui s'est passé ; preventDefault() annonce « ne fais pas le comportement par défaut » (le rechargement) ; .value lit (et écrit) le contenu d'un champ — c'est une propriété des champs de formulaire, pas textContent.

Valider côté page (longueur, champ vide) améliore le confort — la réponse est immédiate. Mais souvenez-vous : cette validation est contournable par n'importe qui (les outils de dev modifient tout). La validation qui protège vraiment se fait sur le serveur — vous n'en avez pas encore, le module 4 publiera du statique.

Pratique (30 min)

  1. Donnez un id à votre formulaire de contact et au champ prénom, et branchez l'écouteur ci-dessus. Rechargez, saisissez, envoyez. Critère de réussite : la page ne recharge PAS (l'URL reste propre), la console affiche la saisie, et le champ se vide.
  2. Remplacez le console.log par un vrai affichage : un <p id="confirmation"> dans la page, dont vous remplissez le textContent : « Merci, X ! ».
  3. Champ vide : envoyez sans rien taper — rien ne se passe (le return). Ajoutez un message « Le prénom est requis » affiché dans ce cas-là.
  4. Testez la touche Entrée dans le champ : elle envoie le formulaire, comme le clic sur le bouton. C'est le comportement natif, gratuit, et les utilisateurs clavier comptent dessus.

Tips agent : « intercepte ce submit et affiche la saisie dans un p » est bien délégué. Piège : il peut oublier preventDefault, et la page recharge — vous croirez que le JS ne marche pas. Preuve : envoyez le formulaire, l'URL ne doit PAS gagner de ?....

Synthèse (10 min)

Trois lignes : preventDefault, .value vs textContent, pourquoi la validation côté page ne protège pas. Puis refaites l'interception de mémoire.

Jour 39 — La liste de tâches complète

Objectif : assembler formulaire, tableau et DOM dans le widget classique : la liste de tâches.

Théorie (20 min)

La liste de tâches (todo list) est LE deuxième widget du parcours : elle combine tout le module. L'architecture, à retenir car elle sert partout :

  • L'état : un tableau JavaScript contient les tâches — c'est la source de vérité ;
  • L'affichage : une fonction afficher() vide la liste HTML et la reconstruit depuis le tableau ;
  • Les actions : les écouteurs (submit, clic) modifient le tableau, puis appellent afficher().
const taches = [];
function afficher() {
  liste.innerHTML = "";              // vide l'affichage (sur des éléments à soi : sûr)
  for (const t of taches) {
    const li = document.createElement("li");
    li.textContent = t;
    liste.appendChild(li);
  }
}

Quand on clique « ajouter » : on fait taches.push(saisie) puis afficher(). Le réflexe « modifier les données, puis ré-afficher » est le cœur de toutes les interfaces, du widget à React.

Pour supprimer une tâche, chaque ligne a besoin de savoir laquelle elle porte : on peut stocker l'index dans le bouton, ou filtrer le tableau : taches.splice(index, 1) retire un élément à la position donnée.

Pratique (30 min)

  1. Construisez la page taches.html : un formulaire (champ + bouton « Ajouter »), un <ul id="liste"> vide, le script avec le tableau, afficher(), et l'écouteur submit.
  2. Critère de réussite : ajoutez trois tâches — elles s'affichent, sans rechargement, et le champ se vide entre chaque.
  3. Ajoutez à chaque ligne un bouton « × » qui retire la tâche du tableau (splice) puis ré-affiche. Testez : supprimez la tâche du milieu et vérifiez que les autres restent dans l'ordre.
  4. Refusez les tâches vides ou faites d'espaces (trim + test vide du jour 32).
  5. Bonus si le temps reste : un clic sur le texte d'une tâche la barre (ajoutez/retirez une classe CSS .fait { text-decoration: line-through; }).

Tips agent : « écris une todo list en JS vanilla avec ajout et suppression » est le test RORSCHACH de la délégation : le code sera plausible. Piège : testez la suppression de l'élément du MILIEU, c'est là que les indices se trompent. Preuve : trois ajouts, une suppression au milieu, un rejet de saisie vide.

Synthèse (10 min)

Trois lignes : l'architecture état/affichage/actions, ce que fait splice, pourquoi ré-afficher depuis l'état. Gardez cette page : le jour 41 lui ajoutera une mémoire.

Jour 40 — fetch : appeler une API publique

Objectif : récupérer des données d'un service public avec fetch et les afficher.

Théorie (20 min)

Une API (Application Programming Interface) est une porte d'entrée d'un service, faite pour les programmes plutôt que pour les humains : au lieu d'une page HTML, elle renvoie des données brutes, le plus souvent en JSON (JavaScript Object Notation) — du texte structuré en paires "clé": valeur, facile à lire pour les machines et lisible pour nous.

JavaScript appelle une API avec fetch :

fetch("https://wttr.in/Paris?format=j1")
  .then(function (reponse) { return reponse.json(); })
  .then(function (donnees) {
    console.log(donnees.current_condition[0].temp_C);
  });

fetch envoie la requête HTTP ; la réponse arrive plus tard, quand le réseau répond — c'est asynchrone : le code ne s'arrête pas d'attendre, et .then() enchaîne ce qu'on fera quand la réponse arrivera. Le premier .then transforme le texte reçu en données JavaScript (.json()), le second les utilise.

wttr.in est un service météo gratuit, sans inscription ni clé, pensé pour le terminal mais dont le format ?format=j1 renvoie du JSON complet (température, vent, prévisions) — parfait pour s'entraîner. Si jamais il ne répond pas, JSONPlaceholder offre de fausses données (utilisateurs, articles) avec la même mécanique.

Et quand le réseau échoue ? Un .catch() en fin de chaîne attrape l'erreur — sinon elle est silencieuse.

Pratique (30 min)

  1. Dans la console d'abord : collez le fetch ci-dessus et explorez l'objet donnees (cliquez pour le déplier) : trouvez la température actuelle et la description du temps.
  2. Dans votre page : un bouton « Météo » et un <p id="meteo">. Au clic, fetch, puis affichez « Il fait X °C à Paris » dans le paragraphe. Critère de réussite : le clic affiche la température réelle du moment — comparez avec wttr.in/Paris dans un onglet.
  3. Ajoutez le .catch qui affiche « Service indisponible » dans le paragraphe. Testez-le : coupez le réseau (mode hors-ligne des outils de dev), cliquez — le message apparaît au lieu d'un silence.
  4. Changez la ville dans l'URL pour la vôtre. Attention aux espaces : Le%20Mans — l'URL n'aime pas les espaces.

Tips agent : « lis ce JSON et dis-moi le chemin jusqu'à la température » en lui collant un EXTRAIT de la réponse (pas les 200 lignes). Piège : sans l'extrait, il invente la structure de l'API. Preuve : affichez donnees dans la console et suivez son chemin du doigt.

Synthèse (10 min)

Trois lignes : ce qu'est une API et le JSON, la chaîne fetch/then/then/catch, ce qu'asynchrone veut dire. Puis refaites l'appel météo de mémoire.

Jour 41 — Bascule de mode sombre avec mémoire

Objectif : ajouter un bouton de bascule clair/sombre qui survit au rechargement grâce à localStorage.

Théorie (20 min)

Jour 26, le mode sombre suivait le réglage du système. Aujourd'hui, l'utilisateur choisit lui-même, et le site se souvient. Deux mécanismes :

D'abord, la bascule : une classe CSS sur <body> qui redéfinit vos variables, et JavaScript l'ajoute ou la retire :

/* CSS */
body.sombre {
  --fond: #17181c;
  --texte: #e8e6e3;
}
/* JS */
document.querySelector("#bascule").addEventListener("click", function () {
  document.body.classList.toggle("sombre");
});

classList.toggle ajoute la classe si elle est absente, la retire si elle est là : une ligne pour un interrupteur.

Ensuite, la mémoire : localStorage est un petit stockage du navigateur, par site, qui survit à la fermeture. Deux méthodes : localStorage.setItem("theme", "sombre") écrit, localStorage.getItem("theme") relit (null si jamais écrit). Au chargement du script, on relit et on applique :

if (localStorage.getItem("theme") === "sombre") {
  document.body.classList.add("sombre");
}

Vous voyez la limite : ce choix ne vit que dans CE navigateur, sur CET appareil. Pas de compte, pas de serveur — pour un site statique, c'est exactement ce qu'il faut.

Pratique (30 min)

  1. Ajoutez la règle CSS body.sombre (avec vos couleurs sombres du jour 26) et un bouton <button id="bascule">Mode sombre</button> dans votre header.
  2. Branchez l'écouteur toggle. Critère de réussite n°1 : le clic bascule le thème, et re-cliquer revient.
  3. Dans l'écouteur, après le toggle, écrivez la préférence : lisez document.body.classList.contains("sombre") et stockez "sombre" ou "clair". Au chargement, relisez et appliquez.
  4. Critère de réussite n°2 : passez en sombre, rechargez la page (F5) : le thème sombre est toujours là. Fermez l'onglet, rouvrez : toujours là.
  5. Ouvrez les outils de dev, onglet Application (ou Stockage) → Local Storage : voyez votre clé theme et sa valeur. Supprimez-la, rechargez : retour au clair.
  6. Faites le même cadeau à votre liste de tâches d'hier si le temps reste : localStorage.setItem("taches", JSON.stringify(taches)) à chaque changement, et JSON.parse au chargement. JSON.stringify transforme le tableau en texte stockable ; JSON.parse fait l'inverse.

Tips agent : « ajoute un toggle dark mode persistant en localStorage » est un classique bien délégué. Piège : il peut oublier d'appliquer le thème AU CHARGEMENT — le choix ne survit qu'au premier rechargement. Preuve : basculez, rechargez, fermez, rouvrez. Trois étapes, pas une.

Synthèse (10 min)

Trois lignes : toggle, setItem/getItem, la limite du stockage local. Puis refaites la bascule complète de mémoire.

Jour 42 — Bilan du module 3

Objectif : vérifier les acquis JavaScript avant le projet final.

Théorie (20 min)

Testez-vous sans notes :

  1. const ou let : lequel par défaut, et pourquoi ?
  2. Que vaut "5" + 3, et comment obtenir 8 ?
  3. Différence entre console.log et return dans une fonction ?
  4. Qu'est-ce que le DOM, et que fait querySelector(".x") quand rien ne correspond ?
  5. Nommez les trois morceaux d'un addEventListener.
  6. Pourquoi textContent plutôt qu'innerHTML pour une saisie utilisateur ?
  7. Décrivez l'architecture état / affichage / actions de la todo list.
  8. Que fait event.preventDefault() sur un submit ?

Pratique (30 min)

  1. Faites le test des huit questions à l'écrit, sans notes.
  2. Pour chaque question ratée, refaites la pratique de la séance correspondante.
  3. Critère de réussite : huit bonnes réponses, ou les séances refaites.
  4. Exercice minute : en vingt minutes, sur une page blanche, reconstruisez le compteur du jour 35 sans regarder vos notes. Chronométrez-vous ; le geste doit devenir naturel.
  5. Rangez : tout le module dans votre dossier module3, avec votre page moi.html enrichie, la météo, la todo list, la bascule.

Tips agent : « interroge-moi sur le JavaScript : variables, conditions, fonctions, DOM, événements, fetch — une question à la fois » vous fait un examinateur. Piège : il peut dériver vers des sujets hors parcours (classes, modules ES). Preuve : recadrez avec votre sommaire collé.

Synthèse (10 min)

Trois lignes : vos trois acquis, la notion fragile. Demain : l'accessibilité, la performance, et la mise en ligne — votre travail rencontre le monde.

Utile ? Dites-nous ce qu'il faut mesurer ensuite.

Commentaires

Ni compte ni traceur : un commentaire est lu par un humain avant d'apparaître.