DOM en JavaScript : le modèle objet de document

Utilise JavaScript pour modifier une page web pendant qu’elle est ouverte. Découvre comment le navigateur transforme le HTML en arbre d’objets, sélectionne les éléments dont tu as besoin et modifie leur texte, leurs attributs, leurs classes et leurs styles. Crée, déplace et supprime des éléments, et transforme des tableaux de données en listes et en tableaux qui restent synchronisés avec les données, le tout sans recharger la page.

DébutantUnité 5 sur 9 de la formation Formation : JavaScript : DOM, événements et code asynchrone

Ce que tu vas apprendre

  1. Explique ce qu’est le modèle objet de document, comment le navigateur le construit à partir du HTML et comment ses nœuds sont reliés entre eux, afin de te repérer dans n’importe quelle page.
    • Décris le DOM comme un arbre de nœuds
      Explique ce qu’est le DOM, comment le navigateur le construit à partir du HTML, quels types de nœuds il contient et en quoi il diffère du code source HTML.
    • Passe d’un élément à son parent, à ses enfants et à ses frères
      Parcours l’arbre depuis n’importe quel élément vers les nœuds qui lui sont liés, choisis entre les propriétés qui incluent les nœuds texte et celles qui ne renvoient que des éléments, et trouve l’ancêtre correspondant le plus proche.
  2. Trouve exactement les éléments dont un script a besoin à l’aide de sélecteurs CSS, gère les éléments absents et manipule des collections d’éléments correspondants.
    • Sélectionne un seul élément
      Trouve un élément avec querySelector ou getElementById, effectue une recherche dans une partie de la page et gère le cas où rien ne correspond.
    • Sélectionne plusieurs éléments et manipule les résultats
      Sélectionne tous les éléments correspondants, parcours les résultats avec une boucle, convertis-les en tableau si nécessaire et sache reconnaître quand une collection se met à jour toute seule.
  3. Mets à jour le texte des éléments ainsi que les attributs et les propriétés qui les contrôlent, choisis la méthode sûre lorsque le contenu provient d’utilisateurs ou de données, et conserve des données supplémentaires sur les éléments.
    • Modifie le texte et le HTML à l’intérieur d’un élément
      Lis et remplace le contenu d’un élément avec textContent, innerText et innerHTML, et protège les pages contre le code injecté.
    • Lis et définis des attributs et des propriétés
      Manipule les attributs avec getAttribute et setAttribute ainsi que les propriétés correspondantes des éléments, et gère les attributs booléens et les différences entre attributs et propriétés.
    • Stocke des données sur les éléments et lis les champs de formulaire
      Conserve des informations supplémentaires sur les éléments avec des attributs de données, et lis et définis la valeur actuelle des champs de formulaire.
  4. Fais basculer des classes CSS, définis des styles en ligne lorsqu’une valeur est calculée, lis les styles appliqués par le navigateur et affiche ou masque des parties d’une page.
    • Ajoute, supprime et fais basculer des classes CSS
      Modifie l’apparence d’un élément en faisant basculer ses classes avec classList, et conserve les règles visuelles dans la feuille de style.
    • Définis des styles en ligne et lis les styles calculés
      Définis des styles en ligne avec la propriété style lorsqu’une valeur est calculée à l’exécution, supprime-les ensuite et lis les styles que le navigateur applique réellement.
    • Affiche et masque des parties d’une page
      Masque et affiche des éléments avec l’attribut hidden ou une classe, choisis parmi les façons dont CSS peut rendre un élément invisible et rends son état clair pour les utilisateurs de lecteurs d’écran.
  5. Construis de nouveaux éléments en JavaScript, place-les exactement là où ils doivent se trouver, et supprime, remplace ou copie des éléments pour modifier la page sans la recharger.
    • Crée de nouveaux éléments et insère-les
      Crée des éléments avec createElement, remplis-les de texte et d’attributs, et insère-les à la fin, au début ou à côté d’un autre élément.
    • Supprime, remplace et copie des éléments
      Retire des éléments de la page, vide un conteneur, remplace un élément par un autre et crée des copies avec cloneNode.
  6. Transforme des tableaux de données en listes et en tableaux sur la page, construis efficacement de nombreux éléments et maintiens la page synchronisée avec les données lorsqu’elles changent.
    • Construis des éléments de liste et des lignes de tableau à partir d’un tableau de données
      Transforme un tableau d’objets en éléments de liste ou en lignes de tableau avec textContent, prévois un affichage adapté pour les listes vides et les valeurs manquantes, et relie chaque élément à ses données.
    • Construis efficacement de nombreux éléments avec des fragments et des éléments template
      Insère de nombreux nouveaux éléments en une étape avec un DocumentFragment ou un seul appel à append, et réutilise du balisage écrit dans un élément HTML template.
    • Mets la page à jour lorsque les données changent
      Conserve les données comme unique source de vérité, réaffiche-les après chaque modification et présente des vues filtrées, triées et récapitulatives sans perdre les données d’origine.

DOM en JavaScript : cours

6 chapitres

1

Lis la page comme un arbre

Le navigateur transforme le HTML en objets que JavaScript peut lire et modifier. Ces objets forment un arbre : trouver un élément de la page implique donc aussi de comprendre où il se situe parmi les autres nœuds. Commence par relier les balises familières aux objets du navigateur. Suis ensuite les relations entre parents, enfants et frères, en prêtant attention aux nœuds texte créés à partir des espaces et des sauts de ligne. Les outils de développement te permettent de voir cet arbre pendant que ton code le modifie.

1.1 Le HTML devient un arbre d’objets

Le modèle objet de document, ou DOM, est l’arbre dynamique des objets de la page dans le navigateur. JavaScript lit et modifie ces objets pour mettre la page à jour sans la recharger. Le navigateur fournit l’API DOM ; JavaScript est le langage utilisé pour l’appeler.

Commencer par le document

document est le point d’entrée. document.documentElement fait référence à <html>, document.head à <head> et document.body à <body>. L’onglet du navigateur est représenté par window, dont la propriété document fait référence à ce document.

Chaque élément de l’arbre est un nœud. Les éléments représentent des balises ; les nœuds texte contiennent des caractères ; les nœuds commentaires contiennent des commentaires HTML ; le nœud document se trouve au-dessus des éléments de la page. Leurs valeurs nodeType sont respectivement 1, 3, 8 et 9. Tout élément est un nœud, mais les textes et les commentaires ne sont pas des éléments.

Lire les relations familiales
<ul id="menu"><li>Home</li><li>About</li></ul>

La liste est le parent de deux éléments de liste frères. Chacun est son enfant. Le premier possède un nœud texte enfant contenant « Home ». La liste est un ancêtre de ce nœud texte, et le texte est un descendant de la liste. Ces relations décrivent l’imbrication, pas les positions à l’écran.

Les espaces et les sauts de ligne entre les balises deviennent généralement des nœuds texte contenant des caractères d’espacement. Une liste indentée peut donc avoir deux éléments enfants mais plus de deux nœuds enfants. children et firstElementChild ne renvoient que des éléments ; childNodes et firstChild incluent les textes et les commentaires.

Comparer l’arbre au code source

L’analyse syntaxique transforme le balisage en arbre et peut le compléter ou le réparer. Les lignes écrites directement dans un <table> reçoivent un parent <tbody>. Les éléments <html>, <head> ou <body> manquants peuvent aussi être ajoutés. Effectue tes sélections dans l’arbre réel, y compris les éléments ajoutés par l’analyseur.

Les modifications apportées par un script affectent le DOM actuel du navigateur, pas le fichier HTML sur le serveur. « Afficher le code source de la page » montre le HTML d’origine, tandis que le panneau Éléments des outils de développement montre l’arbre actuel. Un rechargement reconstruit le DOM ; une modification seule n’enregistre pas les données correspondantes.

Inspecter un objet

Fais un clic droit sur un élément et choisis « Inspecter ». Saisis $0 dans la console pour faire référence à cet élément sélectionné. console.log($0) le présente sous forme de balisage ; console.dir($0) expose ses propriétés. Déplie une liste indentée pour voir les nœuds contenant des caractères d’espacement à côté de ses éléments de liste.

Points clés

  • Le DOM est un arbre fourni par le navigateur que JavaScript peut lire et modifier.
  • Les éléments, les textes, les commentaires et le document sont différents types de nœuds.
  • Les caractères d’espacement et les éléments ajoutés par l’analyseur peuvent rendre le DOM différent du HTML écrit.
  • Inspecte l’arbre actuel dans les outils de développement ; une modification du DOM ne réécrit pas le HTML du serveur.

1.2 Suis les relations entre parents, enfants et frères

Les propriétés de l’arbre permettent à un script d’atteindre du contenu voisin à partir d’un élément qu’il possède déjà. Choisis si ce chemin doit inclure les textes et les commentaires ou seulement les éléments.

Choisir les nœuds ou les éléments

Les propriétés pour les nœuds comprennent parentNode, childNodes, firstChild, lastChild, previousSibling et nextSibling. Leurs équivalents pour les éléments sont parentElement, children, firstElementChild, lastElementChild, previousElementSibling et nextElementSibling. children est une HTMLCollection ; childNodes est une NodeList.

<ul id="tasks">
  <li>Buy milk</li>
  <li>Call Sam</li>
</ul>

Ici, tasks.childNodes.length vaut 5 : deux éléments et trois suites de caractères d’espacement. tasks.children.length vaut 2. tasks.firstChild est un nœud texte contenant des caractères d’espacement, tandis que tasks.firstElementChild.textContent vaut « Buy milk ». Les indices commencent à 0 : tasks.children[1] est donc le deuxième élément de liste.

Suivre un chemin court
const tasks = document.querySelector("#tasks");
const first = tasks.firstElementChild;
const second = first.nextElementSibling;
console.log(second.textContent);
console.log(second.parentElement === tasks);

Le résultat est « Call Sam », puis true. tasks.lastElementChild atteint directement le même élément, tout comme tasks.children[tasks.children.length - 1].

Gérer l’absence d’un nœud lié

Le nextElementSibling du dernier élément de liste vaut null. Un élément sans enfant qui soit un élément a firstElementChild === null et une collection children vide. Le parentNode de l’élément HTML racine est le document, mais son parentElement vaut null.

Lire une propriété de null déclenche une TypeError. Vérifie d’abord le résultat ou utilise second.nextElementSibling?.textContent, qui donne undefined lorsqu’il n’existe pas d’élément suivant.

Trouver un élément englobant

closest(selector) vérifie l’élément actuel, puis ses ancêtres, et renvoie l’élément correspondant le plus proche ou null. Un bouton à l’intérieur de <li class="task" data-id="7"> peut utiliser button.closest(".task") ; le dataset.id de l’élément correspondant vaut « 7 ». matches(selector) teste quant à lui uniquement l’élément actuel et renvoie un booléen.

Les longs chemins tels que el.parentElement.parentElement.nextElementSibling dépendent d’une imbrication précise. L’ajout d’un élément conteneur change leur signification. Utilise des sélecteurs pour les zones nommées, une navigation courte pour les relations stables et closest() pour trouver un élément englobant.

Points clés

  • Utilise la navigation réservée aux éléments lorsque les caractères d’espacement et les commentaires doivent être ignorés.
  • Les indices des collections commencent à 0 ; leur longueur est un nombre d’éléments, pas le dernier indice.
  • Un nœud lié absent vaut null ; vérifie le résultat avant d’en lire une propriété.
  • closest() vérifie l’élément lui-même, puis ses ancêtres.
  • matches() teste l’élément actuel sans se déplacer dans l’arbre.
2

Trouve les éléments de la page

Une modification du DOM commence par une référence au bon élément. Les sélecteurs CSS permettent de rechercher dans toute la page ou seulement dans un conteneur, tandis que les méthodes de collection permettent de manipuler plusieurs résultats. La valeur renvoyée compte : une recherche peut donner un élément ou null, une autre donne toujours une collection. Tu devras aussi savoir quand le script s’exécute et si une collection enregistrée change lorsque la page change, car ces deux facteurs influencent ce que ton code trouve.

2.1 Trouve un élément et vérifie le résultat

Un sélecteur transforme une description d’élément en référence à un objet. Commence par la recherche la plus restreinte qui permet d’identifier l’élément voulu, puis vérifie qu’il a été trouvé avant de le modifier.

Rechercher avec un sélecteur CSS ou un identifiant

document.querySelector(selector) renvoie le premier élément correspondant dans l’ordre du document. Cette méthode accepte les sélecteurs CSS familiers : "h1", ".price", "#cart", "nav a" ou 'input[type="email"]'. Si rien ne correspond, elle renvoie null.

document.getElementById("cart") recherche directement un identifiant. Son argument est l’identifiant seul. getElementById("#cart") recherche un identifiant qui contient réellement le caractère dièse, tandis que querySelector("cart") recherche une balise <cart>. Utilise querySelector("#cart") pour le sélecteur d’identifiant.

Les identifiants doivent être uniques. Si du balisage copié donne le même identifiant à deux éléments, ces recherches renvoient le premier dans l’ordre du document. Corrige le balisage en double au lieu d’attendre d’une recherche par identifiant qu’elle atteigne la seconde copie.

Rechercher dans un conteneur

Supposons que plusieurs cartes possèdent un élément de classe name. Sélectionne d’abord la carte de profil, puis recherche parmi ses descendants :

const card = document.querySelector("#profile");
if (card) {
  const name = card.querySelector(".name");
  if (name) name.textContent = "Maya";
}

La recherche interne se limite à la carte de profil : un élément .name situé plus tôt ailleurs ne perturbe donc pas le résultat. Le conteneur lui-même ne fait pas partie des éléments examinés par sa propre recherche querySelector(). Les éléments ordinaires prennent en charge cette méthode, mais getElementById() appartient à document.

Distinguer une absence de résultat d’un sélecteur invalide

Une recherche valide sans correspondance donne null. Essayer de définir null.textContent déclenche une TypeError : protège donc l’accès au contenu facultatif :

const banner = document.querySelector(".banner");
if (banner) banner.textContent = "Sale ends Friday";

Un sélecteur CSS invalide déclenche une SyntaxError avant qu’un résultat puisse être obtenu. Pour <p id="1st">, querySelector("#1st") est invalide, car le chiffre doit être échappé dans ce sélecteur d’identifiant CSS. getElementById("1st") utilise un identifiant littéral et fonctionne directement.

Exécuter le script après la création du balisage nécessaire

Un script externe classique placé dans <head> s’exécute avant que le navigateur ait analysé le corps de la page. Une recherche portant sur un paragraphe situé plus bas renvoie donc null, même lorsque le HTML le contient. Utilise <script src="app.js" defer></script> pour exécuter le script après l’analyse, utilise un script de module ou place le script juste avant </body>. Les scripts de module sont différés par défaut. L’attribut defer n’a aucun effet sur un script interne classique.

