Accueil

Traduction

Tutoriel sur JS natif, Vue.js, jQuery.js & Node.js

Tutoriel JavaScript - recherche

L'auteur : Patrick Darcheville

Vous pouvez me contacter via Facebook pour questions & suggestions : Page Facebook relative à mon site

Manipuler le DOM avec JavaScript

Ce chapitre est relativement long mais c'est logique car la modification du DOM est l'une des principales missions assignée à JavaScript. En effet des effets basiques (déplacements, agrandissements, masquage/démasquage, etc.) sont désormais confiées à CSS grâce à toutes les nouveautés de se version 3.

Grâce à un script vous pouvez modifier l'aspect initial d'une page sans rechargement de celle-ci (donc sans requête HTTP).
On dit que l'on "dynamise" la page. On parlait avant de DHTML (dynamic HTML) mais le terme n'est plus à la mode. On dit désormais que l'on modifie le DOM de la page.

le DOM

Le DOM est une interface de programmation qui nous permet de manipuler le code HTML & CSS d’une page web de façon dynamique en utilisant le langage JavaScript.
Le DOM est créé automatiquement lors du chargement d’une page web par le navigateur.
Désormais tous les navigateurs génèrent le même DOM, ce qui n'était pas le cas à l'origine (d'où l'invention du framework jQuery ...)
Donc le code pour manipuler dynamiquement le HTML & CSS est désormais indépendant du navigateur : bel effort de normalisation effectué par le W3C.

On peut donc manipuler désormais le DOM en JS pur (sans recourir à jQuery). C'est ce que nous faisons dans ce chapitre.

Les noeuds du DOM

Tout dans une page web doit être considéré comme un noeud ("node" en anglais).
Le document HTML est un noeud, chaque élément HTML est un noeud, les attributs des balises sont des noeuds, le texte de chaque balise est aussi un noeud.
Sachez aussi qu’il existe plusieurs types de nœuds : le type ELEMENT (pour les balises HTML), le type de nœud TEXTE, etc.

La structure DOM d'une page

Le code d'une page

Le DOM de cette page

Le DOM de cette page va être construit comme une hiérarchie de nœuds. On peut le représenter sous forme d'un arbre.
Sachez que la page HTML est le noeud le plus haut hiérarchiquement et appelé : DOCUMENT.
Toutes les balises doubles ou simples de la page constituent des noeuds de type ELEMENT (ou plus simplement élements).
Ainsi la balise double HTML est un noeud de type ELEMENT.

Le noeud HTML comprend deux "enfants" : HEAD et BODY. Pour ces deux "enfants" HTML est l'élément "parent".
L'élément HEAD contient à son tour deux enfants : TITLE et META. On peut dire aussi que TITLE et META ont pour "parent" HEAD.
L'élément BODY contient quatre enfants : H1 et trois balises P.

La structure DOM d'une page apparait dans l'onglet "éléments" de la console du navigateur.
L'interface DOM va nous permettre de manipuler les éléments du document pour le rendre dynamique.
Dans la suite de ce chapitre nous allons voir comment cibler un élément pour ensuite récupérer voire modifier ses paramètres : contenu, attributs, propriétés de style.

Cibler un noeud de type élément

Avant de manipuler en JavaScript un élément HTML (une balise donc) il faut pouvoir le cibler.
Il existe plusieurs méthodes pour accéder à un élément HTML mais toutes ont un point commun : elles retournent un objet !
Donc la syntaxe générique est : variable = méthode de ciblage d'un élément HTML
Après cette instruction la variable créée n'est pas une variable simple (qui stocke une primitive) mais une variable objet qui référence dans le script un élément HTML du document.

Méthodes de sélection d'un élément

Il faut utiliser le DOM et en particulier les méthodes de l'objet document. Il faut distinguer les anciennes méthodes et les nouvelles introduites par HTML 5.

Ces deux nouvelles méthodes ont pour argument un sélecteur CSS.
Attention la première méthode retourne le premier élément répondant au sélecteur CSS passé en paramètre.
La deuxième méthode retourne tous les éléments répondant au sélecteur CSS. Donc dans le cadre de la deuxième méthode il faut parfois rajouter un indice ...

La méthode querySelector()

