Manipuler le DOM avec l'IA : créer des pages interactives

Apprenez à manipuler le DOM JavaScript avec l'aide d'un LLM. Event listeners, UI dynamique et bonnes pratiques pour des pages web interactives.

Le DOM : là où JavaScript devient visible

Troisieme article de la serie "Apprendre JavaScript avec l'IA". On a couvert les bases du langage dans l'article précédent. Maintenant, on touche a ce que l'utilisateur voit : la page web.

Le DOM (Document Object Model), c'est la representation de ta page HTML sous forme d'arbre d'objets. Chaque balise HTML devient un noeud que JavaScript peut lire, modifier, supprimer ou créer. Sans le DOM, JavaScript ne sert a rien cote navigateur.

C'est aussi un domaine ou les LLM generent du code rapidement. Trop rapidement, parfois. L'objectif ici, c'est de comprendre ce que l'IA produit, pas de le copier.

Selectionner des éléments

Trois méthodes a connaître. Pas plus.

javascript// Par ID : retourne un seul element
const titre = document.getElementById("mon-titre");

// Par selecteur CSS : le premier qui correspond
const bouton = document.querySelector(".btn-primary");

// Par selecteur CSS : tous ceux qui correspondent
const tousLesBoutons = document.querySelectorAll(".btn-primary");

querySelector et querySelectorAll acceptent n'importe quel sélecteur CSS. C'est pour ca que je déconseillé getElementById dans du code moderne -- querySelector("#mon-titre") fait la meme chose avec une syntaxe plus coherente.

Un piège classique que l'IA généré souvent :

javascriptconst boutons = document.querySelectorAll("button");

// L'IA ecrit ca, mais ca plante :
// boutons.map(b => b.textContent);
// TypeError: boutons.map is not a function

// querySelectorAll retourne un NodeList, pas un Array
// Il faut convertir :
const textes = Array.from(boutons).map((b) => b.textContent);

J'ai vu ChatGPT et Claude faire cette erreur tous les deux. Teste toujours dans la console du navigateur.

Les événements : tout commence par addEventListener

Un clic, une saisie clavier, un scroll -- tout ca déclenché des événements. addEventListener est la méthode pour les écoûter.

"Cree un bouton HTML qui compte les clics. Utilise addEventListener, pas onclick dans le HTML."

html<button id="compteur-btn">Clics : 0</button>
javascriptconst bouton = document.getElementById("compteur-btn");
let clics = 0;

bouton.addEventListener("click", () => {
  clics++;
  bouton.textContent = `Clics : ${clics}`;
});

Six lignes. Selection, événement, mise à jour du DOM. C'est le schema de base de toute interactivite en JavaScript.

Pour les formulaires, l'événement input permet de reagir en temps réel :

html<input type="text" id="recherche" placeholder="Rechercher...">
<ul id="liste">
  <li>JavaScript</li>
  <li>TypeScript</li>
  <li>Python</li>
  <li>Rust</li>
</ul>
javascriptconst champ = document.getElementById("recherche");
const elements = document.querySelectorAll("#liste li");

champ.addEventListener("input", (e) => {
  const terme = e.target.value.toLowerCase();
  elements.forEach((el) => {
    el.style.display = el.textContent.toLowerCase().includes(terme) ? "" : "none";
  });
});

Ca filtre la liste en temps réel. Avec 50 éléments, aucun problème. Avec 10 000, il faudrait un debounce pour éviter de recalculer a chaque frappe. Demande a ton LLM :

"Ajoute un debounce de 300ms a cette fonction de filtrage. Explique pourquoi c'est nécessaire avec une grande liste."

Projet : construire une todo list de zero

On arrêté les petits exemples. On construit un vrai composant, étape par étape, en demandant de l'aide a l'IA quand on bloque.

Le HTML :

html<form id="todo-form">
  <input type="text" id="todo-input" placeholder="Nouvelle tache..." required>
  <button type="submit">Ajouter</button>
</form>
<ul id="todo-list"></ul>

Étape 1 : ajouter une tache. Essaie d'abord seul. Si tu bloques :

