Accueil

Traduction

Tutoriel JavaScript & jQuery - sommaire

Sommaire partiellement masqué - faites défiler !

Tutoriel JavaScript & jQuery - recherche

L'auteur : Patrick Darcheville

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

Manipuler le DOM avec JavaScript

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.

Via les keyframes (modèles d'animation de CSS 3) il est possible de modifier les valeurs des propriétés CSS des balises mais pas les valeurs des attributs de ces mêmes balises. Donc JavaScript reste alors incontournable.

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.

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.

Des méthodes

L'API DOM ce n'est pas uniquement la représentation de la page sous forme d'une arborescence. Le DOM c'est un ensemble de méthodes et propriétés pour accéder aux noeuds et plus précisément aux

Après avoir référencé un élément HTML il est possible d'accéder à son contenu, récupérer la valeur d'un attribut, récupérer le CSS de l'élément correspondant.
Il est également possible de modifier le contenu de l'élément, modifier la valeur d'un attribut, modifier le CSS élément.
On peut même rajouter des éléments voire supprimer certains éléments !

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 dans un script

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 cible un seul élément (le premier correspondant au sélecteur CSS) alors que la deuxième méthode peut référencer une collection d'éléments sous forme d'un tableau. Donc pour extraire un élément il faut préciser son indice dans le tableau ...

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]
Notez que l'on a utilisé la méthode querySelectorAll() argumentée avec 'p' mais suivie d'un indice.
En effet la méthode querySelectorAll retourne non pas un élément mais une collection d'éléments sous forme d'un tableau. Donc il faut préciser l'indice pour cibler un seul item du tableau.
Ici la valeur de l'indice est 2 (et non pas 3) car le premier élément de la collection a l'indice 0 comme tout tableau JS.

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.

Solution ancienne mais toujours valide

Utilisation de la "bonne vieille" méthode getElementById.

Code CSS & HTML

Il faut obligatoirement ajouter un attribut id à chaque balise img !

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 sélection des éléments : querySelector ou querySelectorAll

Le code CSS inchangé !

Code CSS & HTML

Le code HTML est beaucoup plus simple ; les ID ont disparu.

Le script

Il n'est pas plus long que dans la solution traditionnelle.

Pour cibler la première image j'aurais pu écrire : document.querySelectorAll('img')[0]

Le rendu du code :

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 le DOM

Maintenant que vous savez cibler en JavasScript 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, des attributs (src, class, alt, title, style, etc.) et des propriétés. Nous allons ci-dessous comment récupérer les valeurs de ces différents paramètres en fonction de leur nature (contenu, attributs, propriétés).

Récupération du contenu d'un élément

Le code HTML de la page (extrait)

Le script (sans la balise 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 récupérer le contenu d'un élément on dispose de deux propriétés : innerHTML et textContent.
Attention innerHTML retourne le contenu HTML d'une balise : texte et balisage alors que textContent ne retourne que le texte (sans le balisage interne).

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

Le rendu du code :

Récupération des attributs

Théme : on veut récupérer les valeurs des différents attributs d'une image (src, alt, title, class, etc.)

Le code de la page (extraits)

Le rendu du code :

Nouvelle version du script avec la syntaxe simplifié

Pour récupérer les valeurs d'attributs on peut utiliser un syntaxe simplifiée (à la place de la méthode élément.getAttribute(attribut)). Syntaxe simplifiée élément.attribut.

Le rendu du script avec la syntaxe simplifiée :

Pour récupérer le nom de la classe affectée à un élément il faut argumenter la méthode getAttribute avec le mot class ; ce qui est des plus logiques.
Par contre ce qui l'est moins c'est avec la syntaxe simplifiée, il faut utiliser le mot className (et non pas "class"). En effet le mot "class" est un mot réservé en JavaScript.

Les deux techniques ne sont pas équivalentes. Ainsi image.getAttribute('src') retourne le chemin relatif de la source alors que image.src retourne le chemin absolu. image.style ne retourne rien d'exploitable alors qu'avec la méthode getAttribute() on obtient vraiment la valeur de l'attribut style.
Un conseil : privilégier l'emploi de la méthode getAttribute() ; la syntaxe est un peu plus lourde mais le code est plus solide.

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

Dans certains ouvrages vous pourrez 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

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

Vous pouvez remarquer que j'ai récupéré des valeurs de propriétés de style quelque soit l'endroit où elles sont définies.
Ainsi pour l'élément image la propriété opacity est définie dans la balise mais la propriété display est définie dans la feuille de style externe ("style.css") via la classe centre. Et pour l'élément titre les propriétés sont définies dans la feuille de style interne.

Le rendu du code :

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).
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.

propriété de formatagenom en CSSnom en 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 récupérer les paramètres d'un élément du DOM (contenu, attributs, propriétés CSS).
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 : contenu, attributs, propriétés.

Modifier le contenu d'un élément

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

CSS & HTML

Le script