Pour une page HTML commençant par <!DOCTYPE html>, les sélecteurs d’identifiant et de classe sont sensibles à la casse : .Price ne correspond pas à class="price". Les sélecteurs de balises HTML ne sont pas sensibles à la casse : "LI" et "li" correspondent donc tous deux aux éléments de liste. Lorsqu’une recherche échoue, vérifie l’orthographe, la syntaxe du sélecteur, le conteneur de recherche et le moment d’exécution du script.

Points clés

  • querySelector() renvoie le premier élément correspondant ou null.
  • getElementById() prend un identifiant seul ; querySelector() prend un sélecteur écrit selon la syntaxe CSS.
  • Effectue la recherche parmi les descendants d’un conteneur lorsqu’une classe apparaît dans plusieurs zones de la page.
  • Une recherche sans correspondance renvoie null ; une syntaxe de sélecteur invalide déclenche une erreur.
  • Exécute le code DOM après l’analyse du balisage dont il a besoin.
  • Garde des identifiants uniques et respecte la casse dans les sélecteurs d’identifiant et de classe.

2.2 Manipule des collections d’éléments correspondants

Utilise querySelectorAll() lorsque la même opération doit s’appliquer à plusieurs éléments. Son résultat est une collection : tu dois donc choisir comment la parcourir et déterminer si tu as besoin d’un instantané ou d’une vue dynamique.

Lire et parcourir une NodeList

document.querySelectorAll(".note") renvoie une NodeList des éléments correspondants dans l’ordre du document. En l’absence de correspondance, la NodeList est vide et sa longueur vaut 0. La collection elle-même reste une valeur vraie : if (notes) ne t’indique pas si elle contient des éléments. Vérifie notes.length.

Une NodeList prend en charge les indices, length, forEach() et for...of, mais ce n’est pas un tableau et elle n’a ni map(), ni filter(), ni reduce(). Convertis-la lorsque tu as besoin de ces méthodes :

const weights = Array.from(document.querySelectorAll(".weight"))
  .map(el => Number(el.textContent));
const total = weights.reduce((sum, weight) => sum + weight, 0);

Pour des éléments contenant « 4.5 », « 12 » et « 3.25 », le tableau est [4.5, 12, 3.25] et le total est de 19,75 kg. La conversion en nombres est importante, car les valeurs textuelles sont des chaînes.

Une collection n’est pas un élément combiné. Définir notes.textContent ne modifie aucune note, et notes.classList.add("saved") déclenche une erreur, car la NodeList n’a pas de classList. Applique la modification à chaque élément :

const notes = document.querySelectorAll(".note");
notes.forEach(note => note.classList.add("saved"));
Comparer les résultats statiques et dynamiques

La NodeList issue de querySelectorAll() est statique : les éléments qu’elle contient sont fixés au moment de la recherche. Les éléments auxquels elle fait référence restent les objets réels ; leur texte ou leurs classes peuvent donc changer.

getElementsByClassName("note") et getElementsByTagName("li") renvoient une HTMLCollection dynamique. children est aussi dynamique. Ces collections mettent à jour les éléments qu’elles contiennent lorsque le DOM change. Elles prennent en charge les indices et for...of, mais pas forEach().

Dans une liste contenant trois éléments .item, enregistre à la fois list.getElementsByClassName("item") et list.querySelectorAll(".item"). Ajoute un quatrième élément correspondant. La longueur de la collection dynamique vaut maintenant 4 ; celle de l’instantané vaut toujours 3.

Éviter le piège d’une collection dynamique qui rétrécit pendant une boucle

Supposons que quatre éléments appartiennent à une collection dynamique nommée live :

for (let i = 0; i < live.length; i++) {
  live[i].classList.remove("item");
}

Retirer la classe du premier élément le retire de la collection. L’élément suivant passe à l’indice 0, mais la boucle avance à l’indice 1 et l’ignore. Seuls deux des quatre éléments perdent la classe. Parcours Array.from(live) ou un instantané obtenu avec querySelectorAll() lorsque tu modifies l’appartenance à la collection.

Vérifier les espaces dans les sélecteurs

.task.done désigne un élément possédant les deux classes. .task .done désigne un descendant .done situé dans un élément .task. Pour <li class="task done">, compte les éléments terminés avec document.querySelectorAll(".task.done").length. Une virgule combine des sélecteurs : "h2, h3" renvoie les éléments correspondants dans l’ordre du document, et non tous les titres d’un type suivis de ceux de l’autre.

Points clés

  • Parcours les membres d’une collection avec une boucle pour modifier leur contenu ou leurs classes.
  • querySelectorAll() renvoie une NodeList statique ; un résultat vide a une longueur de 0.
  • Convertis les collections avec Array.from() ou la syntaxe de décomposition avant d’utiliser des méthodes réservées aux tableaux.
  • Les collections dynamiques mettent à jour leurs membres lorsque les éléments correspondants changent.
  • Prends un instantané avant une boucle qui retire des membres d’une collection dynamique.
  • Un espace dans un sélecteur change la relation recherchée.
3

Mets à jour le contenu et les données des éléments

Un élément contient plusieurs types d’informations : du texte visible, une structure HTML, des attributs et des propriétés JavaScript. Choisir le bon type te permet de mettre à jour un libellé, de modifier un lien, de lire un champ ou de relier un élément affiché à ses données. Un même texte peut être traité comme de simples caractères ou analysé comme du HTML, avec des résultats très différents. Examine attentivement ces différences pour que les mises à jour affichent le contenu voulu et que le texte extérieur reste sans danger.

3.1 Choisis entre texte et HTML pour mettre à jour le contenu

Le texte et le HTML sont des entrées différentes. Le texte brut doit apparaître sous forme de caractères ; le HTML décrit des éléments que le navigateur doit construire. Le choix entre les deux a des conséquences sur la structure de la page et sur la possibilité qu’un texte extérieur exécute du code indésirable.

Lire et remplacer du texte

Pour <p id="msg">Total: <strong>3</strong> items</p>, msg.textContent vaut « Total: 3 items ». Cette propriété réunit le texte des descendants de l’élément sans inclure leurs balises, et inclut le texte masqué par CSS.

Définir textContent remplace tous les enfants par un nœud texte. Après msg.textContent = "Cart is empty", l’enfant <strong> n’existe plus dans le paragraphe. Définir msg.textContent = "<b>Hi</b>" affiche les caractères littéraux « Hi » ; cela ne crée aucun élément en gras.

Les valeurs textuelles sont des chaînes. Si un compteur contient « 4 », count.textContent + 1 produit « 41 ». Convertis la valeur avant l’addition :

count.textContent = Number(count.textContent) + 1;

L’addition donne le nombre 5, et l’affectation affiche sa forme textuelle, « 5 ».

Lire le texte qui suit la mise en page

Pour un élément affiché, innerText suit le texte affiché et la mise en page. Cette propriété omet les descendants masqués avec display: none et inclut les sauts de ligne qui suivent la mise en page. Sa lecture peut nécessiter un calcul de mise en page. Utilise textContent pour les opérations courantes sur le texte ; choisis innerText lorsque tu as besoin du texte affiché. Si l’élément lui-même est détaché ou n’est pas affiché, innerText renvoie son contenu textuel.

Analyser volontairement du HTML

innerHTML lit le balisage à l’intérieur d’un élément. Le définir analyse la chaîne et remplace les enfants :

msg.innerHTML = "Total: <strong>5</strong> items";

Cela crée un nouvel élément <strong>. Cette méthode convient au balisage que tu as écrit et que tu contrôles. Pour le texte provenant d’un utilisateur ou de données extérieures, utilise textContent et construis la structure avec createElement().

L’insertion de HTML non fiable peut permettre une injection de script intersite (XSS) : du code contrôlé par un attaquant s’exécute dans le navigateur du visiteur. Une image injectée peut porter un attribut onerror qui exécute du code lorsque le chargement de l’image échoue. Les balises script insérées par innerHTML ne s’exécutent pas, mais cela ne rend pas les autres formes de HTML injecté sûres. Bloquer seulement les balises script laisse cette voie d’attaque ouverte.

Conserver les enfants existants lors de l’ajout de contenu

list.innerHTML += "<li>New</li>" lit le balisage existant, y concatène une chaîne, puis analyse et remplace l’ensemble des enfants. Cette opération ne préserve pas leur identité d’objet. Une variable contenant un ancien enfant conserve cet objet détaché, et les valeurs saisies dans les champs remplacés peuvent être perdues. Utilise append() avec de nouveaux nœuds, ou insertAdjacentHTML("beforeend", markup) pour du balisage fiable, afin d’ajouter du contenu sans recréer les enfants existants.

outerHTML inclut la balise de l’élément lui-même ainsi que son contenu. Le définir remplace l’élément lui-même. Une référence enregistrée pointe toujours vers l’ancien élément détaché après ce remplacement ; elle ne bascule pas automatiquement vers le nouvel élément.

Points clés

  • textContent traite le texte brut et remplace les enfants de l’élément lorsqu’on lui affecte une valeur.
  • Convertis le texte en nombre avant d’effectuer un calcul.
  • innerText suit la mise en page affichée ; innerHTML analyse le balisage.
  • N’insère pas de texte non fiable dans des affectations qui analysent du HTML.
  • innerHTML += recrée les enfants existants ; append() les conserve.
  • Une affectation à outerHTML remplace l’élément et laisse les anciennes références pointer vers l’élément détaché.

3.2 Distingue les attributs des propriétés d’objet

Un attribut est un nom et une valeur dans le HTML. Une propriété appartient à l’objet JavaScript qui représente un élément. De nombreux attributs standard possèdent des propriétés correspondantes, mais ces propriétés peuvent traiter les valeurs ou indiquer un autre type d’état.

Manipuler un attribut par son nom

Pour <img src="logo.png" alt="Company logo">, le navigateur initialise des propriétés telles que img.src et img.alt. Tu peux aussi utiliser des méthodes qui prennent le nom de l’attribut sous forme de chaîne :

  • getAttribute(name) renvoie une chaîne, ou null si l’attribut est absent.
  • setAttribute(name, value) ajoute ou modifie un attribut et enregistre sa valeur sous forme de texte.
  • hasAttribute(name) indique si l’attribut est présent.
  • removeAttribute(name) le supprime.

Par exemple, link.setAttribute("href", "https://example.com/help") modifie la cible d’un lien. En l’absence d’attribut target, link.getAttribute("target") renvoie null, et non une chaîne vide.

Lire la valeur dont tu as réellement besoin

Sur une page située à https://example.com/shop/, le lien <a href="/about"> possède un attribut dont la valeur est « /about ». Sa propriété href est l’URL résolue, « https://example.com/about ». Lis l’attribut lorsque tu as besoin de la valeur exactement telle qu’elle est écrite, et la propriété lorsque tu as besoin de l’URL résolue.

Les propriétés peuvent avoir d’autres types que les chaînes. button.disabled est un booléen ; input.maxLength est un nombre. Les méthodes d’attributs renvoient toujours des chaînes ou null. Les noms de propriétés sont aussi des noms JavaScript sensibles à la casse : el.id fonctionne, tandis que el.ID est une propriété différente qui vaut normalement undefined.

La plupart des noms sont familiers, mais il existe des exceptions. L’attribut HTML class est accessible par className et classList. L’attribut for d’un label correspond à sa propriété htmlFor :

label.htmlFor = "email";

Cela associe le label à l’élément dont l’identifiant est « email ».

Traiter les attributs booléens selon leur présence

Les attributs booléens comprennent disabled, checked, required et readonly. Leur présence signifie que l’attribut est vrai, même si son texte est « false ». Ce code désactive un bouton :

button.setAttribute("disabled", "false");

Pour l’activer, définis button.disabled = false ou appelle button.removeAttribute("disabled"). button.toggleAttribute("disabled", isBusy) ajoute l’attribut lorsque isBusy est vrai et le supprime lorsque cette valeur est fausse.

Décrire les composants de manière accessible

Les attributs ARIA fournissent des informations aux technologies d’assistance. Les méthodes d’attributs sont utiles pour les définir, par exemple button.setAttribute("aria-label", "Close dialog") pour nommer un bouton composé d’une seule icône. Leurs valeurs sont des chaînes ; par exemple, une valeur indiquant l’état développé est « true » ou « false ».

Utilise les propriétés pour les opérations courantes telles que img.src = "photo.jpg" ou input.disabled = true. Utilise les méthodes d’attributs lorsque le nom est stocké dans une variable, lorsque la valeur exacte écrite est importante ou lorsque l’attribut ne possède pas de propriété correspondante que tu utilises.

Suivre l’effet d’une modification de propriété sur le HTML
const field = document.createElement("input");
field.disabled = true;
console.log(field.hasAttribute("disabled"));
console.log(typeof field.disabled);
console.log(typeof field.getAttribute("disabled"));
field.removeAttribute("disabled");
console.log(field.disabled);

Les résultats sont true, « boolean », « string » et false. Définir la propriété ajoute l’attribut booléen. Lire cet attribut renvoie toujours du texte, même si la propriété est un booléen. Le supprimer redonne à la propriété la valeur faux. La méthode et la propriété exposent la même présence au moyen de types de valeurs différents.

Points clés

  • Les attributs stockent des valeurs HTML ; les propriétés peuvent exposer des valeurs typées ou traitées.
  • getAttribute() renvoie une chaîne ou null lorsque l’attribut est absent.
  • Les attributs booléens sont vrais par leur présence, y compris disabled="false".
  • Utilise des noms de propriétés tels que className et htmlFor lorsque les noms HTML diffèrent.
  • Les valeurs ARIA sont des chaînes qui décrivent l’élément aux technologies d’assistance.

3.3 Relie les éléments aux données et lis les champs

Un élément peut porter un identifiant pour les données qu’il affiche sans montrer cet identifiant à l’écran. Les composants de formulaire portent aussi des valeurs, mais leur contenu actuel se lit par des propriétés. Ces deux types de valeurs nécessitent souvent une conversion avant une comparaison ou un calcul.

Stocker des données personnalisées avec des attributs de données

Les noms HTML commençant par data- stockent des informations pour les scripts :

<li data-task-id="17" data-priority="high">Prepare slides</li>

L’objet dataset donne accès à ces attributs. Retire le préfixe data- et remplace chaque tiret suivi d’une lettre minuscule par cette lettre en majuscule : data-task-id devient dataset.taskId. data-priority devient dataset.priority.

li.dataset.dueDate = "2026-11-05";
delete li.dataset.priority;