La méthode querySelectorAll()

Et si vous voulez cibler la troisième balise P de la page et que cet élément n'a ni l'attribut ID ni l'attribut class comment faire ? Il suffit d'écrire : document.querySelectorAll('p')[2] . En effet le premier élément P à l'indice 0 donc le troisième a l'indice 2 !

Thème

Dans une page il y a trois images miniatures et presque transparentes. Si clic sur l'une d'elle, celle-ci s'agrandit et devient opaque.
Voyons comment cibler ces images dans un script avec deux solutions.

Solution ancienne

Utilisation de la méthode getElementById ce qui suppose que chaque élément HTML manipulable soit affecté de l'attribut ID.

Code CSS & HTML :

Notez bien l'attribut ID associé à chaque image.

Le script :

On associe à chaque image une fonction anonyme. Notez l'emploi du mot réservé this.

Solution plus moderne

Utilisons les nouvelles méthodes de ciblage des éléments : querySelector OU querySelectorAll

Le code CSS est inchangé !

Code HTML est simplifié :

Les ID devenus inutiles, disparaissent.

Le script :

Pour cibler le premier élément de type IMG, j'aurais pu écrire : document.querySelectorAll('img')[0]

Le rendu du code dans un Iframe

Le rendu est exactement identique a celui qu'aurait donné la solution traditionnelle.
Le seul intêrêt de la solution moderne est d'avoir un code HTML plus succinct. Mais attention il faut savoir compter. Voir encadré ci-dessous.

Récupérer des informations sur les éléments

Maintenant que vous savez cibler en JS un élément du DOM vous pouvez récupérer toutes les infos possibles sur cet élément.
La récupération d'un paramètre d'un élément est souvent un préalable à sa modification. Un seul exemple : si vous voulez augmenter l'opacité d'une image il faut récupérer la valeur initiale de la propriété opacity puis incrémenter cette valeur.

Un élément se caractérise par un contenu (texte et balisage), des attributs (src, class, alt, title, style, etc.) et des propriétés.

Récupération du contenu d'un élément (texte et balisage)

Code HTML de la page

Aucune trace de JS dans le code HTML !

Le script

titre est une variable objet qui référence la balise H1 de la page.
para quant à elle référence la première (et unique) balise P de la page.
image référence l'image unique de la page.

Pour savoir si l'image dispose de certains attributs j'ai utilisé une instruction basée sur la méthode élément.hasAttribute(). Cette méthode retourne true / false.

Le rendu du code dans un iframe

Observez bien la différence entre les propriétés outerHTML & innerHTML & innerText.

Récupération des valeurs des attributs

Théme : on veut récupérer les valeurs des différents attributs d'un élément IMG.

Le code de la page (extraits)

Le rendu du code :

Pour récupérer les valeurs d'attributs on peut utiliser un syntaxe simplifiée : élément.attribut. Mais je vous déconseille d'utiliser cette syntaxe car elle présente de nombreux pièges ...

Récupération des propriétés de style d'un élément

Dans certains ouvrages on peut lire que pour récupérer une propriété CSS associée à un élément, on peut utiliser la syntaxe : élément.style.propriété

N'utilisez surtout pas cette syntaxe !
En effet ça fonctionne mais à condition que les propriétés de style de l'élément soient "en ligne" (via l'attribut style).
Avec cette syntaxe, il n'est donc pas possible de récupérer une propriété de l'élément définie au niveau d'une feuille de style (interne ou externe).

Le code HTML de l'exemple

Lien vers une feuille de style externe qui formate les balises H1 et définit la classe "centre".
La page ne contient pas de feuille de style interne.
L'attribut STYLE n'est utilisé que pour la balise IMG.
La partie BODY ne comprend que trois balises : H1, IMG et P.

Le script

J'ai utilisé la méthode getComputedStyle(élément).propriété
Les deux éléments HTML sont référencés dans le script via les variables titre & image

Le rendu du code

La méthode getcomputedStyle() retourne les couleurs sous forme de son code RGB.
Beaucoup de valeurs retournées sont exprimées en pixels. Ainsi pour l'image et la propriété "width" la valeur retournée n'est pas 60% mais la largeur en pixels en fonction de la teille de la fenêtre d'affichage.

