Sélectionner des éléments dans le DOM

Présentation

Le DOM, ou Document Object Model, est une représentation hiérarchique et structurée d'une page web chargée dans le navigateur. Il permet de lire et de modifier les éléments qui composent la page, comme les titres, les paragraphes, les listes, les formulaires ou les images.

Lorsqu'une page est affichée, le navigateur transforme le code HTML en un arbre de nœuds. Chaque balise devient un objet du DOM, manipulable via des propriétés et des méthodes. Ce sont ces objets que l'on manipule pour rendre une page interactive et dynamique.

Manipuler le DOM consiste donc à intervenir sur la structure, le contenu ou certains attributs de la page après son chargement, par exemple pour réagir à une action de l'utilisateur ou à un changement d'état de l'application.

Voici quelques situations concrètes dans lesquelles on manipule le DOM :

  • Modifier le texte affiché dans une page après une action de l'utilisateur.
  • Afficher ou masquer un élément selon un contexte précis.
  • Ajouter dynamiquement des éléments dans une liste.
  • Changer l'apparence d'un élément en lui ajoutant ou retirant une classe CSS.
  • Supprimer un élément devenu inutile.

Dans la majorité des cas, une manipulation du DOM suit une logique simple et répétitive. Avant d'entrer dans les détails techniques, voici un exemple de déroulement typique.

  1. Identifier l'élément de la page sur lequel on souhaite agir.
  2. Sélectionner cet élément dans le DOM.
  3. Lire ou modifier son contenu, ses attributs ou son apparence.
  4. Constater immédiatement le changement à l'écran.

Principes de sélection

Avant de pouvoir modifier une page web, il faut d'abord être capable de désigner précisément l'élément sur lequel on souhaite agir. On ne modifie pas directement le code HTML écrit dans le fichier, mais les objets du DOM qui représentent les balises affichées à l'écran.

Les sélecteurs permettent justement de cibler ces éléments dans le DOM. La plupart des sélecteurs modernes sont des méthodes de l'objet document, qui représente le document HTML chargé dans le navigateur.

Dans cette section, nous allons utiliser des sélecteurs CSS. Si ces notions ne sont pas claires, je vous suggère de consulter le chapitre traitant des sélecteurs CSS avant de continuer.

Sélectionner un seul élément

Pour sélectionner un élément unique, la méthode moderne à privilégier est querySelector(). Elle utilise la syntaxe des sélecteurs CSS et permet de garder une approche cohérente, même lorsque vos sélections deviennent plus complexes.

La méthode querySelector() sélectionne un élément à l'aide d'un sélecteur CSS. Elle renvoie le premier élément correspondant au sélecteur fourni, ou null si aucun élément ne correspond.

Le sélecteur CSS doit être fourni sous forme de chaîne de caractères en argument de la méthode. Il s'agit de la même syntaxe que celle utilisée en CSS pour cibler des éléments.

Sélection par id avec querySelector()

Pour cibler un élément par son attribut id, utiliser le sélecteur CSS commençant par # suivi du nom de l'identifiant.

Code HTML :


                    <body>
                        <div id="conteneur">
                            <h2>Titre</h2>
                        </div>
                    </body>
                

Code JS :


                    // Sélectionner l'élément dont l'id vaut "conteneur".
                    const conteneurElem = document.querySelector('#conteneur');

                    console.log(conteneurElem); // Affiche : <div id="conteneur">...</div>
                

À propos de document.getElementById()

Avant l'arrivée des sélecteurs CSS dans le DOM, une méthode très utilisée pour sélectionner un élément unique consistait à passer par son attribut HTML id, via getElementById(). Cette méthode existe toujours et vous la rencontrerez régulièrement dans du code plus ancien.

Dans certains cas, getElementById() peut être légèrement plus rapide que querySelector(). En pratique, cette différence reste négligeable dans la plupart des projets. On privilégie donc souvent querySelector() afin de garder une seule syntaxe de sélection et d'éviter de mélanger plusieurs approches.

La méthode getElementById() renvoie l'élément correspondant, ou null si aucun élément ne possède cet identifiant.

La valeur de l'attribut id doit être fournie sous forme de chaîne de caractères en argument de la méthode. Il ne s'agit pas d'un sélecteur CSS, mais directement de la valeur de l'attribut, sans préfixe particulier.

Nous allons donc cibler la même balise que dans l'exemple précédent, celle dont l'attribut id vaut conteneur, mais cette fois-ci en utilisant cette méthode dédiée.

Code HTML :


                        <body>
                            <div id="conteneur">
                                <h1>Titre</h1>
                            </div>
                        </body>
                    

Code Javascript :


                        // Cibler directement la balise HTML dont l'attribut "id" vaut "conteneur"
                        // puis stocker la référence dans la constante "conteneurElem".
                        const conteneurElem = document.getElementById('conteneur');

                        console.log(conteneurElem); // Affiche : <div id="conteneur">...</div>
                    

Sélection par classe

Pour cibler un élément via une classe CSS, on utilise le sélecteur CSS commençant par un point (.) suivi du nom de la classe.

Code HTML :


                    <section class="js-bloc-info">
                        <p>Premier bloc</p>
                    </section>
                

Code JS :


                    // Sélectionner l'élément ayant pour classe CSS "js-bloc-info".
                    const blocInfoElem = document.querySelector('.js-bloc-info');

                    console.log(blocInfoElem); // Affiche : <section class="js-bloc-info">...</section>
                

Correspondances multiples pour un même sélecteur CSS

La méthode querySelector() renvoie au maximum un seul élément. Si plusieurs éléments correspondent au sélecteur CSS passé en argument, seul le premier dans l'ordre du document sera renvoyé.

Code HTML :


                    <section class="js-bloc-info">
                        <p>Premier bloc</p>
                    </section>

                    <section class="js-bloc-info">
                        <p>Premier bloc</p>
                    </section>
                

Code JS :


                    // Sélectionner le premier élément rencontré ayant pour classe CSS "js-bloc-info".
                    const blocInfoElem = document.querySelector('.js-bloc-info');

                    console.log(blocInfoElem); // Affiche la première section : <section class="js-bloc-info">...</section>
                

Il est évidemment possible de sélectionner l'ensemble des éléments correspondants, (ex.: récupérer les deux balises section ayant pour classe CSS js-bloc-info et pas seulement la première). Pour cela, on utilise la méthode querySelectorAll().

Sélectionner plusieurs éléments

Pour récupérer plusieurs éléments d'un coup, utiliser querySelectorAll(). La méthode renvoie un NodeList contenant tous les éléments correspondants, ou un NodeList vide si aucun élément ne correspond.

Sélection simple avec querySelectorAll()

Dans l'exemple suivant, toutes les balises ayant pour classe CSS js-bloc-info sont sélectionnées. Le résultat est stocké dans une constante afin de pouvoir le parcourir ensuite.

Code HTML :


                    <section class="js-bloc-info">
                        <p>Premier bloc</p>
                    </section>

                    <section class="js-bloc-info">
                        <p>Deuxième bloc</p>
                    </section>
                