L’affectation crée data-due-date="2026-11-05". L’instruction delete supprime data-priority. Les attributs de données peuvent aussi être sélectionnés avec des sélecteurs d’attribut CSS, tels que '[data-priority="high"]'.

Un attribut inventé comme taskid="17" rend le HTML invalide et ne crée aucune propriété li.taskid. getAttribute("taskid") peut toujours le lire, mais data-task-id est la forme correcte pour une donnée personnalisée.

Convertir volontairement les valeurs de type chaîne

li.dataset.taskId vaut « 17 », une chaîne. li.dataset.taskId === 17 est faux, car les types diffèrent. Lorsque les identifiants des données sont des nombres, utilise Number(li.dataset.taskId) === 17. Un attribut de données absent donne undefined. L’affectation li.dataset.count = 3 enregistre le texte « 3 ».

Cela permet de relier facilement un élément affiché à son objet :

const id = Number(li.dataset.taskId);
const task = tasks.find(task => task.id === id);

La comparaison utilise maintenant deux nombres. Si aucun objet ne possède cet identifiant, find() renvoie undefined ; vérifie le résultat avant d’en lire les propriétés.

Lire la valeur actuelle d’un champ

Un <input> ne contient pas la valeur saisie dans son contenu textuel. Lis input.value, qui est une chaîne, ou affecte-lui une valeur pour modifier le champ. input.value = "" vide le champ.

Pour <input id="qty" value="1">, après que l’utilisateur a saisi 3, qty.value vaut « 3 », mais qty.getAttribute("value") vaut toujours « 1 ». L’attribut fournit la valeur initiale ; la propriété fournit la valeur actuelle. Une case à cocher fonctionne de façon similaire : sa propriété checked indique son état booléen actuel, tandis que l’attribut décrit l’état coché initial.

Utiliser la bonne valeur pour chaque composant

Même <input type="number"> possède une value de type chaîne. Si la quantité est « 3 » et que chaque article pèse 0,25 kg, Number(qty.value) * 0.25 donne 0,75 kg. Mais qty.value + 1 donne « 31 », car + concatène une chaîne et un nombre. Un <select> renvoie la valeur de l’option sélectionnée par select.value. Pour une case à cocher, lis checkbox.checked, et non checkbox.value, lorsque tu dois savoir si elle est cochée.

Points clés

  • dataset associe data-task-id à taskId et stocke des valeurs sous forme de chaînes.
  • Utilise delete sur une propriété de dataset pour supprimer son attribut de données.
  • Convertis les identifiants des données avant une comparaison stricte avec des identifiants numériques.
  • Lis le contenu actuel des champs input et select avec value.
  • Lis l’état actuel d’une case à cocher avec checked.
  • Les attributs initiaux value et checked peuvent différer des propriétés actuelles du composant.
4

Contrôle l’apparence et la visibilité

JavaScript peut modifier l’apparence d’une page en faisant basculer des classes, en définissant une valeur calculée en ligne ou en masquant une section. Ces choix fonctionnent avec le CSS déjà présent sur la page. Découvre quel état placer dans une classe, quelles valeurs ont besoin d’unités et comment lire le style appliqué par le navigateur. Afficher et masquer des éléments a aussi des conséquences sur la mise en page et les technologies d’assistance : maintiens donc les panneaux visibles et leurs attributs d’accessibilité synchronisés.

4.1 Fais basculer les classes sans perdre le style de base

Conserve les règles visuelles fixes dans CSS, puis laisse JavaScript modifier les classes qui sélectionnent ces règles. Une classe peut exprimer un état tel que « terminé », « actif » ou « erreur » sans répéter dans le code les couleurs et les décorations correspondantes.

Ajouter et supprimer des noms de classes

Supposons que la feuille de style contienne :