En cliquant sur la deuxième image (drapeau tricolore) on appelle la fonction fran qui remplit chaque élément avec un texte français.
En cliquant sur la troisième image (l'union jack) on appelle la fonction angl qui remplit chaque élément avec un texte anglais.

Affichez cette page en français puis en anglais :

Modifier les valeurs des attributs

Thème : désormais 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. 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 :

Syntaxe

Pour récupérer la valeur d'un attribut il faut utiliser la méthode élément.getAttribute('attribut')
Pour modifier la valeur d'un attribut il faut utiliser la méthode élément.setAttribute('attribut','nouvelle valeur').
La première méthode est de "getter" et la deuxième méthode est "setter". Vous découvriez qu'en jQuery une même méthode peut être utilisée en tant que "getter" ou "setter".

Pour récupérer la valeur d'un attribut on peut aussi utiliser une syntaxe simplifié : élément.attribut.

Supprimer un attribut

Vous pouvez aussi devoir supprimer des attributs de balise avec la syntaxe : élément.removeAttribute('attribut').
Exemple : cliquez sur une image pour l'effacer.
Le code correspondant :

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

Cet exemple est aussi une révision sur la modication d'une valeur d'attribut puisque la largeur de l'image est définie avec l'attribut "width".

Le script

Je récupère la largeur de l'image selon deux techniques dans vlargeur & vlargeur2.

Trois 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.

Rappels de syntaxe

Pour récupérer la valeur d'un attribut on peut toujours utiliser la syntaxe simplifiée élément.attribut OU la méthode élément.getAttribute('attribut')
Pour modifier la valeur d'un attribut choix entre syntaxe simplifiée élément.attribut = valeur OU la méthode élément.setAttribute('attribut',valeur) pour la modifier.

Pour une propriété, la récupération de la valeur doit toujours se faire avec la méthode getComputedStyle(élément).propriété et la modification avec la syntaxe élément.style.propriété = valeur.

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. A 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).

Notez l'emploi de document.image : collection d'images de la page.
Mais j'aurais pu aussi écrire : var image_page = document.querySelectorAll('img')
La structure FOR ... IN ... est très utile pour traiter toute une collection d'objets.

Changer de classe, rajouter une classe

Vous savez que le moyen le plus simple (et le plus efficace) de mettre en forme un élément HTML et de lui attribuer une voire plusieurs classes.

Exemple

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

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

Mauvaise solution

La variable "collection" est un tableau qui référence toutes les images.
Il faut ensuite parcourir ce tableau et utiliser pour chaque item l'attribut className (et non pas "class"). En effet le terme "class" est déjà utilisé en JS.

Le rendu du code faux :

C'est la "cata" ! Certes la classe "cadre" est ajoutée mais la classe "image" est retirée donc les images sont affichées avec leur taille native. Il y a donc remplacement et non rajout de classe.

Bonne solution

A première vue c'est la même instruction
Et bien non. L'instruction unique de la boucle est différente pour deux détails.
J'ai remplacé "=" par "+=" et "cadre" par " cadre". (un espace après les guillemets début).
Donc le code HTML pour chaque image devient : < img src =" ..." class ="image cadre" >
Chaque image se voit donc affectée deux classes !

Le rendu du code correct :

Troisième solution

La nouvelle version de JavaScript a ajouté l'objet classList et c'est heureux car on peut produire un code plus robuste.

La méthode add() ajoute la classe précisée si elle n'existe déjà pas.

La méthode remove() supprime la classe précisée.

La méthode toggle() ajoute (si elle n'existe pas) la clase ou la supprime si elle existe.

La méthode replace() remplace "classe0" par "classe1".

Pour reprendre le thème de l'ajout d'une deuxième classe à chaque image on peut donc écrire :
collection[i].classList.add("cadre");

A propos de l'objet classList

Thématique : on peut appliquer à une page différentes mise en forme selon le bouton de commande cliqué.

Le code CSS & HTML

Certains éléments sont affectés de la classe "modif" ; classe qui n'est pas définie dans la feuille de style.
Cette classe sert seulement à créer la collection des éléments modifiables par le script.

Le script

Le rendu du code :

En cliquant deux fois de suite sur le même bouton de commande toute mise en forme est retirée.

Ajouter / supprimer des éléments

Sachez que l'on peut encore aller plus loin dans la modification du DOM. On peut en effet ajouter de nouveaux éléments voire supprimer des éléments existants.

Pour insérer / supprimer de nouveaux éléments il faut pouvoir se déplacer dans le DOM car l'ajout se fait à partir de l'élément parent.
Avec la méthode removeChild() la suppression se fait aussi à partir le l'élément parent.

Ajouter/supprimer un élément à partir du parent - exemple 1

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 pas de CSS (pas de lien vers la feuille de style externe du site).

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 :

Ajouter / supprimer des éléments - exemple 2

Pour ajouter un nombre variable d'éléments de même nature il faut créer une routine et l'appeler un nombre indéterminé de fois via la méthode setInterval()

Thématique : création d'un patchwork d'images coquines.

Le code CSS & HTML

Pour que les positions absolues des images insérées soient calculées par rapport au coin haut gauche de la boite "eau" il faut que celle-ci soit aussi positionnée.
Si clic sur le bouton : exécution de deux instructions JS.
clearInterval(routine) met fin à l'appel régulier d'une fonction ; appel régulier identifié "routine".

pour supprimer le bouton de commande j'utilise pas la méthode removeChild() mais remove().
J'explique plus loin dans ce chapitre cette solution alternative pour la suppression d'un élément.

Le script

La fonction ajout() est appelée toutes les 500 millisecondes (2 fois par seconde). Cet appel régulier d'une fonction est identifié par la variable "routine".

Dans la fonction ajout() on crée un nouvel élément de type IMG, on lui affecte un SRC, on lui affecte un "left" et un "top". Enfin on l'insère dans le parent (boite à fond 'aqua').

Testez ce code :

Une autre façon de supprimer des éléments

Pour supprimer des éléments de la page il existe aussi la méthode élément.remove() comme je l'ai montré dans le script précédent.
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 "remove" l'image courante

Le code de la page

La classe "image" aligne verticalement toutes les images par le haut avec une largeur de 16% , etc.

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

La classe "image" aligne verticalement toutes les images par le haut avec une largeur de 16% , etc.

La variable images représente la collection de toutes les images de la page.
Il suffit ensuite de parcourir cette collection avec une boucle.

Rendu du code !

Actualisez la page pour réafficher toutes les images !