Code JS :


                    // Sélectionner tous les éléments ayant pour classe CSS "js-bloc-info".
                    const blocInfoElements = document.querySelectorAll('.js-bloc-info');

                    // Vérifier combien d'éléments ont été trouvés.
                    console.log(blocInfoElements.length); // 2

                    // Afficher la collection.
                    console.log(blocInfoElements); // Affiche : NodeList [ section.js-bloc-info, section.js-bloc-info ]
                

Parcourir un NodeList

Un NodeList se parcourt facilement avec for...of. Chaque tour de boucle fournit une référence vers un élément différent.

Code HTML :


                    <section class="js-bloc-info">
                        <p>Premier bloc</p>
                    </section>

                    <section class="js-bloc-info">
                        <p>Deuxième bloc</p>
                    </section>
                

Code JS :


                    // Sélectionner tous les éléments ayant pour classe CSS "js-bloc-info".
                    const blocInfoElements = document.querySelectorAll('.js-bloc-info');

                    // Parcourir chaque élément sélectionné.
                    for (const blocInfoElem of blocInfoElements)
                    {
                        // Afficher chaque élément individuellement.
                        console.log(blocInfoElem);
                    }
                    /*
                        Affiche :
                            <section class="js-bloc-info">...</section>
                            <section class="js-bloc-info">...</section>
                    */
                

Convertir en tableau pour utiliser map() ou filter()

Un NodeList n'est pas un tableau. Pour utiliser des méthodes comme map() ou filter(), commencer par convertir le NodeList en tableau.

Code HTML :


                    <section class="js-bloc-info">
                        <p>Premier bloc</p>
                    </section>

                    <section class="js-bloc-info">
                        <p>Deuxième bloc</p>
                    </section>
                

Code JS :


                    // Sélectionner tous les éléments ayant pour classe CSS "js-bloc-info".
                    const blocInfoElements = document.querySelectorAll('.js-bloc-info');

                    // Convertir le NodeList en tableau.
                    const blocInfoElementsTableau = Array.from(blocInfoElements);

                    // On peut maintenant utiliser les méthodes de tableaux (ex.: map(), filter(), etc.)
                    // sur "blocInfoElementsTableau" pour agir sur chacune des références au DOM y étant stockée.
                

Notez que la NodeList renvoyé par querySelectorAll() est statique. Si de nouvelles balises portant la classe CSS js-bloc-info sont ajoutées au DOM après la sélection, elles n'apparaîtront pas dans ce NodeList. Pour obtenir une liste à jour, relancer une sélection avec querySelectorAll().

Approche historique avec getElementsByClassName()

Avant l'usage systématique des sélecteurs CSS avec querySelectorAll(), une méthode très courante pour récupérer des éléments consistait à sélectionner directement une classe CSS avec getElementsByClassName().

Code HTML :


                        <ul id="liste">
                            <li class="js-item">A</li>
                            <li class="js-item">B</li>
                        </ul>
                    

Code Javascript :


                        // Récupérer tous les éléments ayant la classe "js-item"
                        const liElements = document.getElementsByClassName('js-item');
                        console.log(liElements); Affiche : HTMLCollection { 0: li.js-item, 1: li.js-item, length: 2 }
                    

Le résultat est une HTMLCollection dite live. Cela signifie qu'elle se met à jour automatiquement si le DOM change. Autrement dit, si un nouvel élément portant la classe est ajouté au DOM après la sélection, la collection reflète immédiatement ce nouvel état.

Cette caractéristique peut être utile, mais elle peut aussi surprendre. Une boucle qui parcourt la collection pendant que le DOM change peut se comporter de façon inattendue, car la collection évolue pendant l'itération.

Dans un code moderne, l'approche la plus utilisée consiste à sélectionner avec querySelector() ou querySelectorAll(), car on bénéficie des sélecteurs CSS et d'un comportement plus prévisible.

Sélection par type de balise

Un nom de balise peut aussi servir de sélecteur CSS. Comme ce type de sélection renvoie souvent plusieurs correspondances, on utilise généralement querySelectorAll(). Pour éviter de sélectionner partout dans la page, on précise souvent un conteneur.

Code HTML :


                    <section>
                        <h2>Lorem ipsum</h2>
                        <p>Premier paragraphe</p>
                        <p>Deuxième paragraphe</p>
                    </section>

                    <section>
                        <h2>Dolor sit amet</h2>
                        <p>Troisième paragraphe</p>
                    </section>
                

Code JS :


                    // Sélectionner tous les paragraphes de la page.
                    const pElements = document.querySelectorAll('p');

                    console.log(pElements); // Affiche : NodeList(3) [ p, p, p ]
                

La sélection par type de balise reste possible, mais elle dépend fortement de la structure du HTML. Dès que cette structure évolue, la sélection peut devenir fragile. Pour cibler un élément ou un groupe d'éléments de manière plus stable, l'utilisation d'une classe CSS ou d'un id est généralement plus appropriée.

Approche historique avec getElementsByTagName()

Avant la généralisation des sélecteurs CSS en JavaScript, une manière courante de cibler des éléments consistait à sélectionner directement toutes les balises d'un même type à l'aide de getElementsByTagName(). Cette approche était simple et suffisante dans des structures HTML peu complexes.

Code HTML :


                        <main>
                            <p>Premier paragraphe</p>
                            <p>Deuxième paragraphe</p>
                        </main>
                    

Code Javascript :


                        // Récupérer toutes les balises "p"
                        const pElements = document.getElementsByTagName('p');

                        // Cibler le premier paragraphe
                        console.log(pElements); // Affiche : HTMLCollection { 0: p, 1: p, length: 2 }
                    

Tout comme pour getElementsByClassName(), getElementsByTagName() retourne une HTMLCollection. C'est à dire que si une balise du même type est ajoutée au DOM par la suite, la collection se mettra automatiquement à jour.

Choisir un sélecteur adapté

Il existe plusieurs façons de sélectionner des éléments dans le DOM. Toutes fonctionnent techniquement, mais elles ne présentent pas le même niveau de stabilité ni la même intention. Avant d'écrire un sélecteur, il est donc utile de se demander ce que l'on cherche réellement à cibler.

Les limites de la sélection par type de balise

Sélectionner un élément par son nom de balise est simple et efficace, mais cette approche dépend fortement de la structure du document. Si le HTML évolue ou si de nouveaux éléments sont ajoutés, la sélection peut inclure des éléments non souhaités.

Ce type de sélection est surtout adapté à des exemples simples ou à des traitements très généraux. Pour des comportements précis, d'autres sélecteurs sont souvent préférables.

Utiliser un id pour cibler un élément unique

Un id identifie un élément unique dans la page. Il peut servir au lien, au style CSS et au ciblage par JavaScript.

En JavaScript, un id reste pratique dans un petit projet ou un exercice, lorsqu'il existe un seul élément clairement unique et durable, par exemple un conteneur principal, une zone de navigation ou un formulaire.