"Comment écoûter le submit d'un formulaire en JavaScript, récupérer la valeur d'un input, et ajouter un élément li a une liste ul ?"

javascriptconst formulaire = document.getElementById("todo-form");
const champTache = document.getElementById("todo-input");
const liste = document.getElementById("todo-list");

formulaire.addEventListener("submit", (e) => {
  e.preventDefault();
  const texte = champTache.value.trim();
  if (!texte) return;

  const li = document.createElement("li");
  li.textContent = texte;
  liste.appendChild(li);

  champTache.value = "";
  champTache.focus();
});

Étape 2 : marquer comme terminee. On veut qu'un clic sur la tache bascule une classe CSS.

javascript// Ajoute ca dans le handler du submit, apres la creation du li
li.addEventListener("click", () => {
  li.classList.toggle("terminee");
});
css.terminee {
  text-decoration: line-through;
  opacity: 0.5;
}

Étape 3 : supprimer une tache. On ajoute un bouton de suppression.

javascriptconst btnSupprimer = document.createElement("button");
btnSupprimer.textContent = "X";
btnSupprimer.style.marginLeft = "10px";
btnSupprimer.addEventListener("click", (e) => {
  e.stopPropagation(); // Empeche le toggle de "terminee"
  li.remove();
});
li.appendChild(btnSupprimer);

e.stopPropagation() est un détail que l'IA oublie souvent. Sans lui, cliquer sur "X" declencherait aussi le toggle de la classe terminee. Teste sans pour voir la différence.

Pourquoi createElement et pas innerHTML

L'IA propose souvent innerHTML parce que c'est moins de code. Mais c'est un trou de sécurité :

javascript// Dangereux : si texte contient du HTML malveillant
liste.innerHTML += `<li>${texte}</li>`;
// Un utilisateur pourrait taper : <img src=x onerror="alert('hack')">

// Securise : createElement + textContent echappe automatiquement le HTML
const li = document.createElement("li");
li.textContent = texte;

Si l'IA te généré du innerHTML avec des donnees utilisateur, c'est une faille XSS. Demande-lui toujours :

"Ce code est-il vulnerable aux injections XSS ? Montre la version sécurisée."

Delegation d'événements

Notre todo list a un listener par élément. Avec 100 taches, ca fait 100 listeners en mémoire. La délégation d'événements resout ca :

javascript// Un seul listener sur le parent
liste.addEventListener("click", (e) => {
  if (e.target.tagName === "BUTTON") {
    e.target.parentElement.remove();
  }
  if (e.target.tagName === "LI") {
    e.target.classList.toggle("terminee");
  }
});

Un listener au lieu de cent. Et ca fonctionne meme pour les éléments ajoutes apres le chargement de la page, parce qu'on écoûte le parent et pas les enfants. C'est un pattern que tout développeur frontend freelance doit connaître.

Exercice : modifier le code de l'IA

Demande a Claude ou ChatGPT :

"Cree un composant accordeon en JavaScript pur. Trois sections avec titre et contenu. Cliquer sur un titre ouvre le contenu et ferme les autres."

L'IA va générer quelque chose de fonctionnel. Ton travail :

  1. Lis le code ligne par ligne. Identifie chaque méthode DOM utilisee.
  2. Ajoute une animation CSS sur l'ouverture (transition sur max-height).
  3. Modifie le code pour pouvoir ouvrir plusieurs sections en meme temps.
  4. Recolle ta version modifiee dans le LLM et demande une review.

Cette boucle (générer, comprendre, modifier, faire valider) est exactement ce qui séparé "utiliser l'IA" et "apprendre avec l'IA". C'est aussi l'approche qu'on utilise chez paltemps.fr pour le développement API sur mesure : on part d'un prototype généré, on l'affine, on le teste.

La suite

Dans le prochain article, on s'attaque au sujet le plus redoute : l'asynchrone. Promises, async/await, fetch API. C'est la que l'IA peut vraiment t'aider a debloquer.

Sources

Réservez un audit gratuit de 30 minutes. Je vous montre concrètement ce qu'on peut automatiser.