.done { text-decoration: line-through; color: #888; }

item.classList.add("done") applique l’apparence correspondant à une tâche terminée. item.classList.remove("done") supprime cet état tout en conservant les autres classes. Les deux méthodes acceptent plusieurs noms ; ajouter une classe existante ou supprimer une classe absente ne pose aucun problème.

contains("done") renvoie un booléen. replace("wide", "narrow") remplace une classe présente par une autre. toggle("active") ajoute une classe absente ou supprime une classe présente et indique par sa valeur de retour si la classe existe après l’appel.

Suivre un changement de classe

Pars de <div class="card"> :

card.classList.add("active", "wide");
const active = card.classList.toggle("active");
const replaced = card.classList.replace("wide", "narrow");

Après la première ligne, les classes sont « card active wide ». Le basculement supprime « active » : active vaut donc false et les classes deviennent « card wide ». Le remplacement de « wide » laisse « card narrow » et renvoie true. Un appel ultérieur à card.classList.contains("active") donne false.

Définir une classe à partir d’une condition

Lorsque les données indiquent l’état souhaité, passe un second argument :

row.classList.toggle("overdue", daysLeft < 0);

Une valeur négative de daysLeft garantit la présence de la classe ; sinon, elle est absente. Répéter l’appel conserve cet état. Un simple toggle("overdue") l’inverserait à chaque appel.

Conserver le reste de l’attribut de classe

className est la chaîne complète des classes. card.className = "active" remplace toutes les classes existantes, y compris « card ». Utilise cette affectation lorsque tu veux remplacer tout l’ensemble ; utilise classList pour modifier des états individuellement.

Passe les noms de classes seuls, sans la ponctuation des sélecteurs CSS. classList.add(".active") ajoute un nom contenant un point littéral ; ce n’est pas la classe à laquelle correspond .active. Un argument unique ne peut pas contenir d’espaces : classList.add("big red") déclenche une InvalidCharacterError. Écris classList.add("big", "red") pour deux classes.

Vérifier le CSS lorsque l’apparence ne change pas

Si une classe n’a aucun effet visible, inspecte son nom et sa règle dans les outils de développement. Vérifie si une règle est absente ou mal orthographiée et si des déclarations supplantées sont barrées dans le volet Styles.

Points clés

  • classList modifie des noms de classes individuellement tout en conservant les autres classes.
  • toggle(name) indique par sa valeur de retour si la classe est présente après l’appel.
  • toggle(name, condition) définit une classe à partir des données sans inverser son état à chaque exécution.
  • Une affectation à className remplace toute la chaîne des classes.
  • Passe des noms séparés, sans point de sélecteur ni espace à l’intérieur d’un nom.

4.2 Définis des styles calculés et lis les styles appliqués

Utilise des classes pour les apparences fixes et des styles en ligne pour les valeurs calculées. L’objet style lit et écrit les déclarations en ligne, pas toutes les règles qui affectent un élément.

Écrire des valeurs CSS avec style

Les noms CSS contenant des tirets deviennent des propriétés JavaScript en camelCase. background-color devient backgroundColor, font-size devient fontSize et z-index devient zIndex :

box.style.backgroundColor = "gold";
box.style.width = "250px";

Les valeurs de style sont des chaînes. Inclus une unité lorsque la propriété l’exige. Dans une page en mode standard, l’affectation box.style.width = 250 est ignorée, car une largeur non nulle a besoin d’une unité CSS. La chaîne « 0 » est valide pour une largeur nulle.

style.setProperty() prend quant à lui le nom CSS :

box.style.setProperty("background-color", "gold");
document.documentElement.style.setProperty("--accent", "#0a7d5a");

La propriété personnalisée de l’élément racine fournit une valeur aux règles qui font référence à var(--accent).

Transformer un calcul en valeur CSS

Une barre de progression indique que 3 tâches sur 8 sont terminées :

const percent = (3 / 8) * 100;
bar.style.width = `${percent}%`;

Le rapport 0,375 devient 37,5 %. Le littéral de gabarit fournit « 37.5% », avec l’unité requise.

Supprimer une déclaration en ligne temporaire

Définis box.style.backgroundColor = "" ou appelle box.style.removeProperty("background-color") pour supprimer cette déclaration en ligne. Le navigateur applique alors les règles restantes de la feuille de style. Utilise le nom CSS avec des tirets pour removeProperty().

Fais attention à style.cssText. L’affectation box.style.cssText = "color: red" remplace tout le style en ligne : une largeur définie en ligne est donc perdue. Modifier une seule propriété de style laisse les autres déclarations en ligne intactes.

Lire ce que le navigateur applique

Si une feuille de style rend un paragraphe rouge mais que celui-ci n’a pas de couleur définie en ligne, p.style.color est une chaîne vide. Utilise getComputedStyle(p).color pour obtenir la valeur appliquée, généralement « rgb(255, 0, 0) ». Les valeurs calculées sont accessibles en lecture seule ; modifie la classe ou la déclaration en ligne pour changer l’apparence.

Les déclarations en ligne prennent le dessus sur les règles ordinaires de la feuille de style, mais les déclarations !important applicables peuvent l’emporter. Si un changement de classe semble sans effet, vérifie s’il reste une déclaration en ligne qui prend le dessus.

Points clés

  • style lit et écrit les déclarations en ligne ; les noms en camelCase correspondent aux noms CSS avec des tirets.
  • Fournis les unités dans les chaînes de valeurs CSS lorsqu’elles sont requises.
  • setProperty() et removeProperty() prennent des noms CSS avec des tirets.
  • Supprime une déclaration en ligne pour permettre aux règles de la feuille de style de s’appliquer à nouveau.
  • getComputedStyle() indique les valeurs appliquées, y compris les styles issus des règles CSS.

4.3 Masque du contenu et rends son état clair

Masquer un panneau le laisse dans le DOM, prêt à réapparaître avec son contenu et les valeurs de ses champs. Le supprimer le retire de l’arbre. Choisis de masquer un panneau qui réapparaîtra et de supprimer un élément dont les données n’existent plus.

Utiliser la propriété hidden

panel.hidden = true ajoute l’état masqué ordinaire. Le style par défaut du navigateur masque le panneau sans lui laisser d’espace dans la mise en page. panel.hidden = false supprime cet état et l’affiche à nouveau.

Une feuille de style peut prendre le dessus sur ce comportement par défaut. Par exemple, .panel { display: flex; } peut rendre visible un panneau masqué. Lorsque l’état masqué doit toujours l’emporter, inclus :

[hidden] { display: none !important; }

Tu peux aussi contrôler la visibilité avec une classe CSS. Avec .is-hidden { display: none; }, menu.classList.toggle("is-hidden", !isOpen) ajoute la classe de masquage lorsque le menu est fermé. Vérifie la feuille de style si la classe est présente mais qu’une autre déclaration de display prend le dessus.

Comparer trois façons de masquer

display: none supprime l’espace de l’élément dans la mise en page et le masque aux lecteurs d’écran. visibility: hidden le rend invisible tout en conservant son espace et le masque aussi aux lecteurs d’écran. opacity: 0 le rend transparent mais conserve son espace ; l’élément reste cliquable et accessible aux lecteurs d’écran. La transparence seule est donc une mauvaise façon de fermer un panneau qui ne devrait plus être accessible.

Ces effets concernent la visibilité et la mise en page, pas la suppression. Un champ masqué peut conserver la valeur qui y a été saisie, car le même objet reste dans l’arbre.

Maintenir la description du bouton à jour

Un bouton associé à un panneau repliable doit indiquer si celui-ci est déployé. Définis aria-expanded à la chaîne « true » lorsqu’il est ouvert et à « false » lorsqu’il est fermé. Fais dépendre cette valeur et la visibilité du panneau du même état.

Pour un panneau de réponse initialement défini par <div id="answer-1" hidden>, avec des références nommées answer et button, exécute :

const willOpen = answer.hidden;
answer.hidden = !willOpen;
button.setAttribute("aria-expanded", String(willOpen));

Au départ, answer.hidden vaut true, donc willOpen est vrai. L’affectation donne à hidden la valeur faux et affiche le panneau. L’attribut du bouton devient « true ». Exécuter à nouveau les mêmes instructions part d’un état hidden faux, masque le panneau et écrit « false » dans l’attribut.

Diagnostiquer une incohérence

Si le bouton annonce « déployé » alors que le panneau est masqué, les deux valeurs n’ont pas été mises à jour ensemble. Si hidden est vrai mais que le panneau reste visible, inspecte son display calculé et la règle CSS responsable. Le premier problème est un état incohérent de l’application ; le second est un style qui prend le dessus sur l’état masqué. Lire à la fois les propriétés DOM et le CSS appliqué permet de les distinguer.

Points clés

  • hidden conserve le contenu dans le DOM tout en le masquant avec le style par défaut.
  • Une règle display explicite peut prendre le dessus sur hidden ; inspecte ou impose la règle souhaitée.
  • display: none supprime l’espace ; visibility: hidden le conserve.
  • opacity: 0 conserve les possibilités d’interaction et l’accès par les lecteurs d’écran.
  • Mets aria-expanded à jour à partir du même état d’ouverture que le panneau.
5

Construis et modifie la structure de la page

La structure d’une page peut changer pendant qu’elle est ouverte. Construis un élément en mémoire, remplis-le et insère-le au bon endroit dans l’arbre. Les mêmes méthodes d’insertion peuvent déplacer un nœud existant : ajouter deux fois une référence ne crée donc pas deux copies. Supprimer, remplacer et cloner produisent des changements différents dans l’arbre et dans les références conservées par ton script. Suivre ces références aide à comprendre pourquoi une ancienne variable pointe parfois vers du contenu détaché.

5.1 Crée un nœud, remplis-le, puis insère-le

Un nouvel élément n’apparaît pas simplement parce que tu l’as créé. Crée d’abord l’objet, donne-lui ensuite du contenu et des attributs, puis insère-le dans le document. Avant l’insertion, tu peux assembler en mémoire toute une structure imbriquée.

Construire un élément complet
const li = document.createElement("li");
li.textContent = "Water the plants";
li.className = "task";
li.dataset.id = "4";
document.querySelector("#tasks").append(li);

createElement("li") crée un élément vide. Les lignes suivantes le remplissent ; la dernière l’insère comme dernier enfant de la liste de tâches existante. Elle produit <li class="task" data-id="4">Water the plants</li>. L’appel attend un nom de balise, pas du balisage : createElement("<li>") déclenche une InvalidCharacterError. Définis les classes et les attributs après la création.

Pour du contenu imbriqué, crée séparément un span pour le titre et un bouton, définis leur texte et appelle li.append(title, button). Insère ensuite l’élément assemblé dans la liste. document.createTextNode("…") crée directement du texte ; passer une chaîne à append() insère aussi un nœud texte.

Choisir une position d’insertion
  • parent.append(...) ajoute après les enfants existants.
  • parent.prepend(...) ajoute avant les enfants existants.
  • element.before(...) ajoute des frères précédents.
  • element.after(...) ajoute des frères suivants.

Chaque méthode accepte plusieurs nœuds et chaînes. Les chaînes sont traitées comme du texte : list.append("<li>New</li>") ne construit donc pas un élément de liste. Les chevrons apparaissent comme des caractères dans la liste.

Des méthodes plus anciennes apparaissent encore dans le code. appendChild(node) accepte un nœud et le renvoie ; elle n’accepte pas de chaîne. append() renvoie undefined. parent.insertBefore(newNode, referenceNode) insère un nœud avant un enfant existant ; utiliser null comme référence l’ajoute à la fin.

Comprendre la différence entre déplacer et copier

Un nœud ne peut occuper qu’un seul endroit dans l’arbre. Insérer un nœud existant le déplace. Pour une liste dans l’ordre a, b, c, list.prepend(list.lastElementChild) déplace c au début et produit c, a, b. Cela ne laisse pas un second c à la fin.

Cela explique aussi un bogue courant dans une boucle : créer un seul <li> à l’extérieur de la boucle et l’ajouter à plusieurs reprises ne laisse qu’un seul élément. Chaque passage modifie et déplace ce même objet. Crée un nouvel élément à chaque passage lorsque la page en nécessite plusieurs, ou crée des clones distincts.

Insérer du balisage fiable à côté du contenu existant

insertAdjacentHTML(position, markup) analyse du HTML sans remplacer les enfants existants. Ses quatre noms de position sont "beforebegin" et "afterend" pour les frères à l’extérieur de l’élément, et "afterbegin" et "beforeend" pour les enfants à l’intérieur. list.insertAdjacentHTML("beforeend", "<li>New</li>") ajoute un élément analysé. Utilise cette méthode uniquement pour du balisage fiable ; le texte extérieur doit être placé dans textContent. insertAdjacentElement() et insertAdjacentText() utilisent les mêmes noms de position pour un élément ou du texte brut.

Points clés

  • Créer, remplir et insérer sont des étapes distinctes.
  • append et prepend ajoutent des enfants ; before et after ajoutent des frères.
  • Passer une chaîne à append() insère du texte sans analyser le HTML.
  • Insérer un nœud existant le déplace au lieu de le copier.
  • Crée un nouvel élément à chaque passage de la boucle lorsque tu as besoin de plusieurs objets.
  • appendChild() accepte un nœud et le renvoie ; append() accepte plusieurs entrées et renvoie undefined.
  • insertAdjacentHTML() conserve les enfants existants mais analyse tout de même son entrée comme du HTML.

5.2 Supprime, remplace et clone les bons objets

Supprimer un élément modifie l’arbre, mais n’efface pas toutes les références à cet objet. Son remplacement crée une distinction similaire : le nouvel objet occupe sa place, tandis que des variables enregistrées peuvent toujours faire référence à l’ancien.

Supprimer un élément ou plusieurs éléments correspondants

element.remove() détache cet élément. parent.removeChild(child) est l’ancienne forme passant par le parent et renvoie le nœud supprimé. Si une variable contient toujours le nœud, le script peut le lire ou l’insérer à nouveau plus tard.

Pour supprimer les tâches terminées, sélectionne une collection statique et parcours-la avec une boucle :

document.querySelectorAll(".task.done")
  .forEach(task => task.remove());

Avec cinq tâches, dont deux marquées comme terminées, il en reste trois. Supprimer un élément ne modifie pas les références contenues dans la NodeList statique : la boucle passe donc par les deux tâches sélectionnées.

Ne pas parcourir dans l’ordre croissant une liste dynamique qui rétrécit

list.children est dynamique. Avec six enfants, une boucle qui parcourt les indices dans l’ordre croissant et supprime items[i] n’en supprime que trois. Après la première suppression, le deuxième élément passe à l’indice 0, mais i avance à 1. L’enfant d’origine suivant est ignoré et le même décalage se répète.

Prends un instantané avant de supprimer tous les enfants actuels :

Array.from(list.children).forEach(item => item.remove());

Pour simplement vider un conteneur, list.replaceChildren() est plus clair. Définir list.textContent = "" ou list.innerHTML = "" le vide aussi. Une chaîne vide ne conduit à analyser aucun contenu extérieur.

Remplacer un seul nœud ou tous les enfants

old.replaceWith(newElement) place un nouveau nœud à l’endroit où se trouvait l’ancien. Pour <p id="status">Loading…</p>, document.querySelector("#status").replaceWith(list) remplace le message par la liste. parent.replaceChildren(a, b, c) remplace tous les enfants du parent en une seule opération tout en conservant le parent lui-même.

Cette différence compte pour les références enregistrées. Une variable contenant le parent reste valide après replaceChildren(), mais les références aux enfants supprimés pointent désormais vers des objets détachés. Remplacer un conteneur avec replaceWith() détache également ce conteneur.

Copier l’élément avec ou sans ses descendants

element.cloneNode(true) crée une copie profonde, incluant les descendants et les attributs. cloneNode() ou cloneNode(false) copie l’élément et ses attributs sans ses enfants. Un élément de liste cloné sans descendants ne contient aucun texte de l’élément d’origine.

Un clone est initialement détaché et doit être inséré. Il hérite aussi de l’identifiant de l’original. Donne-lui un nouvel identifiant ou supprime cet attribut avant de le placer sur la même page, afin que la sélection par identifiant reste fiable.

Gérer les éléments facultatifs

Si une recherche peut échouer, n’appelle pas immédiatement une méthode sur son résultat. document.querySelector("#promo").remove() déclenche une erreur lorsqu’aucune promotion n’existe. document.querySelector("#promo")?.remove() ne fait rien dans ce cas, sans déclencher d’erreur. Pour un conteneur obligatoire, un résultat absent est un signal utile pour vérifier le sélecteur et le moment d’exécution du script avant de tenter une modification de structure.

Points clés

  • remove() détache un nœud ; une référence enregistrée permet toujours de l’utiliser ou de le réinsérer.
  • Utilise une liste statique pour supprimer plusieurs éléments sélectionnés.
  • replaceChildren() conserve le conteneur et remplace ou supprime ses enfants.
  • replaceWith() remplace le nœud sélectionné lui-même.
  • cloneNode(true) copie les descendants ; un clone superficiel les omet.
  • Le clonage copie les identifiants : modifie ou supprime un identifiant copié avant l’insertion.
6

Transforme des données en page

Les tableaux décrivent ce qu’une page doit afficher ; le rendu transforme ces descriptions en éléments. Commence par un élément, étends le schéma aux listes et aux tableaux, puis organise le balisage répété avec des fragments ou des éléments template. Une fonction de rendu rend les mises à jour prévisibles lorsque les données changent. Distingue le tableau d’origine, la vue sélectionnée et les éléments affichés pour que le filtrage, le tri, les résultats vides et les récapitulatifs restent cohérents.

6.1 Affiche les éléments d’un tableau sous forme d’entrées de liste et de lignes de tableau

Le rendu consiste à transformer des données en une structure DOM visible. Garde le tableau de données comme source et construis un élément pour chaque objet. Place les valeurs des données dans textContent afin qu’elles restent du texte même si elles contiennent des chevrons.

Construire un élément pour chaque objet

Utilise ces objets représentant des livres :

const books = [
  { id: 1, title: "Dune", pages: 412 },
  { id: 2, title: "Emma", pages: 474 },
  { id: 3, title: "Beloved", pages: 324 }
];
function createBookItem(book) {
  const li = document.createElement("li");
  li.dataset.id = String(book.id);
  li.textContent = `${book.title} (${book.pages} pages)`;
  return li;
}
const list = document.querySelector("#books");
list.append(...books.map(createBookItem));

map() appelle la fonction de construction une fois par livre et produit trois éléments distincts. La décomposition transmet ces éléments comme arguments séparés à append(). L’affichage indique « Dune (412 pages) », « Emma (474 pages) » et « Beloved (324 pages) ». La somme des nombres de pages est de 1 210.

Sans décomposition, list.append(books.map(createBookItem)) reçoit un seul tableau. La méthode le convertit en texte contenant des chaînes telles que « [object HTMLLIElement] » au lieu d’insérer les éléments de liste.

L’identifiant stocké relie l’élément affiché aux données. Lis Number(li.dataset.id) avant de le comparer aux identifiants numériques des livres, puis utilise books.find(book => book.id === id).

Gérer les données manquantes et vides

Si un champ facultatif indiquant l’auteur est absent, son interpolation directe affiche « undefined ». Utilise book.author ?? "Unknown author" comme solution de repli lorsque le champ vaut null ou undefined. La coalescence des nuls laisse les autres valeurs inchangées, y compris 0 et une chaîne vide.

Si le tableau est vide, affiche un message tel que « Aucun livre pour le moment ». Un résultat vide doit indiquer à l’utilisateur qu’il n’y a actuellement aucun élément. Lors d’un nouvel affichage, remplace l’ancien pour qu’un message ou des éléments précédents ne restent pas à côté du nouveau résultat.

Comprendre l’approche par chaîne HTML

Un tableau fiable peut être transformé en chaînes HTML, puis celles-ci peuvent être réunies avec join("") avant l’affectation à innerHTML. La réunion supprime les virgules que la conversion du tableau en chaîne insérerait autrement. Cette approche analyse chaque valeur interpolée comme du HTML. Utilise l’approche qui construit des éléments lorsque les valeurs peuvent provenir de sources extérieures.

Construire une structure de tableau valide

Pour des données tabulaires, construis un <tr> par objet et un <td> pour chaque champ affiché. Ajoute les lignes au <tbody> du tableau. Pour des relevés à Oslo de 4,25 °C et au Caire de 28,5 °C, la cellule de température peut utiliser reading.temp.toFixed(1) : cette méthode affiche « 4.3 » et « 28.5 ». toFixed() renvoie une chaîne avec le nombre de décimales demandé. toLocaleString() met quant à lui en forme selon les paramètres régionaux de l’utilisateur, qui peuvent utiliser une virgule décimale. Réserve la mise en forme à l’étape d’affichage pour que les données numériques restent disponibles pour les calculs.

Construire les deux cellules avant d’insérer la ligne

Pour un corps de tableau vide existant nommé tbody, ce code affiche les relevés :

const readings = [{ city: "Oslo", temp: 4.25 }, { city: "Cairo", temp: 28.5 }];
const rows = readings.map(reading => {
  const row = document.createElement("tr");
  const city = document.createElement("td");
  const temperature = document.createElement("td");
  city.textContent = reading.city;
  temperature.textContent = reading.temp.toFixed(1) + " °C";
  row.append(city, temperature);
  return row;
});
tbody.replaceChildren(...rows);

Chaque passage crée une nouvelle ligne et deux nouvelles cellules. Remplir les deux cellules avant d’ajouter la ligne rend l’ordre des champs explicite. La décomposition de rows fournit séparément les deux nœuds de ligne ; le remplacement final supprime aussi les lignes précédentes.

Points clés

  • Construis un élément distinct pour chaque objet de données et remplis les valeurs avec textContent.
  • Décompose un tableau de nœuds lorsque tu les passes à append().
  • Utilise des attributs de données pour relier les éléments affichés aux objets.
  • Prévois des messages pour les états vides et des valeurs de repli pour les valeurs nulles ou undefined.
  • Place les lignes du tableau dans tbody et les champs dans les cellules.
  • toFixed() renvoie du texte destiné à l’affichage ; conserve les données numériques pour les calculs.

6.2 Assemble le contenu répété avant l’insertion

Lorsqu’une liste contient de nombreux éléments, construis le nouveau contenu hors de la page et insère-le en une fois. Un DocumentFragment regroupe des nœuds sans ajouter d’élément conteneur. Un élément template permet d’écrire une structure répétée en HTML et d’en remplir une nouvelle copie pour chaque objet.

Regrouper des nœuds dans un fragment
const fragment = document.createDocumentFragment();
for (const book of books) {
  fragment.append(createBookItem(book));
}
list.append(fragment);

Le fragment se trouve initialement hors du document. Chaque nouvel élément devient son enfant. Ajouter le fragment déplace ses enfants dans la liste dans leur ordre actuel ; le fragment lui-même n’est pas inséré comme conteneur. Après le transfert de 100 éléments dans une liste vide, la liste a 100 enfants et le fragment en a 0.

Ce schéma regroupe l’insertion et organise le code de construction. Il ne garantit pas de gain de vitesse particulier. Un tableau de nœuds construits convient aussi : list.append(...items) les ajoute, tandis que list.replaceChildren(...items) remplace le contenu actuel par ces nœuds.

Définir du balisage répété dans un élément template
<template id="book-row">
  <li class="book"><span class="title"></span>
    (<span class="pages"></span> pages)</li>
</template>

Le navigateur analyse ce balisage sans l’afficher. Le contenu se trouve dans un DocumentFragment distinct, accessible par template.content. Une recherche au niveau du document ne recherche pas dans ce fragment. Sélectionne l’élément template, clone son contenu, puis recherche dans le clone :

const template = document.querySelector("#book-row");
const clone = template.content.cloneNode(true);
clone.querySelector(".title").textContent = book.title;
clone.querySelector(".pages").textContent = book.pages;
const item = clone.firstElementChild;
list.append(clone);

Le titre et le nombre de pages sont remplis avant l’insertion. item enregistre une référence au nouveau <li>. Après l’ajout, clone est vide parce que ses enfants ont été déplacés, mais item fait toujours référence à l’élément inséré.

Préserver la source réutilisable

Ajoute une copie à chaque fois. Appeler list.append(template.content) déplace les nœuds sources hors de l’élément template. Une recherche ultérieure dans template.content renvoie alors null, et la tentative suivante de remplir le titre manquant déclenche une erreur. L’élément template source doit rester disponible pour les livres suivants.

Pour de nombreuses copies, remplis chaque fragment cloné, ajoute ces copies à un fragment de regroupement, puis insère l’ensemble. Un fragment peut recevoir les enfants d’un autre fragment, tout comme une liste.

Choisir une méthode de construction lisible

createElement() convient à une petite structure ou à une structure qui varie considérablement selon l’élément. Un élément template convient à un balisage répété plus volumineux, plus facile à modifier sous forme de HTML. Dans les deux cas, insère les valeurs extérieures comme du texte. Une chaîne HTML convient au balisage fiable, mais l’interpolation dans cette chaîne déclenche tout de même une analyse HTML. Choisis la méthode de construction selon la structure que tu dois maintenir, en conservant l’ordre : créer ou cloner, remplir, puis insérer.

Regrouper les copies remplies pour un seul remplacement

Avec l’élément template de livre ci-dessus et un tableau books existant :

const group = document.createDocumentFragment();
for (const book of books) {
  const copy = template.content.cloneNode(true);
  copy.querySelector(".title").textContent = book.title;
  copy.querySelector(".pages").textContent = book.pages;
  group.append(copy);
}
list.replaceChildren(group);

Chaque copie remplie transfère son élément dans group. La dernière ligne remplace le contenu de la liste par ces éléments et vide group. L’élément template d’origine reste intact pendant toute l’opération : la fonction peut donc répéter la construction pour un tableau ultérieur.

Points clés

  • Ajouter un fragment déplace ses enfants et laisse le fragment vide.
  • Un fragment regroupe des nœuds sans créer de conteneur dans la page.
  • Le contenu d’un élément template est analysé mais se trouve hors de l’arbre du document affiché.
  • Clone template.content pour chaque élément, puis remplis la copie avant l’insertion.
  • Enregistre la référence à l’élément avant que le fragment qui le contient soit vidé.

6.3 Maintiens les vues affichées synchronisées avec les données

Utilise les données comme unique source de vérité. Une fonction de rendu construit un affichage à partir du tableau actuel. Appelle-la après avoir modifié le tableau ou un objet qu’il contient.

Remplacer l’affichage à chaque rendu

Supposons que tasks contienne quatre objets, dont exactement un est terminé, et que la tâche 2 existe et ne soit pas terminée. Une fonction de rendu peut construire de nouveaux éléments et un récapitulatif :

function render() {
  const items = tasks.map(task => {
    const li = document.createElement("li");
    li.dataset.id = String(task.id);
    li.textContent = task.text;
    li.classList.toggle("done", task.done);
    return li;
  });
  list.replaceChildren(...items);
  const doneCount = tasks.filter(task => task.done).length;
  summary.textContent = `${doneCount} of ${tasks.length} done`;
}

Après tasks.push({ id: 5, text: "Book dentist", done: false }); render();, la liste contient cinq éléments et le récapitulatif indique « 1 of 5 done ». L’exécution de tasks.find(task => task.id === 2).done = true; render(); le remplace par « 2 of 5 done ».

Le remplacement des enfants est essentiel ici. Si la fonction se contentait d’ajouter tous les éléments, l’appeler deux fois dupliquerait l’affichage. Supprimer uniquement un élément DOM est aussi temporaire : si son objet reste dans le tableau, le rendu le fait réapparaître. Avec tasks déclaré au moyen de let, supprime-le des données avec tasks = tasks.filter(task => task.id !== id) et effectue à nouveau le rendu.

Construire une vue sans perdre la source

Pour une fonction de rendu qui accepte un tableau représentant une vue, passe tasks.filter(task => !task.done) pour n’afficher que les tâches non terminées. Conserve le tableau complet pour les vues ultérieures et les décomptes portant sur toute la liste. Donne un sens clair aux récapitulatifs : le nombre de tâches visibles diffère du nombre total de tâches.

sort() modifie le tableau sur lequel la méthode est appelée. Trie une copie pour l’affichage avec [...tasks].sort(...), ou utilise tasks.toSorted(...) pour obtenir une copie triée. Fournis un comparateur : les valeurs numériques nécessitent (a, b) => a - b, et les titres peuvent utiliser (a, b) => a.title.localeCompare(b.title). Le tri par défaut compare les formes textuelles : [100, 25, 3].sort() conserve donc cet ordre ; le tri numérique donne [3, 25, 100].

Faire correspondre les identifiants et analyser correctement les données

Le dataset.id d’un élément affiché est une chaîne. Convertis-le avant une comparaison stricte avec des identifiants numériques, sinon find() peut renvoyer undefined même si l’objet recherché existe. Les données JSON sont différentes : JSON.parse() conserve les nombres et les booléens JSON dans leurs types respectifs. Les objets obtenus par analyse peuvent passer par la même fonction de rendu que les objets écrits directement dans le code.

Préserver l’état local si nécessaire

Une reconstruction complète crée de nouveaux éléments. Elle peut faire perdre le focus et le texte saisi dans les champs de la zone reconstruite. Pour une petite modification d’état qui doit préserver ces objets, mets les données à jour, puis modifie l’élément existant, par exemple avec li.classList.toggle("done", task.done). Les données doivent toujours enregistrer le changement pour qu’un rendu complet ultérieur corresponde à l’affichage actuel.

Fournir des entrées distinctes à la vue et au récapitulatif

Une vue filtrée peut tout de même afficher un récapitulatif de toutes les tâches :

function renderOpenTasks() {
  const visible = tasks.filter(task => !task.done);
  const nodes = visible.map(task => {
    const li = document.createElement("li");
    li.textContent = task.text;
    return li;
  });
  if (visible.length === 0) {
    const empty = document.createElement("li");
    empty.textContent = "No open tasks";
    nodes.push(empty);
  }
  list.replaceChildren(...nodes);
  const done = tasks.filter(task => task.done).length;
  summary.textContent = `${done} of ${tasks.length} done`;
}

Un tableau dont toutes les tâches sont terminées affiche le message indiquant que cette vue est vide, mais conserve chaque objet pour le total. Compter à partir de visible répondrait à une autre question et pourrait indiquer qu’aucune tâche n’est terminée simplement parce que cette vue les exclut.

Points clés

  • Mets les données à jour, puis construis la page à partir de ces données.
  • Remplace les anciens enfants lorsque tu reconstruis une liste pour éviter les doublons.
  • Filtre et trie une vue dérivée tout en conservant le tableau d’origine si nécessaire.
  • Fournis un comparateur pour le tri numérique et convertis les identifiants de dataset avant une comparaison numérique.
  • JSON.parse() préserve les types de données numériques et booléens.
  • Utilise une mise à jour ciblée d’un élément lorsque la reconstruction ferait perdre le focus ou l’état de saisie nécessaire.

DOM en JavaScript : exemples

6 Leçons Interactives

1

Repère-toi dans l’arbre d’une page

11 étapes
Inspecte une petite liste, distingue les éléments du texte et suis des chemins fiables vers le contenu voisin.
  1. 1
    IntroductionCommence par une page que tu peux inspecter

    Le navigateur construit des objets à partir du HTML. JavaScript utilise cet arbre DOM.

    Suis une liste de deux éléments, du balisage aux nœuds, puis utilise les relations familiales pour atteindre un élément voisin. Garde les outils de développement ouverts pour comparer la page visible à son arbre.

  2. 2
    ExplicationEntre par document

    Le DOM est le modèle dynamique de la page dans le navigateur. document y donne accès ; document.body fait référence à l’élément body.

    Le navigateur fournit cette API. JavaScript l’appelle pour modifier la page actuelle sans la recharger ni réécrire le fichier HTML du serveur.

  3. 3
    ExempleObserve séparément l’élément et son texte

    Observe <li>Buy milk</li>. Le <li> devient un nœud élément et « Buy milk » devient un nœud texte enfant à l’intérieur.

    Lis nodeType pour les distinguer : l’élément est de type 1 et son enfant texte est de type 3. Les commentaires sont de type 8 et le document lui-même est de type 9. « Nœud » désigne le groupe le plus large ; un élément est un type de nœud.

  4. 4
    ExempleCompte ce qu’ajoute l’indentation

    Utilise cette disposition exacte :

    <ul id="tasks">
      <li>Buy milk</li>
      <li>Call Sam</li>
    </ul>
    

    La liste a deux éléments enfants. Elle a aussi trois nœuds texte contenant des caractères d’espacement : avant, entre et après ces éléments. Son children.length vaut donc 2, tandis que childNodes.length vaut 5. Les nœuds supplémentaires proviennent des caractères entre les balises.

  5. 5
    DéfiDétermine quel est le premier nœud

    Dans la liste indentée de la diapositive précédente, quel type de nœud est tasks.firstChild et pourquoi diffère-t-il de tasks.firstElementChild ?

    ---reveal---

    firstChild est le nœud texte contenant des caractères d’espacement avant le premier élément. firstElementChild ignore ce nœud et renvoie le premier <li>. L’indentation affecte la suite des nœuds même si elle ne crée pas de tâche visible supplémentaire.

  6. 6
    ConseilInspecte l’arbre actuel

    Choisis « Inspecter » sur le premier élément de liste. Le panneau Éléments montre le DOM actuel. Une fois l’élément sélectionné, $0 dans la console y fait référence et console.dir($0) expose ses propriétés.

    L’arbre peut contenir des éléments ajoutés par l’analyseur, comme un <tbody> autour des lignes d’un tableau. Utilise ce panneau pour vérifier l’imbrication réelle au lieu de supposer qu’elle correspond à chaque limite de balise dans le code source.

  7. 7
    ExemplePasse à l’élément suivant

    Enregistre la liste sous le nom tasks, puis suis une relation entre éléments :

    const first = tasks.firstElementChild;
    const second = first.nextElementSibling;
    

    second.textContent vaut « Call Sam ». Lire first.nextSibling atteint à la place le nœud contenant les caractères d’espacement entre les éléments. Choisis la forme pour les éléments lorsque tu veux passer d’un élément de page à l’autre en ignorant les nœuds texte.

  8. 8
    ExplicationArrête-toi sans erreur au dernier élément

    Le nextElementSibling du dernier élément vaut null. Lire une propriété directement à partir de cette référence absente déclenche une TypeError.

    second.nextElementSibling?.textContent s’arrête là et donne undefined, sans ajouter de nœud ni fournir de chaîne vide.

  9. 9
    LienTrouve l’élément englobant selon son rôle

    Un span imbriqué peut trouver la tâche qui l’englobe avec span.closest("li"). La recherche commence par le span lui-même, puis vérifie les ancêtres successifs jusqu’à trouver une correspondance.

    span.matches("li") teste uniquement le span et renvoie faux dans ce cas. Une recherche parmi les ancêtres est utile lorsqu’un conteneur supplémentaire pourrait conduire un nombre fixe de passages par les parents au mauvais endroit.

  10. 10
    DéfiNavigue malgré l’ajout d’un conteneur

    Chaque élément de liste contient maintenant son texte dans un span. En partant du premier span, comment lire le texte de l’élément suivant sans dépendre des nœuds contenant des caractères d’espacement ni du nombre de conteneurs dans un élément de liste ?

    ---reveal---

    Trouve l’élément englobant, puis son frère suivant qui soit un élément : span.closest("li").nextElementSibling?.textContent. L’élément englobant est trouvé par sa balise, et la navigation entre éléments frères ignore les caractères d’espacement entre les éléments de liste.

  11. 11
    RécapitulatifEssaie ensuite avec un tableau

    Inspecte un tableau dont le code source place une ligne directement dans <table>. Trouve le parent réel de la ligne.

    Compare son nombre de nœuds enfants à son nombre d’éléments enfants, en utilisant le panneau Éléments pour expliquer la structure ajoutée par l’analyseur et les caractères d’espacement.

2

Sélectionne et mets à jour les éléments voulus

12 étapes
Choisis la portée d’une recherche, vérifie les résultats absents et évite les surprises liées aux boucles sur les collections dynamiques.

Enregistre cette unité pour suivre chaque Leçon Interactive pas à pas.

  1. 1
    IntroductionChoisis une recherche avant de modifier une page
  2. 2
    ExplicationUtilise la syntaxe d’identifiant adaptée à la méthode
  3. 3
    ExempleLimite la recherche d’une classe répétée à sa carte
  4. 4
    ConseilDistingue un nœud absent d’une syntaxe incorrecte
  5. 5
    DéfiExplique un résultat null obtenu trop tôt
  6. 6
    ExempleParcours les éléments renvoyés
  7. 7
    ExplicationConvertis la collection lorsque tu as besoin de méthodes de tableau
  8. 8
    ExempleCompare deux collections enregistrées
  9. 9
    Point cléObserve une collection dynamique qui rétrécit
  10. 10
    DéfiChoisis le bon sélecteur combiné
  11. 11
    DéfiCombine une recherche limitée avec une boucle sûre
  12. 12
    RécapitulatifDiagnostique ton prochain échec de recherche
3

Mets un profil à jour et lis les valeurs de son formulaire

15 étapes
Choisis entre texte brut, propriétés d’élément, attributs et entrées de dataset selon le type d’information.

Enregistre cette unité pour suivre chaque Leçon Interactive pas à pas.

  1. 1
    IntroductionDistingue les informations contenues dans un élément
  2. 2
    ExempleLis le texte sans ses balises
  3. 3
    ExplicationTraite les valeurs extérieures comme des caractères
  4. 4
    DéfiPréserve un champ existant
  5. 5
    LienLis le texte affiché lorsque c’est nécessaire
  6. 6
    ExempleLis une URL telle qu’elle est écrite ou son URL résolue
  7. 7
    ExplicationDéfinis un booléen par sa présence
  8. 8
    DéfiRépare un composant désactivé
  9. 9
    ExempleTransforme un nom de donnée en nom de propriété
  10. 10
    ExplicationLis le contenu actuel d’un champ
  11. 11
    DéfiCalcule avec la valeur d’un champ
  12. 12
    ExempleTrouve un objet à l’aide d’un identifiant affiché
  13. 13
    ConseilDonne un nom lisible à un bouton à icône
  14. 14
    DéfiRelie la recherche de données à un affichage sûr
  15. 15
    RécapitulatifInspecte un champ avant et après modification
4

Fais suivre à l’apparence un état clair

13 étapes
Fais basculer des classes, calcule des styles de progression et synchronise un panneau avec son état déployé accessible.

Enregistre cette unité pour suivre chaque Leçon Interactive pas à pas.

  1. 1
    IntroductionLaisse les données déterminer l’état visible
  2. 2
    ExempleConserve une classe de base en ajoutant un état
  3. 3
    ExplicationUtilise une condition pour les mises à jour répétées
  4. 4
    DéfiPrévois le résultat de deux mises à jour répétées
  5. 5
    ExempleCalcule un pourcentage CSS
  6. 6
    ExplicationLis le résultat de la cascade
  7. 7
    DéfiRétablis la couleur de la feuille de style
  8. 8
    ExplicationChoisis ce que la fermeture d’un panneau supprime
  9. 9
    ExempleSynchronise un panneau et son bouton
  10. 10
    ConseilVérifie un style qui prend le dessus sur hidden
  11. 11
    DéfiDiagnostique un composant invisible mais actif
  12. 12
    DéfiCombine des classes avec une valeur calculée
  13. 13
    RécapitulatifVérifie séparément l’état et l’apparence
5

Construis des éléments et suis leurs références d’objet

12 étapes
Crée et insère du nouveau contenu, déplace un élément existant, puis supprime et clone des éléments sans perdre de vue leur identité.

Enregistre cette unité pour suivre chaque Leçon Interactive pas à pas.

  1. 1
    IntroductionConstruis un élément de tâche en plusieurs étapes
  2. 2
    ExempleCrée un élément détaché
  3. 3
    ExempleInsère l’élément terminé
  4. 4
    ExplicationChoisis entre enfants et frères
  5. 5
    ExempleDéplace un nœud existant
  6. 6
    DéfiExplique pourquoi une boucle ne produit qu’un élément
  7. 7
    ExplicationDétache un élément sans détruire sa référence
  8. 8
    ExempleRemplace un élément ou tout un affichage
  9. 9
    ConseilCopie les descendants et vérifie les identifiants
  10. 10
    DéfiPrévois le contenu d’une copie superficielle
  11. 11
    DéfiDéplace l’original et insère une copie
  12. 12
    RécapitulatifSuis les identités en parallèle du balisage
6

Affiche une liste à partir de données et mets-la à jour de façon fiable

17 étapes
Construis des éléments répétés, utilise un élément template en toute sécurité et maintiens les vues filtrées et les récapitulatifs cohérents avec les données.

Enregistre cette unité pour suivre chaque Leçon Interactive pas à pas.

  1. 1
    IntroductionLaisse le tableau de données déterminer l’affichage
  2. 2
    ExempleÉcris une fonction de construction pour un livre
  3. 3
    ExempleDécompose le tableau en arguments de type nœud
  4. 4
    ConseilRends les données manquantes lisibles
  5. 5
    LienApplique le schéma aux lignes d’un tableau
  6. 6
    DéfiTrouve pourquoi la liste affiche du texte représentant des objets
  7. 7
    ExempleRegroupe des nœuds hors de la page
  8. 8
    ExplicationConserve la structure répétée en HTML
  9. 9
    ExempleRemplis le clone avant de le transférer
  10. 10
    DéfiPréserve l’élément template réutilisable
  11. 11
    ExplicationRemplace l’affichage à partir des données actuelles
  12. 12
    ExempleMets à jour un objet et son récapitulatif
  13. 13
    ExplicationConserve une vue triée séparément
  14. 14
    DéfiExplique pourquoi un élément revient après sa suppression
  15. 15
    Point cléPréserve l’état local de saisie
  16. 16
    DéfiCombine une recherche avec une mise à jour ciblée
  17. 17
    RécapitulatifVérifie le rendu pour trois états

DOM en JavaScript : QCM

50 Questions Pratiques en 5 séries

Série 1 : Lis et modifie une page10 Questions Pratiques

Question 1 sur 10

Un script remplace « Draft » par « Ready » dans un paragraphe. Qu’affiche « Afficher le code source de la page » pour ce paragraphe après la modification ?
  1. Le texte DOM mis à jour : « Ready ».
  2. Le texte HTML d’origine : « Draft ».
  3. Les deux textes dans des nœuds texte voisins.
  4. Un paragraphe vide après la modification.
Afficher la réponseMasquer la réponse
Réponse : B
« Afficher le code source de la page » montre toujours « Draft », car cette commande lit le HTML d’origine. Le panneau Éléments montre le texte DOM modifié « Ready » ; une modification par un script ne réécrit pas le fichier HTML sur le serveur.

Question 2 sur 10

Pour <ul><li>A</li> <li>B</li></ul>, une variable first contient le premier élément de liste. Que renvoie first.nextSibling.nodeType ?
  1. 1
  2. 8
  3. 9
  4. 3
Afficher la réponseMasquer la réponse
Réponse : D
L’espace littéral entre les deux éléments de liste devient un nœud texte : le frère suivant a donc un nodeType de 3. Le second élément de liste est un élément dont le nodeType vaut 1, mais on l’atteint avec nextElementSibling. La navigation entre nœuds inclut le texte entre les balises ; la navigation entre éléments l’ignore.

Question 3 sur 10

Comment un script peut-il sélectionner l’élément <section id="report"> avec getElementById() ?
  1. document.getElementById("report")
  2. document.getElementById("#report")
  3. document.getElementById("section#report")
  4. document.getElementById("[id=report]")
Afficher la réponseMasquer la réponse
Réponse : A
Passe l’identifiant seul « report » à getElementById(). Le dièse appartient à la syntaxe des sélecteurs CSS ; passer « #report » ici recherche un identifiant contenant ce caractère et ne trouve pas cette section.

Question 4 sur 10

Cinq éléments, dans l’ordre de A à E, possèdent tous la classe flag. Le code enregistre const live = box.getElementsByClassName("flag"), puis exécute for (let i = 0; i < live.length; i++) { live[i].classList.remove("flag"); }. Quels éléments conservent la classe ?
  1. C et E.
  2. B, C et D.
  3. B et D.
  4. A, C et E.
Afficher la réponseMasquer la réponse
Réponse : C
Retirer la classe de A décale B à l’indice 0, mais la boucle avance à l’indice 1 et retire la classe de C. Elle la retire ensuite à E, à l’indice 2, avant que la longueur réduite arrête la boucle : B et D la conservent. Traiter la collection comme un instantané fixe conduirait à prévoir à tort que tous les éléments perdent leur classe.

Question 5 sur 10

Que s’affiche-t-il après label.textContent = "<em>Saved</em>" ?
  1. Le mot « Saved » dans un élément em.
  2. Un élément em sans texte à l’intérieur.
  3. Le texte littéral « Saved ».
  4. Le texte littéral « Saved » sans balises.
Afficher la réponseMasquer la réponse
Réponse : C
textContent insère les caractères littéraux « Saved ». Cette propriété n’analyse pas ces balises pour créer un élément d’emphase ; utilise la création d’éléments ou l’analyse de HTML fiable lorsque tu veux créer une structure.

Question 6 sur 10

Un bouton est désactivé. Le code exécute button.setAttribute("disabled", "false"). Quel état button.disabled indique-t-il ?
  1. false
  2. true
  3. "false"
  4. null
Afficher la réponseMasquer la réponse
Réponse : B
L’attribut disabled reste présent, donc button.disabled est vrai. Son texte « false » ne peut pas désactiver un attribut booléen ; supprime l’attribut ou définis la propriété booléenne à faux pour activer le bouton.

Question 7 sur 10

Un champ input contient actuellement « 6 ». Que produit input.value + 2 ?
  1. "62"
  2. 8
  3. "8"
  4. 62
Afficher la réponseMasquer la réponse
Réponse : A
La valeur du champ est la chaîne « 6 » : + 2 la concatène donc pour donner « 62 ». Convertis-la avant l’addition avec Number(input.value) + 2 pour obtenir le nombre 8, y compris lorsque le champ est de type numérique.

Question 8 sur 10

Une carte possède initialement class="card compact". Comment le code peut-il ajouter « selected » tout en conservant les deux classes existantes ?
  1. card.className = "selected"
  2. card.classList.add(".selected")
  3. card.setAttribute("class", "selected")
  4. card.classList.add("selected")
Afficher la réponseMasquer la réponse
Réponse : D
classList.add("selected") conserve « card » et « compact ». Affecter une valeur à toute la chaîne des classes les remplace, tandis qu’un point initial devient une partie du nom ajouté au lieu d’être une syntaxe de sélecteur.

Question 9 sur 10

Une liste contient des éléments nommés P, Q, R. Quel est leur ordre après list.append(list.firstElementChild) ?
  1. P, Q, R, P.
  2. Q, R, P.
  3. R, P, Q.
  4. P, R, Q.
Afficher la réponseMasquer la réponse
Réponse : B
Ajouter le premier enfant existant déplace P à la fin, ce qui donne Q, R, P. Le même nœud ne peut pas occuper à la fois l’ancienne et la nouvelle position : la liste contient donc toujours trois éléments. Un quatrième élément P nécessiterait un nœud distinct, par exemple un clone, plutôt qu’une nouvelle insertion du même objet.

Question 10 sur 10

makeItem() renvoie un nouveau <li>. Qu’insère list.append(records.map(makeItem)) lorsque records contient deux entrées ?
  1. Deux éléments li avec leur contenu construit.
  2. Un élément li contenant les deux éléments construits.
  3. Du texte issu des deux objets éléments.
  4. Deux copies des enregistrements en texte JSON.
Afficher la réponseMasquer la réponse
Réponse : C
map() renvoie un tableau et append() reçoit ce tableau comme un seul argument. La méthode le convertit en texte contenant les représentations textuelles des éléments au lieu d’insérer les nœuds. Utilise list.append(...records.map(makeItem)) pour passer chaque élément comme argument distinct.
Série 2 : Choisis la bonne opération DOM10 Questions Pratiques

Enregistre cette unité pour voir chaque réponse et t'entraîner sur chaque série.

Question 1 sur 10

Le HTML contient <table><tr><td>8</td></tr></table>. Quel élément enfant direct l’analyseur place-t-il normalement dans le tableau ?
  1. Le tr exactement tel qu’il est écrit.
  2. Le td sorti de la ligne.
  3. Un tbody contenant la ligne.
  4. Un div entourant les cellules du tableau.
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 2 sur 10

Un script externe classique dans <head> sélectionne un pied de page écrit plus loin dans <body> et obtient null. Le sélecteur est correct. Quel attribut de script permet de l’exécuter après l’analyse du HTML ?
  1. defer
  2. async
  3. disabled
  4. hidden
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 3 sur 10

Une NodeList statique contient deux éléments .note. L’un perd sa classe note et un nouvel élément note est ajouté. Quelle est la longueur de la NodeList enregistrée ?
  1. 1
  2. 2
  3. 3
  4. 0
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 4 sur 10

Un élément possède data-record-id="38". Comment le code peut-il comparer cet identifiant au nombre 38 avec l’égalité stricte ?
  1. row.dataset.recordId === 38
  2. Number(row.getAttribute("record-id")) === 38
  3. row.dataset["record-id"] === 38
  4. Number(row.dataset.recordId) === 38
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 5 sur 10

Une feuille de style définit la couleur d’un titre et ce titre n’a pas de couleur définie en ligne. Comment le code peut-il lire la couleur appliquée ?
  1. heading.style.color
  2. getComputedStyle(heading).color
  3. heading.getAttribute("color")
  4. heading.dataset.color
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 6 sur 10

Un panneau fermé doit conserver son espace dans la mise en page et être masqué aux lecteurs d’écran. Quelle déclaration CSS convient ?
  1. visibility: hidden
  2. display: none
  3. opacity: 0
  4. visibility: visible
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 7 sur 10

Un conteneur contient les éléments A et B. Le code enregistre son premier élément sous le nom a, appelle container.replaceChildren(), définit a.textContent = "C", puis exécute container.append(a) et container.append(a.cloneNode(true)). Que contient le conteneur ?
  1. Un élément affichant « C ».
  2. Deux éléments affichant « A » et « C ».
  3. Deux éléments affichant tous deux « C ».
  4. Trois éléments affichant « A », « B » et « C ».
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 8 sur 10

Un enregistrement possède score: 0. Qu’affiche record.score ?? "Pending" lorsqu’il est affecté à textContent ?
  1. « Pending »
  2. « undefined »
  3. Une chaîne vide.
  4. « 0 »
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 9 sur 10

Une liste vide reçoit un fragment contenant trois éléments. Le code définit ensuite le textContent du fragment à « Reset » et ajoute à nouveau le même fragment. Que contient la liste ?
  1. Les trois éléments d’origine, puis le texte « Reset ».
  2. Seulement le texte « Reset », qui remplace les trois éléments.
  3. Six éléments, suivis du texte « Reset ».
  4. Les trois éléments dont chaque libellé vaut « Reset ».
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 10 sur 10

Les données sont [{n: 14}, {n: 3}, {n: 9}]. Une vue doit les afficher par ordre numérique croissant tout en préservant l’ordre de la source. Quelle expression construit cette vue ?
  1. data.sort((a, b) => a.n - b.n)
  2. [...data].sort((a, b) => a.n - b.n)
  3. [...data].sort((a, b) => b.n - a.n)
  4. [...data].sort((a, b) => String(a.n).localeCompare(String(b.n)))
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Série 3 : Suis les nœuds, l’état et les collections10 Questions Pratiques

Enregistre cette unité pour voir chaque réponse et t'entraîner sur chaque série.

Question 1 sur 10

Un bouton possède lui-même la classe entry et se trouve dans une section ayant la même classe. Que renvoie button.closest(".entry") ?
  1. La section englobante.
  2. Le parent de la section.
  3. Null ; les deux correspondent.
  4. Le bouton lui-même.
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 2 sur 10

Une boîte contient initialement quatre éléments .mark. Le code enregistre une collection dynamique fondée sur la classe et une NodeList statique des éléments correspondants. Il supprime le premier membre de la collection dynamique, puis retire la classe à son nouveau premier membre. Quelles sont les longueurs finales des collections dynamique et statique ?
  1. Dynamique : 2, statique : 3.
  2. Dynamique : 3, statique : 4.
  3. Dynamique : 2, statique : 4.
  4. Dynamique : 3, statique : 3.
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 3 sur 10

Un compteur affiche « 12 ». Quelle affectation lui fait afficher « 13 » ?
  1. counter.textContent = Number(counter.textContent) + 1
  2. counter.textContent = counter.textContent + 1
  3. counter.textContent = counter.textContent + "1"
  4. counter.textContent = Number(counter.textContent + 1)
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 4 sur 10

Sur https://example.com/catalog/, un lien est écrit <a href="/guide">Guide</a>. Que renvoie link.getAttribute("href") ?
  1. "https://example.com/guide"
  2. "/guide"
  3. "https://example.com/catalog/guide"
  4. "guide"
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 5 sur 10

Une ligne possède initialement class="row done". Le code exécute deux fois row.classList.toggle("done", false). Quelles classes restent présentes ?
  1. Seulement « row ».
  2. « row » et « done ».
  3. Seulement « done ».
  4. Aucune classe.
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 6 sur 10

Une boîte possède une largeur et une couleur définies en ligne. Comment le code peut-il supprimer uniquement la couleur en ligne pour que la feuille de style la détermine ?
  1. box.style.cssText = ""
  2. box.removeAttribute("style")
  3. box.style.removeProperty("color")
  4. box.style.color = "inherit"
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 7 sur 10

Une section contient déjà deux paragraphes. À quelle position insertAdjacentHTML() doit-il insérer une note fiable comme premier enfant de la section ?
  1. "beforebegin"
  2. "afterbegin"
  3. "beforeend"
  4. "afterend"
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 8 sur 10

Un élément dont l’identifiant est « entry » et qui contient un span imbriqué est cloné en profondeur. L’identifiant du clone devient « entry-copy », puis le clone est ajouté et l’original est supprimé. Vers quoi pointe une référence enregistrée au span d’origine ?
  1. Vers le span correspondant dans le clone ajouté.
  2. Vers le nouveau conteneur parent de l’élément ajouté.
  3. Vers null, car son élément d’origine a été supprimé.
  4. Vers le span dans l’élément d’origine détaché.
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 9 sur 10

Le code ajoute directement template.content à une liste. Pourquoi un appel ultérieur à template.content.querySelector(".title") renvoie-t-il null ?
  1. L’élément template est devenu une chaîne HTML.
  2. La classe a été supprimée lors de l’insertion.
  3. Le contenu source a été déplacé dans la liste.
  4. Le contenu template rejette les sélecteurs de classe.
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 10 sur 10

Les tâches sont [{id:31, done:true}, {id:32, done:false}, {id:33, done:false}]. Le code supprime uniquement la ligne 31 du DOM, marque la tâche 32 comme terminée dans le tableau, puis reconstruit entièrement toutes les lignes et le récapitulatif à partir de ce tableau. Qu’est-ce qui s’affiche ?
  1. Trois lignes ; « 2 of 3 done ».
  2. Deux lignes ; « 1 of 2 done ».
  3. Trois lignes ; « 1 of 3 done ».
  4. Deux lignes ; « 2 of 2 done ».
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Série 4 : Construis des affichages fiables à partir de données10 Questions Pratiques

Enregistre cette unité pour voir chaque réponse et t'entraîner sur chaque série.

Question 1 sur 10

Un paragraphe contient Hello, un élément imbriqué <strong>team</strong> et un commentaire HTML. Le texte de l’élément strong est-il un frère du commentaire ?
  1. Oui ; le paragraphe est son parent.
  2. Non ; son texte est un enfant de strong.
  3. Oui ; les commentaires sont frères de tout texte.
  4. Non ; ce texte est un attribut.
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 2 sur 10

Une page possède une barre latérale et une section principale, chacune contenant .status. Une variable main contient la section principale. Quelle recherche trouve son premier descendant status ?
  1. document.querySelector(".status")
  2. main.getElementById("status")
  3. main.querySelector(".status")
  4. document.getElementById(".status")
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 3 sur 10

Le code enregistre const field = box.querySelector("input"). Un utilisateur remplace « A » par « B » dans ce champ. Le script exécute box.innerHTML += "<span>Done</span>", puis field.value = "C". Qu’arrive-t-il au champ visible ?
  1. C’est un champ de remplacement ; la dernière affectation ne modifie que l’original détaché.
  2. C’est le champ d’origine et il affiche désormais la valeur finale « C ».
  3. C’est le champ de remplacement et la référence enregistrée pointe désormais vers lui.
  4. Il est définitivement supprimé, car innerHTML ne peut pas reconstruire les champs input.
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 4 sur 10

Un champ input possède initialement value="2". Après que l’utilisateur a remplacé cette valeur par 7, un script lit Number(input.getAttribute("value")) + 1. Quel nombre obtient-il ?
  1. 8
  2. 21
  3. 71
  4. 3
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 5 sur 10

Un panneau est masqué avec panel.hidden = true, mais CSS contient .panel { display: grid; } et le panneau reste visible. Son bouton indique aussi toujours aria-expanded="true". Quelle solution corrige les deux états pour un panneau fermé ?
  1. Conserver la règle display et définir aria-expanded à « false » sans modifier CSS.
  2. Définir l’opacité à zéro et laisser aria-expanded à sa valeur actuelle.
  3. Supprimer hidden et définir aria-expanded à « true » pour correspondre à la mise en page actuelle.
  4. Imposer [hidden] { display: none !important; } et définir aria-expanded à « false ».
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 6 sur 10

Une liste commence dans l’ordre A, B, C. Le code enregistre son premier élément sous le nom a, exécute list.lastElementChild.before(a), puis list.prepend(list.lastElementChild). Quel est l’ordre final ?
  1. B, A, C.
  2. C, B, A.
  3. C, A, B.
  4. A, C, B.
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 7 sur 10

Un enregistrement ne possède pas de propriété author. Quelle affectation affiche « Unknown author » sans analyser la valeur comme du HTML ?
  1. cell.textContent = record.author ?? "Unknown author"
  2. cell.textContent = String(record.author)
  3. cell.innerHTML = record.author ?? "Unknown author"
  4. cell.textContent = record.author === null ? "Unknown author" : record.author
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 8 sur 10

Une fonction de rendu clone un élément template contenant une ligne, ajoute le clone à un fragment, puis seulement ensuite essaie clone.querySelector(".name").textContent = record.name. Pourquoi cela échoue-t-il ?
  1. Un fragment ne peut pas contenir les enfants d’un autre fragment.
  2. Le clonage profond supprime les classes des champs clonés.
  3. L’ajout a vidé le clone avant que son champ soit rempli.
  4. Un champ template ne peut pas recevoir textContent avant l’affichage.
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 9 sur 10

Un tableau contient les identifiants 11, 12 et 13. Le code supprime uniquement le <li> de l’identifiant 12, puis affiche une vue filtrée à partir du tableau inchangé. Le filtre conserve les trois objets. Que faut-il changer pour que l’identifiant 12 reste supprimé après tout rendu complet ultérieur ?
  1. Retirer une deuxième fois l’identifiant 12 du DOM nouvellement affiché.
  2. Retirer l’identifiant 12 du tableau source avant le rendu.
  3. Conserver une NodeList statique qui exclut l’élément supprimé.
  4. Trier le tableau source avant de construire la vue suivante.
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 10 sur 10

Une chaîne JSON est [{"id":24,"done":false}]. Après JSON.parse(), comment les types de id et done se comparent-ils à celui de data-id="24" sur un élément ?
  1. L’id analysé est numérique ; done est booléen ; l’id de dataset est du texte.
  2. L’id analysé est du texte ; done est du texte ; l’id de dataset est numérique.
  3. L’id analysé est numérique ; done est du texte ; l’id de dataset est numérique.
  4. L’id analysé est du texte ; done est booléen ; l’id de dataset est du texte.
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Série 5 : Débogue les mises à jour dans le DOM10 Questions Pratiques

Enregistre cette unité pour voir chaque réponse et t'entraîner sur chaque série.

Question 1 sur 10

Un article contient <div class="card"><div class="body"><span class="label">A</span></div></div>. Depuis le libellé, le code utilise parentElement.parentElement pour trouver la carte. Un nouveau conteneur est inséré entre body et label. Quel remplacement reste fiable ?
  1. label.closest(".card")
  2. label.parentElement.parentElement
  3. label.querySelector(".card")
  4. label.nextElementSibling?.parentElement
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 2 sur 10

Une liste vide donne l’instantané snap = list.querySelectorAll(".new"). Deux éléments de classe new sont ajoutés, puis une boucle sur snap retire la classe new. Une nouvelle recherche par classe est enregistrée comme collection dynamique. Quelles sont les longueurs de snap et de la collection dynamique ?
  1. Instantané : 0, dynamique : 0.
  2. Instantané : 2, dynamique : 0.
  3. Instantané : 2, dynamique : 2.
  4. Instantané : 0, dynamique : 2.
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 3 sur 10

Un aperçu affiche un commentaire fourni par un utilisateur. Un développeur filtre d’abord les balises <script>. Quelle mise à jour conserve l’élément d’aperçu et insère le commentaire comme texte littéral sans analyse HTML ?
  1. preview.innerHTML = comment
  2. preview.textContent = comment
  3. preview.insertAdjacentHTML("beforeend", comment)
  4. preview.outerHTML = comment
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 4 sur 10

Comment le code peut-il associer un label au champ dont l’identifiant est « contact » à l’aide de la propriété DOM du label ?
  1. label.for = "contact"
  2. label.id = "contact"
  3. label.htmlFor = "contact"
  4. label.className = "contact"
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 5 sur 10

Une ligne possède initialement class="row selected". Les données indiquent que selected est faux. Le code exécute row.classList.toggle("selected"), puis plus tard row.classList.toggle("selected", false). Quelles sont les deux valeurs de retour et les classes finales ?
  1. false, false ; seule row reste.
  2. false, true ; row et selected restent.
  3. true, false ; seule row reste.
  4. true, true ; row et selected restent.
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 6 sur 10

Une barre de progression représente 7 enregistrements terminés sur 20. Quelle chaîne définit correctement sa largeur en pourcentage ?
  1. "0.35%"
  2. "35px"
  3. "35%"
  4. "7%"
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 7 sur 10

Un panneau est initialement masqué et son bouton indique aria-expanded « false ». Deux fois, le code enregistre const open = panel.hidden, définit panel.hidden = !open et écrit String(open) dans aria-expanded. Quels sont les états finaux ?
  1. Hidden false ; aria-expanded « true ».
  2. Hidden true ; aria-expanded « true ».
  3. Hidden false ; aria-expanded « false ».
  4. Hidden true ; aria-expanded « false ».
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 8 sur 10

Un élément <li id="copy-me"><span>Map</span></li> est copié avec cloneNode(false). Que contient le clone détaché ?
  1. Le li et le span, mais sans l’identifiant.
  2. Le li et son identifiant, sans span ni texte.
  3. Le li, l’identifiant, le span et le texte « Map ».
  4. Seulement un nœud texte contenant « Map ».
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 9 sur 10

Pour chacun de trois enregistrements, le code clone en profondeur un élément template contenant un élément de liste, remplit son titre et ajoute le clone à un fragment de regroupement. Il appelle ensuite list.replaceChildren(fragment). Quels objets restent remplis ?
  1. La liste et le fragment de regroupement ; l’élément template source est vide.
  2. Seulement l’élément template source ; la liste reçoit des fragments vides.
  3. La liste et l’élément template source ; le fragment de regroupement est vide.
  4. Les trois ; chacun conserve des copies des mêmes objets éléments.
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 10 sur 10

Les données contiennent {id: 5, done: false}. La ligne existante correspondante possède data-id="5" et un champ input ayant le focus. Le code doit marquer l’enregistrement comme terminé, refléter cet état par la classe et préserver l’objet du champ. Quelle séquence convient ?
  1. Convertir l’identifiant de dataset, mettre à jour l’objet correspondant, puis reconstruire toutes les lignes à partir des données.
  2. Comparer directement l’identifiant de dataset aux identifiants numériques, puis mettre à jour l’objet trouvé et la ligne.
  3. Forcer la classe done de la ligne existante, laisser l’objet inchangé, puis reconstruire toutes les lignes plus tard.
  4. Convertir l’identifiant de dataset, mettre à jour l’objet correspondant, puis forcer la classe done de la ligne existante.
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Tu bloques sur ton propre exercice ? Aide aux Devoirs

Mots-Clés

74 Mots-Clés, chacun avec sa définition

A

Analyse syntaxique
L’analyse syntaxique transforme le balisage HTML lu par le navigateur en arbre de document structuré.
Lorsqu’il analyse des lignes placées directement dans un tableau, le navigateur peut insérer un élément <tbody>.
Ancêtre
Un ancêtre est un parent ou un nœud englobant plus éloigné sur le chemin qui mène au document.
Une liste est un ancêtre du texte placé dans un span imbriqué dans l’un de ses éléments de liste.
append()
La méthode append() insère des nœuds ou du texte brut après les enfants existants d’un conteneur et accepte plusieurs entrées en un seul appel.
item.append(title, button) assemble deux éléments enfants dans un élément de liste avant son insertion dans la page.
aria-expanded
L’attribut aria-expanded décrit l’état ouvert ou fermé d’un composant aux technologies d’assistance avec les chaînes « true » ou « false ».
Lorsqu’un panneau de réponse s’ouvre, le bouton qui le contrôle doit aussi indiquer aria-expanded="true".
Array.from()
La méthode Array.from() crée un tableau à partir d’une collection, ce qui permet d’utiliser les méthodes de tableau et d’obtenir un instantané aux membres fixes.
Array.from(list.children) permet à une boucle de suppression de parcourir chaque enfant d’origine sans décalage d’indice.
Attribut
Un attribut est une valeur HTML nommée sur un élément, qui peut être lue ou modifiée par des méthodes telles que getAttribute() et setAttribute().
L’attribut href d’un lien peut contenir « /help » tandis que sa propriété indique une URL complète résolue.
Attribut ARIA
Un attribut ARIA fournit des informations sur le rôle, l’état ou le nom d’un élément aux technologies d’assistance telles que les lecteurs d’écran.
Définir aria-label à « Close dialog » fournit un nom accessible à un bouton composé d’une seule icône.
Attribut booléen
Un attribut booléen représente vrai par sa présence et faux par son absence, quel que soit le texte écrit comme valeur.
Un bouton reste désactivé après setAttribute("disabled", "false") parce que l’attribut existe.
Attribut de données
Un attribut de données est un attribut HTML personnalisé commençant par data- qui stocke des informations pour les scripts sans les afficher sous forme de texte.
Une ligne portant data-id="26" peut être associée à l’objet qui a fourni ses champs affichés.
Attribut defer
L’attribut defer diffère l’exécution d’un script externe classique jusqu’à la fin de l’analyse du HTML.
Un script différé dans head peut trouver un élément de pied de page écrit près de la fin du corps de la page.

B

Basculement forcé d’une classe
Un basculement forcé d’une classe définit la présence d’une classe à partir d’un second argument booléen, afin qu’elle corresponde à un état connu.
row.classList.toggle("done", task.done) maintient la ligne cohérente au fil des rendus répétés.

C

camelCase
La notation camelCase joint des mots en mettant en majuscule la première lettre de chaque mot après le premier, comme dans backgroundColor.
La propriété CSS background-color s’écrit style.backgroundColor en JavaScript.
checked
La propriété checked indique l’état actuel d’une case à cocher sous forme de booléen, indépendamment de son attribut checked initial.
Après que l’utilisateur a décoché une case initialement cochée, sa propriété checked devient false.
classList
La propriété classList donne accès aux noms de classes d’un élément et à des méthodes permettant de les ajouter, de les supprimer, de les tester, de les faire basculer ou de les remplacer individuellement.
Ajouter « selected » avec classList conserve la classe « card » existante et son style de base.
className
La propriété className est la chaîne complète des classes ; lui affecter une valeur remplace toutes les classes.
Affecter « active » au className d’une carte supprime son ancienne classe « card », sauf si elle est incluse à nouveau.
Clone profond
Un clone profond copie un nœud, ses attributs et tout son sous-arbre de descendants.
Cloner une carte remplie en profondeur copie son texte et ses spans imbriqués, ainsi que son identifiant d’origine.
closest()
La méthode closest() vérifie un élément et ses ancêtres pour trouver l’élément correspondant le plus proche selon un sélecteur.
Un span dans une carte de produit peut utiliser closest(".product") pour trouver la carte qui l’englobe.
Coalescence des nuls
La coalescence des nuls choisit une valeur de repli avec ?? uniquement lorsque la valeur de gauche est null ou undefined, et laisse les autres valeurs inchangées.
book.author ?? "Unknown author" fournit un texte lisible lorsque l’auteur facultatif est absent.
Collection dynamique
Une collection dynamique met ses membres à jour pour refléter le DOM actuel ; des modifications peuvent donc changer sa longueur et ses indices pendant une boucle.
Retirer une classe correspondante en parcourant les indices dans l’ordre croissant peut conduire une boucle à ignorer le membre dynamique suivant.
Collection statique
Une collection statique conserve les membres qu’elle avait à sa création, même si des éléments correspondants sont ensuite ajoutés à la page ou retirés de celle-ci.
Un résultat querySelectorAll() enregistré omet un quatrième élément ajouté après la recherche initiale.
Comparateur
Un comparateur indique à un tri, par sa valeur de retour, dans quel ordre placer deux valeurs.
Le comparateur (a, b) => a - b ordonne les valeurs numériques de la plus petite à la plus grande.
Contenu du template
Le contenu du template est le DocumentFragment distinct accessible par template.content, qui contient la structure enfant non affichée de l’élément template.
Une recherche dans le document ne trouve pas un span de titre dans l’élément template ; recherche dans son contenu ou dans un clone.
Conversion de type
La conversion de type change la représentation d’une valeur, par exemple en transformant en nombre le texte numérique d’un champ ou d’un attribut de données.
Number(row.dataset.id) permet à l’égalité stricte de comparer les chiffres stockés à l’identifiant numérique d’un objet.
Corps de tableau
Un corps de tableau est la section <tbody> qui regroupe les lignes de données d’un tableau.
Une fonction de rendu ajoute chaque nouveau <tr> au corps sélectionné et remplit ses champs dans des cellules <td>.
createElement()
La méthode createElement() crée un élément détaché à partir d’un nom de balise, prêt à être rempli puis inséré dans le document.
document.createElement("li") crée un élément de liste sans l’ajouter encore à la liste visible.

D

dataset
La propriété dataset expose les attributs de données d’un élément sous forme d’entrées dont les valeurs sont des chaînes et les noms sont convertis en camelCase.
Écrire row.dataset.recordId = "26" crée ou modifie l’attribut data-record-id.
display: none
La déclaration display: none masque un élément, supprime son espace dans la mise en page et exclut ce contenu masqué des lecteurs d’écran.
Un panneau de réponse fermé qui utilise cette déclaration ne laisse aucun bloc vide dans la mise en page.
DocumentFragment
Un DocumentFragment est un conteneur hors de la page dont les enfants sont déplacés vers la cible lors de son insertion, laissant le fragment vide.
Un fragment regroupe plusieurs nouvelles lignes avant que leurs enfants soient transférés dans le corps du tableau.

É

Élément
Un élément est un nœud DOM qui représente une balise HTML, ses attributs et ses éventuels nœuds enfants.
Un élément <ul> peut contenir deux éléments enfants <li> ainsi que des nœuds texte contenant des caractères d’espacement.
Élément template
Un élément template contient du HTML analysé mais non affiché et fournit une source réutilisable pour copier une structure répétée.
Un élément template de carte peut fournir les mêmes spans de titre et de détail pour chaque objet d’un tableau de données.
État vide
Un état vide indique aux utilisateurs qu’il n’y a aucune donnée à afficher.
Une liste de lecture sans livres peut afficher « Aucun livre pour le moment » à la place de ses éléments précédents.

E

Enfant
Un enfant est un nœud directement contenu dans un autre nœud, sans parent intermédiaire.
Le texte dans un span imbriqué est un descendant de l’élément de liste, mais il est l’enfant direct du span.

F

Fonction de rendu
Une fonction de rendu construit ou met à jour le DOM visible à partir des données actuelles et peut être rappelée après une modification de ces données.
Appeler la fonction après avoir marqué une tâche comme terminée met à jour sa classe et le nombre affiché de tâches terminées.

G

getElementById()
La méthode getElementById() trouve un élément par son identifiant littéral, sans ponctuation CSS.
document.getElementById("result") recherche l’identifiant « result », sans dièse initial.

H

hidden
La propriété hidden contrôle l’état masqué ordinaire : elle conserve l’élément dans le DOM tandis que le style par défaut supprime son espace dans la mise en page.
Définis panel.hidden = false pour afficher un panneau masqué sans reconstruire son contenu.
HTMLCollection
Une HTMLCollection est une collection dynamique indexée d’éléments qui se met à jour lorsque les relations entre éléments qui la définissent changent.
Supprimer un enfant modifie la longueur et les indices de la collection renvoyée par list.children.

I

Injection de script intersite
Une injection de script intersite est une attaque dans laquelle un contenu non fiable provoque l’exécution de code contrôlé par un attaquant dans le navigateur d’un visiteur.
Utiliser textContent pour un nom soumis empêche ses caractères de devenir du balisage injecté.
innerHTML
La propriété innerHTML lit le balisage interne et analyse le balisage qui lui est affecté pour créer de nouveaux nœuds enfants, en remplaçant les enfants existants.
Affecter le balisage fiable "<strong>Ready</strong>" crée un nouvel élément strong dans le conteneur.
innerText
La propriété innerText lit le texte selon la mise en page affichée, en ignorant les descendants masqués d’un élément affiché.
Le innerText d’un libellé visible omet une note imbriquée mise en forme avec display: none.
insertAdjacentHTML()
La méthode insertAdjacentHTML() analyse du balisage fiable à une position nommée à côté ou à l’intérieur d’un élément, tout en conservant les enfants existants.
La position « beforeend » ajoute du balisage dans un conteneur après son dernier enfant actuel.
insertBefore()
La méthode insertBefore() insère un nœud avant un enfant indiqué d’un parent, ou à la fin lorsque cette référence vaut null.
list.insertBefore(newItem, list.firstElementChild) place l’élément avant le premier élément enfant.
Insertion groupée
Une insertion groupée place plusieurs nœuds préparés dans un conteneur en une seule opération, avec un fragment ou un tableau de nœuds décomposé.
Construis d’abord les nœuds des éléments, puis passe-les ensemble à replaceChildren(...items).

M

Mise à jour ciblée
Une mise à jour ciblée modifie un élément existant pour qu’il corresponde aux données modifiées, tout en conservant l’objet élément et son état local.
Mettre à jour la classe done d’une seule ligne peut préserver le focus qui serait perdu si toutes les lignes étaient reconstruites.
Modèle objet de document
Le modèle objet de document est l’arbre dynamique des objets de la page dans le navigateur, exposé par une API et que JavaScript peut lire et modifier.
Un script met à jour un titre par le DOM pendant que la page reste ouverte dans le navigateur.

N

NodeList
Une NodeList est une collection DOM indexée possédant une longueur ; celle que renvoie querySelectorAll() contient les éléments correspondants.
Convertis les paragraphes sélectionnés avec Array.from() avant d’utiliser la méthode de tableau map().
Nœud
Un nœud est un objet de l’arbre DOM, tel qu’un élément, un texte, un commentaire ou le document.
L’élément paragraphe et le texte qu’il contient occupent des nœuds distincts dans l’arbre de la page.
Nœud détaché
Un nœud détaché est un nœud hors de l’arbre du document qui peut encore exister en mémoire tant qu’un script en conserve une référence.
Un élément supprimé peut être ajouté à nouveau par la variable qui fait toujours référence à son objet.
Nœud frère
Un nœud frère est un nœud qui partage le même parent immédiat qu’un autre nœud dans l’arbre DOM.
Deux éléments de liste adjacents sont des éléments frères même si un nœud texte contenant des caractères d’espacement se trouve entre eux.
Nœud texte
Un nœud texte contient des caractères du DOM, notamment des mots visibles ou des caractères d’espacement entre les balises.
Une liste indentée peut commencer par un nœud texte contenant un saut de ligne avant son premier élément.
Nom de classe
Un nom de classe est un nom séparé des autres noms de l’attribut class par des caractères d’espacement.
Passe « large » et « red » séparément à classList.add() pour qu’aucun des deux noms ne contienne d’espace.
null
null est la valeur explicite indiquant l’absence de résultat que renvoient les recherches d’un seul élément et les propriétés de l’arbre lorsqu’aucun objet ne correspond.
Vérifie une référence de bannière absente avant de définir son texte, car lire une propriété de null déclenche une erreur.

O

opacity: 0
La déclaration opacity: 0 rend un élément transparent tout en conservant son espace dans la mise en page, les interactions et l’accès par les lecteurs d’écran.
Un bouton invisible peut toujours réagir aux clics lorsque seule son opacité a été modifiée.
outerHTML
La propriété outerHTML inclut le balisage de l’élément lui-même ; lui affecter une valeur remplace l’élément par de nouveaux nœuds issus de l’analyse.
Après le remplacement, une variable contenant le paragraphe d’origine fait toujours référence à l’objet détaché.
Outils de développement
Les outils de développement sont l’ensemble des outils du navigateur qui permettent d’inspecter le DOM actuel, les règles CSS, les résultats de la console et les propriétés des éléments.
Sélectionner un paragraphe dans le panneau Éléments le rend accessible sous $0 dans la console.

P

Parent
Un parent est le nœud situé immédiatement au-dessus d’un autre dans l’arbre, qu’il contient comme enfant.
Dans <ul><li>Read</li></ul>, la liste est le parent immédiat de l’élément de liste.
prepend()
La méthode prepend() insère des nœuds ou du texte brut avant les enfants existants d’un conteneur et déplace les nœuds déjà présents ailleurs.
Placer le dernier élément d’une liste au début déplace ce même objet en première position sans le copier.
Propriété
Une propriété est une valeur ou une méthode nommée sur l’objet JavaScript d’un élément, qui expose parfois des données d’attribut traitées ou typées.
La propriété disabled renvoie un booléen, tandis que la lecture d’un attribut renvoie une chaîne ou null.
Propriété CSS personnalisée
Une propriété CSS personnalisée est une valeur CSS nommée dont le nom commence par deux tirets et à laquelle les règles peuvent faire référence avec la fonction var().
Définis "--accent" avec style.setProperty() pour modifier les règles qui font référence à cette valeur d’accent.

Q

querySelector()
La méthode querySelector() renvoie le premier élément correspondant à un sélecteur CSS dans sa zone de recherche, ou null si aucun ne correspond.
Rechercher dans une seule carte empêche qu’une classe .name répétée ailleurs soit renvoyée.

R

Rendu
Le rendu est le processus qui consiste à construire ou à mettre à jour le contenu DOM à partir de données afin que la page visible représente les valeurs actuelles.
Un tableau de livres devient une liste en construisant, pour chaque objet, un élément contenant un titre et un nombre de pages.
replaceChildren()
La méthode replaceChildren() remplace les enfants d’un conteneur par les nœuds ou le texte fournis, ou les supprime lorsqu’aucune entrée n’est fournie.
Un rendu complet utilise cette méthode pour supprimer les anciens éléments et placer le nouvel affichage construit.
replaceWith()
La méthode replaceWith() remplace le nœud sélectionné lui-même par les nœuds ou le texte fournis à sa position actuelle.
Un paragraphe de chargement peut être remplacé par une liste achevée tandis que le reste de la page reste en place.

S

Sélecteur CSS
Un sélecteur CSS est un motif qui permet de trouver des éléments selon des caractéristiques telles que leur balise, leur classe, leur identifiant ou leur imbrication.
Le sélecteur "#profile .name" trouve les descendants de classe name de l’élément profile.
Source de vérité
Une source de vérité est l’ensemble des données conservées comme état de référence à partir duquel sont construits les éléments affichés et les récapitulatifs de la page.
Supprimer un objet du tableau de tâches à partir duquel une liste est affichée empêche le rendu suivant de rétablir son élément de liste.
Style calculé
Un style calculé est une valeur de style résolue, accessible en lecture seule et fournie par le navigateur après prise en compte des déclarations CSS applicables.
getComputedStyle(title).color peut indiquer le rouge même lorsque title.style.color est vide.
Style en ligne
Un style en ligne est une déclaration CSS placée dans l’attribut style d’un élément.
L’affectation bar.style.width = "60%" stocke directement sur la barre une largeur de progression calculée.
Syntaxe de décomposition
La syntaxe de décomposition développe un itérable en valeurs distinctes, ce qui permet de passer un tableau de nœuds comme arguments individuels à une méthode.
list.append(...items) insère chaque nœud construit au lieu de la représentation textuelle du tableau.

T

textContent
La propriété textContent lit le texte des descendants et, lorsqu’on lui affecte une valeur, remplace les nœuds enfants par du texte brut sans analyser de HTML.
Affecter « Ready » affiche ces caractères et ne crée pas d’élément d’emphase.
toFixed()
La méthode toFixed() renvoie un nombre sous forme de chaîne avec un nombre de décimales indiqué, adapté à un affichage mis en forme.
Une température de 28,5 devient la chaîne « 28.5 » avec toFixed(1) avant son insertion dans une cellule.
Tri en place
Le tri en place réordonne le tableau d’origine : les références existantes à ce tableau voient donc le nouvel ordre.
Crée une copie avec [...items] avant d’appeler sort() lorsque l’ordre de la source doit rester inchangé.

U

Unité CSS
Une unité CSS donne son sens à une longueur ou à une autre valeur de style, par exemple les pixels pour une largeur absolue ou le pourcentage pour une largeur relative.
Une largeur non nulle nécessite un texte tel que « 180px » ; un nombre seul est ignoré en mode standard.

V

value
La propriété value contient la valeur actuelle d’un composant de formulaire sous forme de chaîne ; elle peut différer de son attribut HTML initial.
Lire un champ de quantité après modification renvoie le texte actuellement saisi, pas sa valeur d’origine.
visibility: hidden
La déclaration visibility: hidden masque un élément tout en conservant son espace dans la mise en page et en le masquant aux lecteurs d’écran.
Une boîte d’état invisible peut réserver son espace habituel afin que le contenu qui l’entoure ne se déplace pas.
Vue dérivée
Une vue dérivée est un tableau filtré ou réordonné utilisé pour l’affichage, tandis que les données d’origine restent disponibles pour d’autres vues.
Affiche les tâches non terminées avec tasks.filter(task => !task.done) sans abandonner celles qui sont terminées.

À propos de cette unité

Par StudeliSignaler une erreur

Crée ton propre Matériel d'Étude

Transforme tes notes, diapos et documents en Guides d'Étude, Questions Pratiques, Flashcards et 6 autres outils.

Commencer