Dans un projet plus grand, l'usage systématique des id devient plus contraignant. Un id doit rester unique sur toute la page, ce qui complique la réutilisation de blocs. De plus, un sélecteur CSS basé sur un id est très spécifique, ce qui peut rendre les ajustements de style moins souples.

Pour limiter les effets de bord, une pratique courante consiste à réserver l'id à l'identification et à utiliser une classe dédiée au ciblage JavaScript. Cela évite qu'un changement de style impose de renommer un sélecteur attendu par le script.

Exemple :


                    <header id="zone-navigation" class="js-zone-navigation">...</header>
                

Classes visuelles et classes utilisées par JavaScript

En HTML, l'attribut class définit toujours des classes CSS. Toutefois, une même classe peut être utilisée pour des objectifs différents, comme la mise en forme ou le ciblage par JavaScript.

Cette distinction ne vient pas du langage lui-même, mais d'une convention de nommage et d'organisation du code. Une classe liée au style décrit une apparence, tandis qu'une classe utilisée par JavaScript décrit un rôle ou un comportement.

Utiliser une même classe pour ces deux rôles peut poser problème lors des évolutions. Une classe de style est souvent renommée, déplacée ou supprimée pour des raisons visuelles. Si un script dépend de ce nom, il cesse de fonctionner sans que l'erreur soit visible immédiatement. Séparer les classes de style et les classes de ciblage réduit ce couplage et limite les régressions lorsque la mise en forme change.

Mélanger ces deux usages peut rendre le code plus fragile. Lorsqu'un élément doit être ciblé par un script, il est donc préférable d'utiliser une classe dédiée à la sélection, distincte de celles utilisées uniquement pour le style. Une pratique courante, sans être obligatoire, consiste à préfixer ces classes avec js- pour indiquer qu'elles servent au ciblage en Javascript. Cela permet de distinguer rapidement les classes liées au style de celles liées au comportement.

Exemple :


                        <button class="btn-alerte js-supprimer">Supprimer</button>
                

Dans cet exemple, btn-alerte est liée au visuel, tandis que js-supprimer sert de point d'ancrage pour le JavaScript.

Combiner plusieurs critères de sélection CSS

Quand un sélecteur devient plus précis, l'intention est plus claire et les collisions deviennent moins probables. Trois approches reviennent souvent, combiner plusieurs critères, limiter la recherche à une zone du DOM, puis utiliser des pseudo-classes simples.

Sélecteur descendant et correspondances à plusieurs niveaux

Un espace dans un sélecteur CSS correspond à une relation de type descendant. Cela permet de cibler des éléments situés à l'intérieur d'une zone, quel que soit leur niveau d'imbrication dans le DOM.

Code HTML :


                    <section id="zone-01">
                        <h2>Zone 01</h2>
                        <div class="js-balise-de-test js-test-1">
                            <div class="js-balise-de-test js-test-2"></div>
                        </div>
                        <div class="js-balise-de-test js-test-3"></div>
                    </section>

                    <section id="zone-02">
                        <h2>Zone 02</h2>
                        <div class="js-balise-de-test js-test-4">
                            <div class="js-balise-de-test js-test-5"></div>
                        </div>
                        <div class="js-balise-de-test js-test-6"></div>
                    </section>
                

Code JS :


                    // Sélectionner toutes les balises ayant la classe "js-balise-de-test"
                    // présentes dans la balise dont l'id vaut "zone-02".
                    // Le sélecteur ne tient pas compte du niveau d'imbrication.
                    const balisesDeTestZone02Elements = document.querySelectorAll('#zone-02 .js-balise-de-test');

                    console.log(balisesDeTestZone02Elements);
                    /* 
                        Affiche : 
                            NodeList(3) [ 
                                div.js-balise-de-test.js-test-4, 
                                div.js-balise-de-test.js-test-5, 
                                div.js-balise-de-test.js-test-6 
                            ]
                    */
                

Dans cet exemple, toutes les balises possédant la classe js-balise-de-test et situées dans la section zone-02 sont sélectionnées, qu'elles soient des enfants directs ou imbriquées plus profondément.

Limiter aux enfants directs avec >

Le chevron fermant > correspond au sélecteur d'enfant direct. Il permet de cibler uniquement les éléments qui se trouvent immédiatement sous le parent.

Dans l'exemple suivant, #zone-02 > .js-balise-de-test sélectionne uniquement les balises de test qui sont des enfants directs de #zone-02. La balise imbriquée plus profondément n'est pas sélectionnée.

Code HTML :


                    <section id="zone-02">
                        <h2>Zone 02</h2>
                        <div class="js-balise-de-test js-test-4">
                            <div class="js-balise-de-test js-test-5"></div>
                        </div>
                        <div class="js-balise-de-test js-test-6"></div>
                    </section>
                

Code JS :


                    // Sélectionner toutes les balises ayant la classe "js-balise-de-test"
                    // étant les enfants directs de l'élément dont l'id vaut "zone-02".
                    const balisesDeTestDirectesZone02Elements = document.querySelectorAll('#zone-02 > .js-balise-de-test');

                    console.log(balisesDeTestDirectesZone02Elements);
                    /* 
                        Affiche : 
                            NodeList(2) [ 
                                div.js-balise-de-test.js-test-4, 
                                div.js-balise-de-test.js-test-6 
                            ]
                    */
                

La différence est importante. Le sélecteur descendant avec un espace inclut tous les niveaux, tandis que le sélecteur avec > se limite aux enfants directs.

Limiter la recherche à une zone du DOM

Pour éviter de chercher dans toute la page, on commence par sélectionner un conteneur, puis on effectue plusieurs sélections à partir de cette référence. Cela clarifie l'intention et limite les risques de collisions.

Code HTML :


                    <section id="zone-02">
                        <h2>Zone 02</h2>
                        <div class="js-balise-de-test js-test-4">
                            <div class="js-balise-de-test js-test-5"></div>
                        </div>
                        <div class="js-balise-de-test js-test-6"></div>
                    </section>
                

Code JS :


                    // Sélectionner la zone où travailler.
                    const zone02Elem = document.querySelector('#zone-02');

                    // Les éléments que l'on désire cibler sont tous des enfants de la référence stockée dans "zone02Elem",
                    // plutôt que d'utiliser la méthode sur l'objet "document", on peut alors limiter sa zone de recherche
                    // en le plaçant sur cette même référence.
                    const titreElem = zone02Elem.querySelector('h2');
                    const balisesDeTestElements = zone02Elem.querySelectorAll('.js-balise-de-test');

                    console.log(titreElem); // Affiche : <h2>Zone 02</h2>
                    console.log(balisesDeTestElements);
                    /* 
                        Affiche : 
                            NodeList(3) [ 
                                div.js-balise-de-test.test-4, 
                                div.js-balise-de-test.test-5, 
                                div.js-balise-de-test.test-6 
                            ]
                    */
                

Le pseudo-sélecteur :scope

Le pseudo-sélecteur :scope permet de désigner explicitement l'élément à partir duquel un sélecteur CSS doit être évalué. En pratique, il n'est utile que dans des situations bien précises.