Attention, pour les noms des propriétés de style, vous devez utiliser la syntaxe JS. En effet en JavaScript le tiret milieu est un opérateur (soustraction) et ne peut être utilisé pour désigner une variable, une propriété, etc.
Donc pour passer du nom CSS de la propriété au nom JS, il suffit de supprimer le tiret et de remplacer la lettre qui suit par son équivalent en majuscule.

Prenons quelques exemples afin que mon propos soit plus clair.

propriéténom CSSnom JS
couleur de fondbackground-colorbackgroundColor
bordure (méga propriété)borderborder
hauteur de ligneline-heightlineHeight
marges externesmarginmargin

On appelle cette technique de nommage : "camelCase".

Modifier les éléments HTML

Vous savez donc désormais récupérer les paramètres d'un élément du DOM (contenu, attributs, propriétés).
Mais pour obtenir des pages dynamiques (qui changent d'aspect sans rechargement de celle-ci) il faut pouvoir modifier les valeurs de ces paramètres !

Modifier le contenu d'un élément

Thème : ma première page dynamique : un clic sur la drapeau tricolore et la page est remplie de texte en français ; un clic sur l'Union Jack et la page est remplie de texte en anglais.

CSS & HTML

Les éléments H2, FIGCAPTION et P sont vides de tout contenu !
C'est l'exécution du script qui va remplir ces balises.

Le script

En cliquant sur le drapeau tricolore on appelle la fonction fran qui remplit chaque élément avec un texte français.
En cliquant sur l'Union Jack on appelle la fonction angl qui remplit chaque élément avec un texte anglais.

Les propriétés innerHTML, innerText (ou textContent) peuvent être utilisées aussi en écriture.
Par contre la propriété outerHTML ne peut s'appliquer qu'en lecture.

Le rendu de ce code dans un Iframe

Modifier les valeurs des attributs

Thème : sur beaucoup de sites et dans le cadre du formulaire de connexion, les caractères que vous saisissez dans un champ "mot de passe" peuvent être affichés en cliquant sur une icône (un oeil). Il suffit qu'un script transforme le type de ce champ : de type "password" à type "text".

Le code HTML

Une image représentant un oeil (facile à trouver sur la toile) est affichée à côté du champ de type "password".
Une légende est associée à l'image : 'afficher le mot de passe'.
Si clic sur cette image : appel d'une fonction.

Le script

Il est d'un simplicité déroutante:

Si le champ "motdepasse" est de type "password" alors il devient de type "text".
Sinon c'est l'inverse.

Le rendu du code :

Supprimer un attribut

Avec la méthode removeAttribute() il est possible de supprimer d'un élément un ou plusieurs attributs.
La syntaxe : élément.removeAttribute('attribut').

Thématique : une page commprend différentes images ; un clic sur une image provoque son effacement par la suppression de l'attribut SRC.

Le code correspondant

Il ne s'agit pas en fait de la suppression d'un élément mais de la suppression de l'attribut SRC : seul attribut indispensable pour une balise IMG.

Le rendu du code

Modifier les propriétés de style

Dans la page et selon que je clique sur le bouton "plus" ou "moins" l'image est plus ou moins opaque et plus ou moins grande.

Le code HTML correspondant

Attention la largeur de l'image est définie via un attribut (et non pas via la propriété CSS).

Le script (extrait)

La largeur de l'image est récupérée selon deux techniques dans les variables vlargeur & vlargeur2.

Le script comprend 3 fonctions anonymes !

La fonction anonyme d'information indique que la largeur de l'image est nativement de type number alors que l'opacité est nativement de type string.

Pour faire varier l'opacité il faut donc faire une conversion avant incrémentation ou décrémentation.
Alors que pour faire varier la taille on peut incrémenter ou décrémenter directement.

Pour faire varier la valeur de l'attribut "width" j'utilise deux techniques.
Alors que pour faire varier la valeur de la propriété "opacity" je ne dispose que d'une seule syntaxe.

Le script ci-dessus est relativement complexe.
La manipulation directe des propriétés de style n'est pas l'approche idéale.
Il serait préférable de jouer sur les classes : ajouter/supprimer une classe, substituer une classe à une autre, etc.
Nous verrons la manipulation des classes plus loin dans ce chapitre.

Le rendu du code :

Modifier le CSS - exercice

Dans une page les images sont par défaut chargées mais masquées.
En cliquant sur un bouton le visiteur les affiche. En cliquant sur un autre bouton le visiteur les masque de nouveau.

Le rendu du code :

Le code CSS & HTML

Grâce au CSS les images chargées sont par défaut masquées : img{display : none ; }
Donc pour les démasquer il faut que pour chaque image la valeur de la propriété display passe à inline !
Il s'agit donc d'un changement de valeur d'une propriété de style pour une collection d'objets.
Il faut donc associer à chaque bouton de commande une fonction qui consiste en une boucle qui traite toute la collection d'images de la page.

Le script - extrait

Je ne vous communique qu'une fonction anonyme sur les deux ; à vous de trouver le code de la seconde.
Vous devez entre autre sélectionner le deuxième bouton de commande (indice de rang 1 dans la collection des boutons).

La structure FOR (... IN ...) est très utile pour traiter toute une collection d'objets.

Ajouter, supprimer des classes

Comme je l'ai déjà fait remarquer, l'usage direct aux propriétés de style n'est pas la solution la plus simple pour mettre en forme les éléments.
Il est préférable de jouer sur les classes : ajout, suppression, substitution,etc.

Le code CSS & HTML d'une page est le suivant :

Notez que la classe "image" est déjà attribuée aux images. C'est elle qui redimensionne et positionne les images.
Nous voulons que le script rajoute la classe "cadre" (bordure + ombrage + coins arrondis) aux différentes images.

L'objet classList

La nouvelle version de JavaScript a ajouté l'objet classList qui comprend plusieurs méthodes pour manipuler les classes.

Le script est donc le suivant :

Le rendu :

Ajouter / supprimer des éléments

Sachez que l'on peut encore aller plus loin dans la modification du DOM via JS. On peut en effet ajouter de nouveaux éléments voire supprimer des éléments existants.
Il faut d'abord créer un élément avec la méthode createElement() puis insérer le nouvel élément dans la page avec la méthode appendChild().
Plutôt que de créer un nouvel élément, il est possible de cloner un élément existant : clonerNode().

Créer puis insérer un nouvel élément

Théme : insertion dans une page d'un lien vers une feuille de style externe puis d'une image et enfin suppression des boutons d'insertion.

Le code correspondant

La page est très moche car il n'y a aucune mise en forme.

Le script

Si clic sur le premier bouton il y a alors insertion d'une balise LINK dans la partie HEAD. Cet élément charge une feuille de style.
Si clic sur deuxième bouton il y a alors insertion dans la boite SECTION d'une belle image.
Dans les deux cas il faut d'abord créer un nouvel élément avec la méthode createElement(type de balise) puis il faut donner des attributs à cet élément et enfin il faut insérer l'élément avec la méthode parent.appendChild(enfant)

Après avoir été cliqué chaque bouton est supprimé via la méthode parent.removeChild(enfant)

Le rendu du code :

Cloner un élément existant puis insérer le clone

Plutôt que de créer un nouvel élément de toute pièce on peut cloner un élément existant.

Le code

Il faut utiliser la méthode cloneNode() puis appendChild()

Le rendu

A chaque fois que vous cliquez sur le bouton de commande il y a duplication de la boite DIV.

Affichez l'onglet "éléments" de la console du navigateur pour observer la modification du DOM.

Suppression d'éléments

Pour supprimer des éléments de la page il existe aussi la méthode élément.remove().
Cette méthode est plus simple à mettre en oeuvre que parent.removeChild(enfant). Nous allons l'expliquer grâce à deux exemples.

Exemple 1

Reprenons le thème : suppression de l'image courante dans une page.
Dans une première solution, nous avions supprimé l'attribut SRC pour effacer l'image mais nous pouvons aussi utiliser la méthode remove().

Le code de la page

Testez ce code !

Actualisez la page pour réafficher les images effacées !

Exemple 2 : suppression par un simple clic de toutes les images de la page

Dans ce deuxième exemple un bouton de commande permet par simple clic de supprimer toutes les images !

Le code de la page

Rendu du code !

Actualisez la page pour réafficher toutes les images !