DOM en JavaScript : le modèle objet de document
DébutantUnité 5 sur 9 de la formation Formation : JavaScript : DOM, événements et code asynchrone
Ce que tu vas apprendre
- 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œudsExplique 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èresParcours 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.
- Décris le DOM comme un arbre de nœuds
- 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émentTrouve 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ésultatsSé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.
- Sélectionne un seul élément
- 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émentLis 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ésManipule 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 formulaireConserve 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.
- Modifie le texte et le HTML à l’intérieur d’un élément
- 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 CSSModifie 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ésDé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 pageMasque 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.
- Ajoute, supprime et fais basculer des classes CSS
- 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-lesCré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émentsRetire des éléments de la page, vide un conteneur, remplace un élément par un autre et crée des copies avec cloneNode.
- Crée de nouveaux éléments et insère-les
- 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éesTransforme 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 templateInsè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 changentConserve 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.
- Construis des éléments de liste et des lignes de tableau à partir d’un tableau de données
DOM en JavaScript : cours
1Lis 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.
2Trouve 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.
3Mets à 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, ounullsi 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.
4Contrô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.
5Construis 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.
6Transforme 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
1Repère-toi dans l’arbre d’une page
11 étapes
- 1IntroductionCommence 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.
- 2ExplicationEntre par document
Le DOM est le modèle dynamique de la page dans le navigateur.
documenty donne accès ;document.bodyfait 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.
- 3ExempleObserve 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
nodeTypepour 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. - 4ExempleCompte 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.lengthvaut donc 2, tandis quechildNodes.lengthvaut 5. Les nœuds supplémentaires proviennent des caractères entre les balises. - 5Dé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.firstChildet pourquoi diffère-t-il detasks.firstElementChild?---reveal---
firstChildest le nœud texte contenant des caractères d’espacement avant le premier élément.firstElementChildignore 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. - 6ConseilInspecte 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é,
$0dans la console y fait référence etconsole.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. - 7ExemplePasse à 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.textContentvaut « Call Sam ». Lirefirst.nextSiblingatteint à 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. - 8ExplicationArrête-toi sans erreur au dernier élément
Le
nextElementSiblingdu dernier élément vautnull. Lire une propriété directement à partir de cette référence absente déclenche une TypeError.second.nextElementSibling?.textContents’arrête là et donneundefined, sans ajouter de nœud ni fournir de chaîne vide. - 9LienTrouve 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. - 10Dé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. - 11Ré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.
2Sélectionne et mets à jour les éléments voulus
12 étapes
Enregistre cette unité pour suivre chaque Leçon Interactive pas à pas.
- 1IntroductionChoisis une recherche avant de modifier une page
- 2ExplicationUtilise la syntaxe d’identifiant adaptée à la méthode
- 3ExempleLimite la recherche d’une classe répétée à sa carte
- 4ConseilDistingue un nœud absent d’une syntaxe incorrecte
- 5DéfiExplique un résultat null obtenu trop tôt
- 6ExempleParcours les éléments renvoyés
- 7ExplicationConvertis la collection lorsque tu as besoin de méthodes de tableau
- 8ExempleCompare deux collections enregistrées
- 9Point cléObserve une collection dynamique qui rétrécit
- 10DéfiChoisis le bon sélecteur combiné
- 11DéfiCombine une recherche limitée avec une boucle sûre
- 12RécapitulatifDiagnostique ton prochain échec de recherche
3Mets un profil à jour et lis les valeurs de son formulaire
15 étapes
Enregistre cette unité pour suivre chaque Leçon Interactive pas à pas.
- 1IntroductionDistingue les informations contenues dans un élément
- 2ExempleLis le texte sans ses balises
- 3ExplicationTraite les valeurs extérieures comme des caractères
- 4DéfiPréserve un champ existant
- 5LienLis le texte affiché lorsque c’est nécessaire
- 6ExempleLis une URL telle qu’elle est écrite ou son URL résolue
- 7ExplicationDéfinis un booléen par sa présence
- 8DéfiRépare un composant désactivé
- 9ExempleTransforme un nom de donnée en nom de propriété
- 10ExplicationLis le contenu actuel d’un champ
- 11DéfiCalcule avec la valeur d’un champ
- 12ExempleTrouve un objet à l’aide d’un identifiant affiché
- 13ConseilDonne un nom lisible à un bouton à icône
- 14DéfiRelie la recherche de données à un affichage sûr
- 15RécapitulatifInspecte un champ avant et après modification
4Fais suivre à l’apparence un état clair
13 étapes
Enregistre cette unité pour suivre chaque Leçon Interactive pas à pas.
- 1IntroductionLaisse les données déterminer l’état visible
- 2ExempleConserve une classe de base en ajoutant un état
- 3ExplicationUtilise une condition pour les mises à jour répétées
- 4DéfiPrévois le résultat de deux mises à jour répétées
- 5ExempleCalcule un pourcentage CSS
- 6ExplicationLis le résultat de la cascade
- 7DéfiRétablis la couleur de la feuille de style
- 8ExplicationChoisis ce que la fermeture d’un panneau supprime
- 9ExempleSynchronise un panneau et son bouton
- 10ConseilVérifie un style qui prend le dessus sur hidden
- 11DéfiDiagnostique un composant invisible mais actif
- 12DéfiCombine des classes avec une valeur calculée
- 13RécapitulatifVérifie séparément l’état et l’apparence
5Construis des éléments et suis leurs références d’objet
12 étapes
Enregistre cette unité pour suivre chaque Leçon Interactive pas à pas.
- 1IntroductionConstruis un élément de tâche en plusieurs étapes
- 2ExempleCrée un élément détaché
- 3ExempleInsère l’élément terminé
- 4ExplicationChoisis entre enfants et frères
- 5ExempleDéplace un nœud existant
- 6DéfiExplique pourquoi une boucle ne produit qu’un élément
- 7ExplicationDétache un élément sans détruire sa référence
- 8ExempleRemplace un élément ou tout un affichage
- 9ConseilCopie les descendants et vérifie les identifiants
- 10DéfiPrévois le contenu d’une copie superficielle
- 11DéfiDéplace l’original et insère une copie
- 12RécapitulatifSuis les identités en parallèle du balisage
6Affiche une liste à partir de données et mets-la à jour de façon fiable
17 étapes
Enregistre cette unité pour suivre chaque Leçon Interactive pas à pas.
- 1IntroductionLaisse le tableau de données déterminer l’affichage
- 2ExempleÉcris une fonction de construction pour un livre
- 3ExempleDécompose le tableau en arguments de type nœud
- 4ConseilRends les données manquantes lisibles
- 5LienApplique le schéma aux lignes d’un tableau
- 6DéfiTrouve pourquoi la liste affiche du texte représentant des objets
- 7ExempleRegroupe des nœuds hors de la page
- 8ExplicationConserve la structure répétée en HTML
- 9ExempleRemplis le clone avant de le transférer
- 10DéfiPréserve l’élément template réutilisable
- 11ExplicationRemplace l’affichage à partir des données actuelles
- 12ExempleMets à jour un objet et son récapitulatif
- 13ExplicationConserve une vue triée séparément
- 14DéfiExplique pourquoi un élément revient après sa suppression
- 15Point cléPréserve l’état local de saisie
- 16DéfiCombine une recherche avec une mise à jour ciblée
- 17RécapitulatifVérifie le rendu pour trois états
DOM en JavaScript : QCM
Série 1 : Lis et modifie une page10 Questions Pratiques
Question 1 sur 10
Afficher la réponseMasquer la réponse
Question 2 sur 10
<ul><li>A</li> <li>B</li></ul>, une variable first contient le premier élément de liste. Que renvoie first.nextSibling.nodeType ?Afficher la réponseMasquer la réponse
nextElementSibling. La navigation entre nœuds inclut le texte entre les balises ; la navigation entre éléments l’ignore.Question 3 sur 10
<section id="report"> avec getElementById() ?Afficher la réponseMasquer la réponse
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
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 ?Afficher la réponseMasquer la réponse
Question 5 sur 10
label.textContent = "<em>Saved</em>" ?Afficher la réponseMasquer la réponse
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
button.setAttribute("disabled", "false"). Quel état button.disabled indique-t-il ?Afficher la réponseMasquer la réponse
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
input.value + 2 ?Afficher la réponseMasquer la réponse
+ 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
class="card compact". Comment le code peut-il ajouter « selected » tout en conservant les deux classes existantes ?Afficher la réponseMasquer la réponse
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
list.append(list.firstElementChild) ?Afficher la réponseMasquer la réponse
Question 10 sur 10
makeItem() renvoie un nouveau <li>. Qu’insère list.append(records.map(makeItem)) lorsque records contient deux entrées ?Afficher la réponseMasquer la réponse
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
<table><tr><td>8</td></tr></table>. Quel élément enfant direct l’analyseur place-t-il normalement dans le tableau ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 2 sur 10
<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 ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 3 sur 10
.note. L’un perd sa classe note et un nouvel élément note est ajouté. Quelle est la longueur de la NodeList enregistrée ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 4 sur 10
data-record-id="38". Comment le code peut-il comparer cet identifiant au nombre 38 avec l’égalité stricte ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 5 sur 10
Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 6 sur 10
Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 7 sur 10
container.replaceChildren(), définit a.textContent = "C", puis exécute container.append(a) et container.append(a.cloneNode(true)). Que contient le conteneur ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 8 sur 10
score: 0. Qu’affiche record.score ?? "Pending" lorsqu’il est affecté à textContent ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 9 sur 10
Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 10 sur 10
[{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 ?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
entry et se trouve dans une section ayant la même classe. Que renvoie button.closest(".entry") ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 2 sur 10
.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 ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 3 sur 10
Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 4 sur 10
https://example.com/catalog/, un lien est écrit <a href="/guide">Guide</a>. Que renvoie link.getAttribute("href") ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 5 sur 10
class="row done". Le code exécute deux fois row.classList.toggle("done", false). Quelles classes restent présentes ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 6 sur 10
Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 7 sur 10
insertAdjacentHTML() doit-il insérer une note fiable comme premier enfant de la section ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 8 sur 10
Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 9 sur 10
template.content à une liste. Pourquoi un appel ultérieur à template.content.querySelector(".title") renvoie-t-il null ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 10 sur 10
[{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 ?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
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 ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 2 sur 10
.status. Une variable main contient la section principale. Quelle recherche trouve son premier descendant status ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 3 sur 10
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 ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 4 sur 10
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 ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 5 sur 10
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é ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 6 sur 10
a, exécute list.lastElementChild.before(a), puis list.prepend(list.lastElementChild). Quel est l’ordre final ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 7 sur 10
author. Quelle affectation affiche « Unknown author » sans analyser la valeur comme du HTML ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 8 sur 10
clone.querySelector(".name").textContent = record.name. Pourquoi cela échoue-t-il ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 9 sur 10
<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 ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 10 sur 10
[{"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 ?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
<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 ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 2 sur 10
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 ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 3 sur 10
<script>. Quelle mise à jour conserve l’élément d’aperçu et insère le commentaire comme texte littéral sans analyse HTML ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 4 sur 10
Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 5 sur 10
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 ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 6 sur 10
Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 7 sur 10
const open = panel.hidden, définit panel.hidden = !open et écrit String(open) dans aria-expanded. Quels sont les états finaux ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 8 sur 10
<li id="copy-me"><span>Map</span></li> est copié avec cloneNode(false). Que contient le clone détaché ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 9 sur 10
list.replaceChildren(fragment). Quels objets restent remplis ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 10 sur 10
{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 ?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
A
Analyse syntaxique
<tbody>.Ancêtre
append()
item.append(title, button) assemble deux éléments enfants dans un élément de liste avant son insertion dans la page.aria-expanded
aria-expanded="true".Array.from()
Array.from(list.children) permet à une boucle de suppression de parcourir chaque enfant d’origine sans décalage d’indice.Attribut
getAttribute() et setAttribute().href d’un lien peut contenir « /help » tandis que sa propriété indique une URL complète résolue.Attribut ARIA
aria-label à « Close dialog » fournit un nom accessible à un bouton composé d’une seule icône.Attribut booléen
setAttribute("disabled", "false") parce que l’attribut existe.Attribut de données
data- qui stocke des informations pour les scripts sans les afficher sous forme de texte.data-id="26" peut être associée à l’objet qui a fourni ses champs affichés.Attribut defer
B
Basculement forcé d’une classe
row.classList.toggle("done", task.done) maintient la ligne cohérente au fil des rendus répétés.C
camelCase
backgroundColor.background-color s’écrit style.backgroundColor en JavaScript.checked
checked devient false.classList
classList conserve la classe « card » existante et son style de base.className
className d’une carte supprime son ancienne classe « card », sauf si elle est incluse à nouveau.Clone profond
closest()
closest(".product") pour trouver la carte qui l’englobe.Coalescence des nuls
?? 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
Collection statique
querySelectorAll() enregistré omet un quatrième élément ajouté après la recherche initiale.Comparateur
(a, b) => a - b ordonne les valeurs numériques de la plus petite à la plus grande.Contenu du template
template.content, qui contient la structure enfant non affichée de l’élément template.Conversion de type
Number(row.dataset.id) permet à l’égalité stricte de comparer les chiffres stockés à l’identifiant numérique d’un objet.Corps de tableau
<tbody> qui regroupe les lignes de données d’un tableau.<tr> au corps sélectionné et remplit ses champs dans des cellules <td>.createElement()
document.createElement("li") crée un élément de liste sans l’ajouter encore à la liste visible.D
dataset
row.dataset.recordId = "26" crée ou modifie l’attribut data-record-id.display: none
DocumentFragment
É
É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
État vide
E
Enfant
F
Fonction de rendu
G
getElementById()
document.getElementById("result") recherche l’identifiant « result », sans dièse initial.H
hidden
panel.hidden = false pour afficher un panneau masqué sans reconstruire son contenu.HTMLCollection
list.children.I
Injection de script intersite
textContent pour un nom soumis empêche ses caractères de devenir du balisage injecté.innerHTML
"<strong>Ready</strong>" crée un nouvel élément strong dans le conteneur.innerText
innerText d’un libellé visible omet une note imbriquée mise en forme avec display: none.insertAdjacentHTML()
insertBefore()
list.insertBefore(newItem, list.firstElementChild) place l’élément avant le premier élément enfant.Insertion groupée
replaceChildren(...items).M
Mise à jour ciblée
Modèle objet de document
N
NodeList
querySelectorAll() contient les éléments correspondants.Array.from() avant d’utiliser la méthode de tableau map().Nœud
Nœud détaché
Nœud frère
Nœud texte
Nom de classe
classList.add() pour qu’aucun des deux noms ne contienne d’espace.null
O
opacity: 0
outerHTML
Outils de développement
$0 dans la console.P
Parent
<ul><li>Read</li></ul>, la liste est le parent immédiat de l’élément de liste.prepend()
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
var()."--accent" avec style.setProperty() pour modifier les règles qui font référence à cette valeur d’accent.Q
querySelector()
null si aucun ne correspond..name répétée ailleurs soit renvoyée.R
Rendu
replaceChildren()
replaceWith()
S
Sélecteur CSS
"#profile .name" trouve les descendants de classe name de l’élément profile.Source de vérité
Style calculé
getComputedStyle(title).color peut indiquer le rouge même lorsque title.style.color est vide.Style en ligne
bar.style.width = "60%" stocke directement sur la barre une largeur de progression calculée.Syntaxe de décomposition
list.append(...items) insère chaque nœud construit au lieu de la représentation textuelle du tableau.T
textContent
toFixed()
toFixed(1) avant son insertion dans une cellule.Tri en place
[...items] avant d’appeler sort() lorsque l’ordre de la source doit rester inchangé.U
Unité CSS
V
value
visibility: hidden
Vue dérivée
tasks.filter(task => !task.done) sans abandonner celles qui sont terminées.À propos de cette unité
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.