Lorsqu'on utilise querySelector() ou querySelectorAll() sur un élément du DOM, la recherche est déjà limitée à son sous-arbre. Dans la majorité des cas, :scope n'apporte donc aucun avantage supplémentaire.

Le principal intérêt de :scope apparaît lorsqu'on souhaite utiliser le sélecteur d'enfant direct > à partir d'un élément déjà sélectionné.

Problème sans :scope

Le sélecteur d'enfant direct > doit toujours être interprété par rapport à un élément précis. Utilisé seul dans querySelectorAll(), il est ambigu et donc invalide.

Code HTML :


                    <section id="zone-02">
                        <h2>Zone 02</h2>
                        <div class="js-balise-de-test js-test-4">
                            <div class="js-balise-de-test js-test-5"></div>
                        </div>
                        <div class="js-balise-de-test js-test-6"></div>
                    </section>
                

Code JS :


                    // Sélectionner une zone du DOM.
                    const zone02Elem = document.querySelector('#zone-02');

                    // Tentative incorrecte de sélection des enfants directs.
                    zone02Elem.querySelectorAll('> .js-balise-de-test'); 
                    /* 
                        Affiche : 
                            Uncaught DOMException: Element.querySelectorAll: '> .js-balise-de-test' is not a valid selector
                    */
                

Dans cet exemple, le navigateur ne sait pas à quel élément le chevron doit se rapporter.

Solution avec :scope

En utilisant :scope, on indique explicitement que le point de départ du sélecteur est l'élément sur lequel la méthode est appelée.

Code JS :


                    // Sélectionner une zone du DOM.
                    const zone02Elem = document.querySelector('#zone-02');

                    // Sélectionner uniquement les enfants directs de la zone.
                    const balisesDeTestDirectesElements = zone02Elem.querySelectorAll(':scope > .js-balise-de-test');
                

Ici, :scope représente l'élément stocké dans zone02Elem. Le sélecteur :scope > .js-balise-de-test permet donc de cibler uniquement ses enfants directs, sans inclure les éléments imbriqués plus profondément.

Sélectionner un parent du DOM avec closest()

Jusqu'ici, la sélection consiste surtout à chercher vers le bas en partant de document ou d'un conteneur avec querySelector() et querySelectorAll().

Dans certaines situations, on fait l'inverse. On part d'un élément déjà connu, souvent celui qui a été cliqué, puis on cherche son parent pertinent. C'est exactement le rôle de closest().

La méthode closest() prend un sélecteur CSS et remonte dans le DOM jusqu'à trouver le premier ancêtre qui correspond. Si l'élément lui-même correspond au sélecteur, il est renvoyé directement. Si aucun ancêtre ne correspond, le résultat est null.

Exemple

Dans l'exemple suivant, un bouton "Favori" se trouve à l'intérieur d'une carte produit. À partir du bouton, on utilise closest() pour retrouver la carte parente (celle qui possède la classe js-carte).

Code HTML :


                    <div class="carte js-carte">
                        <h3>Produit A</h3>
                        <button class="js-btn-favori">
                            <span>★</span> Favori
                        </button>
                    </div>
                

Code JS :


                    // On part d'un élément précis, ici un bouton.
                    const btnFavoriElem = document.querySelector('.js-btn-favori');

                    // On remonte vers la "carte" qui contient ce bouton.
                    const carteElem = btnFavoriElem.closest('.js-carte');

                    console.log(carteElem); // Affiche : <div class="carte js-carte">...</div>
                

L'intérêt est de pouvoir retrouver rapidement le bloc parent cohérent sans construire un sélecteur CSS long et fragile. On exprime l'intention de manière claire. Partir d'un élément, puis retrouver le composant auquel il appartient.

Sélectionner par attribut HTML

Pour id et class, CSS propose une forme abrégée (# et .). Pour les autres attributs, on utilise un sélecteur d'attribut avec le nom de l'attribut entre crochets [ ... ].

Ce principe fonctionne avec des attributs standards (href, type, required, disabled, aria-...) et avec des attributs personnalisés data-....

Exemple avec un attribut standard sans valeur

Pour cibler toutes les balises qui possèdent l'attribut type, utiliser le sélecteur CSS [type].

Code HTML :


                    <form>
                        <input type="email" required>
                        <input type="password">
                        <input type="text">
                    </form>
                

Code JS :


                    // Sélectionner toutes les balises qui possèdent un attribut HTML "type".
                    const champsAvecTypeElements = document.querySelectorAll('[type]');

                    console.log(champsAvecTypeElements); // Affiche : NodeList(3) [ input, input, input ]
                

Exemple avec un attribut standard avec valeur

Pour cibler la première balise dont l'attribut type vaut password, utiliser le sélecteur CSS [type="password"].

Code HTML :


                    <form>
                        <input type="email" required>
                        <input type="password">
                    </form>
                

Code JS :


                    // Sélectionner le champ dont l'attribut type vaut "password".
                    const passwordElem = document.querySelector('[type="password"]');

                    console.log(passwordElem); // Affiche : <input type="password">
                

Les opérateurs sur les attributs

Un sélecteur d'attribut peut être plus souple qu'une égalité stricte. CSS propose plusieurs opérateurs pour décrire une correspondance partielle.

  • [attr="valeur"] correspondance exacte
  • [attr^="valeur"] commence par
  • [attr$="valeur"] se termine par
  • [attr*="valeur"] contient

Code HTML :


                    <nav class="ressources">
                        <a href="/cours/javascript-dom">DOM</a>
                        <a href="/cours/css-selecteurs">Sélecteurs CSS</a>
                        <a href="/docs/guide-dom.pdf">Guide PDF</a>
                        <a href="https://developer.mozilla.org/">MDN</a>
                    </nav>
                

Code JS :


                    // Sélectionner tous les liens dont le href commence par "https://"
                    const liensExternes = document.querySelectorAll('a[href^="https://"]');
                    console.log(liensExternes.length); // 1

                    // Sélectionner tous les liens dont le href se termine par ".pdf"
                    const liensPdf = document.querySelectorAll('a[href$=".pdf"]');
                    console.log(liensPdf.length); // 1

                    // Sélectionner tous les liens dont le href contient le mot "cours"
                    const liensCours = document.querySelectorAll('a[href*="cours"]');
                    console.log(liensCours.length); // 2
                

L'opérateur *= signifie "contient". Ce n'est pas un joker général, c'est un test de sous-chaîne appliqué à la valeur de l'attribut.

Sélectionner selon la position avec :nth-child()

Les pseudo-classes :nth-child() et :nth-last-child() permettent de sélectionner des éléments selon leur position parmi les enfants d'un même parent. Le comptage commence à 1, pas à 0.

Sélectionner au début avec :nth-child()

Pour cibler un élément en début de liste, on peut utiliser :nth-child(1) pour le premier élément, ou :nth-child(2) pour le deuxième.

Code HTML :


                    <ul class="js-liste">
                        <li>Élément 1</li>
                        <li>Élément 2</li>
                        <li>Élément 3</li>
                        <li>Élément 4</li>
                        <li>Élément 5</li>
                    </ul>
                

Code JS :


                    // Sélectionner le premier élément de la liste.
                    const premierElem = document.querySelector('.js-liste li:nth-child(1)');
                    console.log(premierElem.textContent); // "Élément 1"

                    // Sélectionner le deuxième élément de la liste.
                    const deuxiemeElem = document.querySelector('.js-liste li:nth-child(2)');
                    console.log(deuxiemeElem.textContent); // "Élément 2"
                

Sélectionner à partir de la fin avec :nth-last-child()

:nth-last-child() fonctionne comme :nth-child(), mais en comptant depuis la fin. :nth-last-child(1) cible le dernier, :nth-last-child(2) cible l'avant-dernier.

Code HTML :


                    <ul class="js-liste">
                        <li>Élément 1</li>
                        <li>Élément 2</li>
                        <li>Élément 3</li>
                        <li>Élément 4</li>
                        <li>Élément 5</li>
                    </ul>
                

Code JS :


                    // Sélectionner le dernier élément.
                    const dernierElem = document.querySelector('.js-liste li:nth-last-child(1)');
                    console.log(dernierElem.textContent); // "Élément 5"

                    // Sélectionner le troisième élément en partant de la fin.
                    const troisiemeDepuisLaFinElem = document.querySelector('.js-liste li:nth-last-child(3)');
                    console.log(troisiemeDepuisLaFinElem.textContent); // "Élément 3"
                

Sélectionner un élément sur deux, pairs, impairs

:nth-child() accepte aussi des mots-clés et des formules. Cela permet de sélectionner un élément sur deux, uniquement les pairs, ou uniquement les impairs.

Code HTML :


                    <ul class="js-liste">
                        <li>Élément 1</li>
                        <li>Élément 2</li>
                        <li>Élément 3</li>
                        <li>Élément 4</li>
                        <li>Élément 5</li>
                        <li>Élément 6</li>
                    </ul>
                

Code JS :


                    // Sélectionner les éléments de position impaire 1, 3, 5...
                    const impairsElements = document.querySelectorAll('.js-liste li:nth-child(odd)');

                    // Sélectionner les éléments de position paire 2, 4, 6...
                    const pairsElements = document.querySelectorAll('.js-liste li:nth-child(even)');

                    console.log(impairsElements.length); // 3
                    console.log(pairsElements.length);   // 3

                    // Variante équivalente avec une formule.
                    const unSurDeuxElements = document.querySelectorAll('.js-liste li:nth-child(2n)');
                    console.log(unSurDeuxElements.length); // 3
                

Formules utiles à retenir

Les formules suivent le modèle an + b. n représente une suite de valeurs 0, 1, 2, 3... et le résultat donne les positions ciblées.

  • :nth-child(1) cible le premier enfant
  • :nth-last-child(1) cible le dernier enfant
  • :nth-child(odd) cible 1, 3, 5...
  • :nth-child(even) cible 2, 4, 6...
  • :nth-child(2n) cible 2, 4, 6...
  • :nth-child(2n + 1) cible 1, 3, 5...

:nth-child() se base sur la position réelle parmi les enfants du parent. Si d'autres balises sont présentes au même niveau, le résultat peut surprendre. Dans ce cas, préciser le contexte dans le sélecteur, par exemple .js-liste li:nth-child(...), aide à garder une intention claire.

Exclure des éléments de la sélection avec :not()

Certaines pseudo-classes CSS permettent de cibler des éléments selon une règle simple. Elles sont utiles lorsqu'on veut inclure ou exclure un sous-ensemble d'éléments sans ajouter de nouvelles classes dans le HTML.

Exclure des éléments avec :not()

La pseudo-classe :not() permet d'exclure les éléments qui correspondent à un sélecteur. Dans l'exemple suivant, on cible les éléments du menu qui ne possèdent pas la classe actif.

Code HTML :


                    <ul class="js-menu">
                        <li class="actif">Accueil</li>
                        <li>Cours</li>
                        <li>Contact</li>
                    </ul>
                

Code JS :


                    // Sélectionner l'élément actif.
                    const itemActifElem = document.querySelector('.js-menu > li.actif');

                    // Sélectionner tous les éléments qui ne sont pas actifs.
                    const itemsNonActifsElements = document.querySelectorAll('.js-menu > li:not(.actif)');

                    console.log(itemActifElem); // Affiche : <li class="actif">Accueil</li>
                    console.log(itemsNonActifsElements);  // Affiche : NodeList(2) [ li, li ]
                

:not() permet de cibler rapidement un groupe d'éléments sans modifier la structure du HTML. Cette approche est utile tant que la règle d'exclusion reste simple et lisible.

Bonnes pratiques

Une sélection devient plus fiable et plus lisible en adoptant quelques habitudes. Éviter de répéter la même sélection à plusieurs endroits, stocker la référence, utiliser un nom explicite, et vérifier les retours quand l'élément peut être absent.

Vérifier la sélection avant manipulation

Une sélection peut échouer. Avec querySelector(), la valeur retournée est null lorsqu'aucun élément ne correspond au sélecteur fourni. Avant de manipuler l'élément sélectionné, il est donc préférable de vérifier que la sélection a réussi.

Sans cette vérification, une opération sur null provoque une erreur dans la console et le script peut s'arrêter à cet endroit. Ce test permet d'obtenir un message clair, et d'identifier rapidement un sélecteur incorrect ou un élément absent du DOM au moment où le script s'exécute.

Code JS avec vérification :


                    // Sélectionner l'élément dont l'id vaut "conteneur".
                    const conteneurElem = document.querySelector('#conteneur');

                    // Vérifier la validité de la sélection.
                    if (conteneurElem)
                    {
                        // La sélection a réussi.
                        // On peut maintenant manipuler l'élément via "conteneurElem"
                        // ...
                    }
                    else
                    {
                        // La sélection a échoué, message utile pour le débogage.
                        console.error('Aucun élément ne correspond au sélecteur "#conteneur".');
                    }
                

Lorsque le site est en ligne, il est courant de conserver une vérification simple lorsque l'élément peut être absent. Les messages de débogage peuvent être retirés pour éviter de polluer la console.

Code JS avec vérification minimale :


                    // Sélectionner l'élément dont l'id vaut "conteneur".
                    const conteneurElem = document.querySelector('#conteneur');

                    if (conteneurElem)
                    {
                        // La sélection a réussi.
                        // On peut maintenant manipuler l'élément via "conteneurElem"
                        // ...
                    }
                

Lorsque le code se trouve dans une fonction, un return permet d'interrompre proprement l'exécution si l'élément est absent.

Code JS dans une fonction avec return :


                    function initialiserConteneur()
                    {
                        const conteneurElem = document.querySelector('#conteneur');

                        if (!conteneurElem)
                        {
                            return;
                        }

                        // La sélection a réussi.
                        // On peut maintenant manipuler l'élément via "conteneurElem"
                        // ...
                    }
                

Exercices

Le travail se fait dans app.js. Tous les résultats se vérifient dans la console en affichant les éléments avec console.log(element), puis en passant la souris sur le résultat afin de voir le surlignage sur la page.

Exo-selecteurs-dom-serie-01

Structure

Créer un dossier nommé Exo-selecteurs-dom-serie-01, puis y organiser les fichiers et dossiers en respectant l'arborescence suivante :


                    Exo-selecteurs-dom-serie-01/
                    |-- index.html
                    └── js/
                        |-- app.js
                        └── modules/
                            |-- exo01.js
                            |-- exo02.js
                            |-- exo03.js
                            |-- exo04.js
                            |-- exo05.js
                            |-- exo06.js
                            |-- exo07.js
                            |-- exo08.js
                            |-- exo09.js
                            └── exo10.js
                

Copier le gabarit HTML suivant dans le fichier index.html situé à la racine du projet :


                    <!doctype html>
                    <html lang="fr">
                    <head>
                        <meta charset="utf-8">
                        <meta name="viewport" content="width=device-width, initial-scale=1">
                        <title>JS: Exo Sélecteurs DOM Série 01</title>
                    </head>
                    <body>
                        <h1>JS: Exo Sélecteurs DOM Série 01</h1>

                        <main id="page">
                            <section id="zone-principale" class="js-bloc-info">
                                <h2>Zone principale</h2>
                                <p class="js-texte-intro">Intro A</p>
                                <div class="js-outro-conteneur">
                                    <p>Outro A</p>
                                </div>
                            </section>

                            <section id="zone-secondaire" class="js-bloc-info">
                                <h2>Zone secondaire</h2>
                                <p class="js-texte-intro">Intro B (enfant direct de zone secondaire)</p>
                                <div class="js-outro-conteneur">
                                    <p>Outro B (enfant indirect de zone secondaire)</p>
                                </div>
                            </section>

                            <aside id="panneau" class="js-bloc-aside">
                                <h2>Panneau</h2>
                                <p>Texte du panneau</p>
                            </aside>
                        </main>

                        <script src="./js/app.js" type="module"></script>
                    </body>
                    </html>
                

Ouvrir la page via le navigateur (via un serveur local, car les modules l'exigent), puis ouvrir la console :

Exo 01

Objectif : Sélection par ID (querySelector).

  • Se rendre dans le fichier js/modules/exo01.js.
  • Créer une fonction exportée (export nommé) appelée execExo01.
  • Dans app.js, importer execExo01 depuis ./modules/exo01.js, puis appeler execExo01().
  • À l'intérieur de la fonction execExo01 :
    1. Dans la fonction, afficher ----- Exo 01 ----- dans la console.
    2. Sélectionner l'élément dont l'attribut id vaut zone-principale avec la méthode querySelector(), puis stocker la référence dans une constante nommée zonePrincipaleElem1.
    3. Afficher la référence dans la console, puis la survoler avec le curseur afin de vérifier que l'élément surligné dans la page correspond bien à l'élément attendu.

Exo 02

Objectif : Sélection par ID (getElementById).

  • Se rendre dans le fichier js/modules/exo02.js.
  • Créer et exporter une fonction fléchée nommée execExo02.
  • Dans app.js, importer execExo02 depuis ./modules/exo02.js, puis appeler execExo02().
  • À l'intérieur de la fonction execExo02 :
    1. Dans la fonction, afficher ----- Exo 02 ----- dans la console.
    2. Sélectionner le même élément dont l'attribut id vaut zone-principale, mais cette fois-ci avec la méthode getElementById(), puis stocker la référence dans une constante nommée zonePrincipaleElem2.
    3. Afficher la référence dans la console, puis la survoler avec le curseur afin de vérifier que l'élément surligné dans la page correspond bien à l'élément attendu.

Exo 03

Objectif : Sélection par Classe.

  • Se rendre dans le fichier js/modules/exo03.js.
  • Créer et exporter une fonction fléchée nommée execExo03.
  • Dans app.js, importer execExo03 depuis ./modules/exo03.js, puis appeler execExo03().
  • À l'intérieur de la fonction execExo03 :
    1. Dans la fonction, afficher ----- Exo 03 ----- dans la console.
    2. Sélectionner l'élément ayant la classe CSS js-bloc-aside avec la méthode querySelector(), puis stocker la référence dans une constante nommée blocAsideElem.
    3. Afficher la référence dans la console, puis la survoler avec le curseur afin de vérifier que l'élément surligné dans la page correspond bien à l'élément attendu.

Exo 04

Objectif : Sélection unique d'un élément partagé.

  • Se rendre dans le fichier js/modules/exo04.js.
  • Créer et exporter une fonction fléchée nommée execExo04.
  • Dans app.js, importer execExo04 depuis ./modules/exo04.js, puis appeler execExo04().
  • À l'intérieur de la fonction execExo04 :
    1. Dans la fonction, afficher ----- Exo 04 ----- dans la console.
    2. Sélectionner un élément ayant la classe CSS js-bloc-info avec la méthode querySelector(), puis stocker la référence dans une constante nommée blocInfosElem.
    3. Afficher la référence dans la console, puis la survoler avec le curseur afin de vérifier que l'élément surligné dans la page correspond bien à l'élément attendu.
      Bien que deux éléments de la page possèdent la classe CSS js-bloc-info, la méthode querySelector() ne renvoie qu'un seul élément. Seul le premier élément correspondant dans l'ordre du document est donc sélectionné.

Exo 05

Objectif : Sélection multiple (NodeList).

  • Se rendre dans le fichier js/modules/exo05.js.
  • Créer et exporter une fonction fléchée nommée execExo05.
  • Dans app.js, importer execExo05 depuis ./modules/exo05.js, puis appeler execExo05().
  • À l'intérieur de la fonction execExo05 :
    1. Dans la fonction, afficher ----- Exo 05 ----- dans la console.
    2. Sélectionner tous les éléments ayant la classe CSS js-bloc-info avec la méthode querySelectorAll(), puis stocker la collection retournée dans une constante nommée blocInfosElements.
    3. Afficher la collection blocInfosElements dans la console afin de vérifier qu'il s'agit d'un NodeList.
    4. Afficher ensuite la propriété length afin de vérifier le nombre d'éléments trouvés.
    5. Survoler la collection et ses éléments dans la console afin de vérifier que le surlignage correspond bien à toutes les sections attendues.

Exo 06

Objectif : Parcours d'une collection.

  • Se rendre dans le fichier js/modules/exo06.js.
  • Créer et exporter une fonction fléchée nommée execExo06.
  • Dans app.js, importer execExo06 depuis ./modules/exo06.js, puis appeler execExo06().
  • À l'intérieur de la fonction execExo06 :
    1. Dans la fonction, afficher ----- Exo 06 ----- dans la console.
    2. Il faut d'abord récupérer la collection d'éléments comme à l'étape précédente : Sélectionner tous les éléments ayant la classe CSS js-bloc-info avec la méthode querySelectorAll() et stocker dans blocInfosElements.
    3. Parcourir le NodeList obtenu avec une boucle for...of.
    4. À chaque tour de boucle, afficher l'élément courant dans la console. Survoler plusieurs résultats afin de vérifier que chaque section portant la classe js-bloc-info est bien parcourue et surlignée à l'écran.

Exo 07

Objectif : Sélection multiple par balise.

  • Se rendre dans le fichier js/modules/exo07.js.
  • Créer et exporter une fonction fléchée nommée execExo07.
  • Dans app.js, importer execExo07 depuis ./modules/exo07.js, puis appeler execExo07().
  • À l'intérieur de la fonction execExo07 :
    1. Dans la fonction, afficher ----- Exo 07 ----- dans la console.
    2. Sélectionner toutes les balises p de la page avec la méthode querySelectorAll(), puis stocker le NodeList retourné dans une constante nommée pElements.
    3. Afficher la collection pElements dans la console afin de vérifier qu'il s'agit bien d'un NodeList.
    4. Survoler la collection et ses éléments dans la console afin de vérifier que le surlignage correspond bien à toutes les balises p attendues.

Exo 08

Objectif : Sélecteur composé.

  • Se rendre dans le fichier js/modules/exo08.js.
  • Créer et exporter une fonction fléchée nommée execExo08.
  • Dans app.js, importer execExo08 depuis ./modules/exo08.js, puis appeler execExo08().
  • À l'intérieur de la fonction execExo08 :
    1. Dans la fonction, afficher ----- Exo 08 ----- dans la console.
    2. Sélectionner le paragraphe d'introduction de la zone principale en utilisant querySelector().
      Construire un sélecteur CSS composé qui exprime le chemin suivant :
      • Commencer par la balise main.
      • Depuis cette balise main, cibler son enfant direct (signe >) avec la balise section dont l'id vaut zone-principale.
      • Depuis cette balise section, cibler son enfant direct (signe >) avec la balise p ayant la classe CSS js-texte-intro.
      Stocker la référence dans une constante nommée introZonePrincipaleElem.
    3. Afficher la référence dans la console, puis la survoler avec le curseur afin de vérifier que seul le paragraphe "Intro A" est surligné.

Exo 09

Objectif : Recherche dans un sous-élément (querySelector).

  • Se rendre dans le fichier js/modules/exo09.js.
  • Créer et exporter une fonction fléchée nommée execExo09.
  • Dans app.js, importer execExo09 depuis ./modules/exo09.js, puis appeler execExo09().
  • À l'intérieur de la fonction execExo09 :
    1. Dans la fonction, afficher ----- Exo 09 ----- dans la console.
    2. Sélectionner l'élément dont l'attribut id vaut zone-principale avec la méthode querySelector(), puis stocker la référence dans une constante nommée zonePrincipaleElem.
    3. À partir de la référence zonePrincipaleElem (et non plus à partir de document), sélectionner toutes les balises p situées dans cette zone en utilisant la méthode querySelectorAll(), puis stocker le NodeList retourné dans une constante nommée zonePrincipalePElements.
    4. Afficher la collection zonePrincipalePElements dans la console, puis la survoler avec le curseur afin de vérifier que seuls les paragraphes de la zone principale sont surlignés.

Exo 10

Objectif : Recherche ciblée et enfants directs.

  • Se rendre dans le fichier js/modules/exo10.js.
  • Créer et exporter une fonction fléchée nommée execExo10.
  • Dans app.js, importer execExo10 depuis ./modules/exo10.js, puis appeler execExo10().
  • À l'intérieur de la fonction execExo10 :
    1. Dans la fonction, afficher ----- Exo 10 ----- dans la console.
    2. Sélectionner l'élément dont l'attribut id vaut zone-secondaire avec la méthode querySelector(), puis stocker la référence dans une constante nommée zoneSecondaireElem.
    3. À partir de la référence zoneSecondaireElem (et non plus à partir de document), sélectionner uniquement les balises p qui sont des enfants directs de cette zone en utilisant la méthode querySelectorAll(). Le sélecteur CSS doit exprimer une relation d'enfant direct. Stocker le NodeList retourné dans une constante nommée zoneSecondaireDirectPElements.
    4. Afficher la collection zoneSecondaireDirectPElements dans la console, puis la survoler avec le curseur afin de vérifier que seul le paragraphe directement contenu dans zone-secondaire est surligné.

Exo-selecteurs-dom-serie-02

Structure

Créer un dossier nommé Exo-selecteurs-dom-serie-02, puis y organiser les fichiers et dossiers en respectant l'arborescence suivante :


                    Exo-selecteurs-dom-serie-02/
                    |-- index.html
                    |-- css/
                    |   └── style.css
                    └── js/
                        |-- app.js
                        └── modules/
                            |-- exo11.js
                            |-- exo12.js
                            |-- exo13.js
                            |-- exo14.js
                            |-- exo15.js
                            |-- exo16.js
                            |-- exo17.js
                            |-- exo18.js
                            |-- exo19.js
                            |-- exo20.js
                            |-- exo21.js
                            └── exo22.js
                

Copier le gabarit HTML suivant dans index.html :


                    <!doctype html>
                    <html lang="fr">
                    <head>
                        <meta charset="utf-8">
                        <meta name="viewport" content="width=device-width, initial-scale=1">
                        <link rel="stylesheet" href="./css/style.css">
                        <title>JS: Exo Sélecteurs DOM Série 02</title>
                    </head>
                    <body>
                        <h1>JS: Exo Sélecteurs DOM Série 02</h1>
                        <main id="page">
                            <form id="form-inscription">
                                <div class="field-group js-group-pseudo">
                                    <label for="user_pseudo">Pseudo</label>
                                    <input id="user_pseudo" type="text" name="user_pseudo" required>
                                </div>
                                <div class="field-group js-group-city">
                                    <label for="user_city">Ville</label>
                                    <input id="user_city" type="text" name="user_city">
                                </div>
                                <div class="field-group js-group-email">
                                    <label for="user_email">Email</label>
                                    <input id="user_email" type="email" name="user_email" required>
                                </div>
                                <div class="field-group js-group-password">
                                    <label for="user_password">Mot de passe</label>
                                    <input id="user_password" type="password" name="user_password" required>
                                </div>
                                <div class="field-group field-group--inline js-group-terms">
                                    <input id="conditions_terms" type="checkbox" name="conditions_terms" required>
                                    <label for="conditions_terms">J'accepte les conditions d'utilisation</label>
                                </div>
                                <div class="field-group field-group--inline js-group-privacy">
                                    <input id="privacy_terms" type="checkbox" name="privacy_terms" required>
                                    <label for="privacy_terms">J'accepte la politique de confidentialité</label>
                                </div>
                                <div class="field-group js-submit-box">
                                    <button type="submit" type="module">s'inscrire</button>
                                </div>
                            </form>
                        </main>
                        <script src="./js/app.js"></script>
                    </body>
                    </html>
                

Copier la feuille de style suivante dans style.css :


                    form {
                        max-width: 300px;
                        width: 100%;
                    }
                    .field-group {
                        display: flex;
                        flex-direction: column;
                        gap: 0.2rem;
                        margin-bottom: 0.6rem;
                    }

                    .field-group--inline {
                        flex-direction: row;
                        align-items: center;
                        gap: 10px;
                    }
                

Ouvrir la page via le navigateur (serveur local), puis ouvrir la console.

Exo 11

Objectif : Sélection par ID.

  • Se rendre dans le fichier js/modules/exo11.js.
  • Créer et exporter une fonction fléchée nommée execExo11.
  • Dans app.js, importer execExo11 depuis ./modules/exo11.js, puis appeler execExo11().
  • À l'intérieur de la fonction execExo11 :
    1. Dans la fonction, afficher ----- Exo 11 ----- dans la console.
    2. Sélectionner le formulaire #form-inscription avec querySelector() et le stocker dans formElem.
    3. Afficher la référence dans la console et vérifier le surlignage.

Exo 12

Objectif : Sélecteur d'attribut simple.

  • Se rendre dans js/modules/exo12.js.
  • Créer et exporter execExo12.
  • Dans app.js, importer execExo12 depuis ./modules/exo12.js, puis appeler execExo12().
  • À l'intérieur de la fonction execExo12 :
    1. Dans la fonction, afficher ----- Exo 12 ----- dans la console.
    2. Sélectionner dans le formulaire tous les éléments possédant l'attribut required avec querySelectorAll().
    3. Stocker le résultat dans champsRequiredElements.
    4. Afficher la collection et sa propriété length.

Exo 13

Objectif : Sélecteur d'attribut avec valeur.

  • Se rendre dans js/modules/exo13.js.
  • Créer et exporter execExo13.
  • Dans app.js, importer execExo13 depuis ./modules/exo13.js, puis appeler execExo13().
  • À l'intérieur de la fonction execExo13() :
    1. Afficher "----- Exo 13 -----".
    2. Sélectionner tous les input dont le type vaut exactement text.
    3. Stocker dans champsTexteElements, afficher et vérifier.

Exo 14

Objectif : Attribut "Commence par" (^).

  • Se rendre dans js/modules/exo14.js.
  • Créer et exporter execExo14.
  • Dans app.js, importer execExo14 depuis ./modules/exo14.js, puis appeler execExo14().
  • À l'intérieur de la fonction execExo14() :
    1. Afficher "----- Exo 14 -----".
    2. Sélectionner tous les input dont l'attribut name commence par la chaîne user_ (Sélecteur ^=).
    3. Stocker dans champsUserElements, afficher et vérifier.

Exo 15

Objectif : Attribut "Se termine par" ($).

  • Se rendre dans js/modules/exo15.js.
  • Créer et exporter execExo15.
  • Dans app.js, importer execExo15 depuis ./modules/exo15.js, puis appeler execExo15().
  • À l'intérieur de la fonction execExo15() :
    1. Afficher "----- Exo 15 -----".
    2. Sélectionner tous les input dont l'attribut name se termine par la chaîne _terms (Sélecteur $=).
    3. Stocker dans champsTermsElements, afficher et vérifier.

Exo 16

Objectif : Attribut "Contient" (*).

  • Se rendre dans js/modules/exo16.js.
  • Créer et exporter execExo16.
  • Dans app.js, importer execExo16 depuis ./modules/exo16.js, puis appeler execExo16().
  • À l'intérieur de la fonction execExo16() :
    1. Afficher "----- Exo 16 -----".
    2. Sélectionner toutes les div dont la classe contient le mot group (Sélecteur *=).
    3. Stocker dans groupesChampsElements.
    4. Afficher et vérifier (le bouton ne doit pas être sélectionné).

Exo 17

Objectif : Négation (:not).

  • Se rendre dans js/modules/exo17.js.
  • Créer et exporter execExo17.
  • Dans app.js, importer execExo17 depuis ./modules/exo17.js, puis appeler execExo17().
  • À l'intérieur de la fonction execExo17() :
    1. Afficher "----- Exo 17 -----".
    2. Sélectionner tous les éléments obligatoires (required) en excluant ceux dont le type est password (utiliser :not()).
    3. Stocker dans champsRequiredHorsMdpElements, afficher et vérifier.

Exo 18

Objectif : Les premiers éléments (:nth-child).

  • Se rendre dans js/modules/exo18.js.
  • Créer et exporter execExo18.
  • Dans app.js, importer execExo18 depuis ./modules/exo18.js, puis appeler execExo18().
  • À l'intérieur de la fonction execExo18() :
    1. Afficher "----- Exo 18 -----".
    2. Sélectionner les deux premiers groupes (div enfants directs du form) avec :nth-child().
    3. Stocker dans deuxPremiersGroupesElements.
    4. Afficher et vérifier (Pseudo et Ville).

Exo 19

Objectif : Les derniers éléments (:nth-last-child).

  • Se rendre dans js/modules/exo19.js.
  • Créer et exporter execExo19.
  • Dans app.js, importer execExo19 depuis ./modules/exo19.js, puis appeler execExo19().
  • À l'intérieur de la fonction execExo19() :
    1. Afficher "----- Exo 19 -----".
    2. Sélectionner les deux derniers groupes avec :nth-last-child().
    3. Stocker dans deuxDerniersGroupesElements.
    4. Afficher et vérifier (Confidentialité et Bouton).

Exo 20

Objectif : À partir du Xème élément.

  • Se rendre dans js/modules/exo20.js.
  • Créer et exporter execExo20.
  • Dans app.js, importer execExo20 depuis ./modules/exo20.js, puis appeler execExo20().
  • À l'intérieur de la fonction execExo20() :
    1. Afficher "----- Exo 20 -----".
    2. Sélectionner tous les groupes à partir du 3ème avec :nth-child().
    3. Stocker dans aPartirDuTroisiemeElements.
    4. Afficher et vérifier (Pseudo et Ville sont exclus).

Exo 21

Objectif : Tout sauf les derniers.

  • Se rendre dans js/modules/exo21.js.
  • Créer et exporter execExo21.
  • Dans app.js, importer execExo21 depuis ./modules/exo21.js, puis appeler execExo21().
  • À l'intérieur de la fonction execExo21() :
    1. Afficher "----- Exo 21 -----".
    2. Sélectionner tous les groupes sauf les deux derniers en utilisant la logique inverse avec :nth-last-child() (tous ceux à partir du 3ème en partant de la fin).
    3. Stocker dans tousSaufDeuxDerniersElements, afficher et vérifier.

Exo 22

Objectif : Positions paires/impaires.

  • Se rendre dans js/modules/exo22.js.
  • Créer et exporter execExo22.
  • Dans app.js, importer execExo22 depuis ./modules/exo22.js, puis appeler execExo22().
  • À l'intérieur de la fonction execExo22() :
    1. Afficher "----- Exo 22 -----".
    2. Sélectionner uniquement les groupes situés à une position paire avec :nth-child(even).
    3. Stocker dans groupesPairsElements, afficher et vérifier.