Les interactions que l'utilisateur peut avoir avec un document Web chargé dans un navigateur vont produire des événements. Il existe différents types d'événements selon les actions de l'utilisateur. Voici quelques-uns de ces événements :
Pour une liste plus complète des événements existant, voir w3schools.
Lorsqu'un événement survient, il est toujours associé à l'élément du DOM concerné par l'événement. Par conséquent, si une fonction a été associée à ce type d'événement sur ce type d'élément du DOM, l'interpréteur javascript va l'exécuter ce qui va permettre de "réagir" à l'événement. Par exemple, suite au clic sur un bouton, on va pouvoir afficher un message particulier dans la page.
Voici un petit exemple d'un tel comportement :
Texte au chargement
Ainsi, pour réagir aux actions de l'utilisateur, il faut pouvoir, en javascript :
<input>
)click
).
En javascript, le DOM est représenté grâce à un arborescence d'objets. Les différents types d'objets permettant de représenter le DOM sont donnés ici On vous propose également ce petit résumé :
.La façon la plus simple de retrouver directement un élément du DOM consiste à utiliser la méthode
getElementById(identifiantElement)
de l'objet document
construit
pour vous par le navigateur.
Ainsi, dans le document html suivant :
<html> <body> <h1 id="titre">Ma page</h1> <p id="p1">Premier paragraphe</p> <p id="p2">Deuxième paragraphe< <strong>avec une partie en gras</strong> /p> </body> </html>
Pour récupérer l'objet représentant le deuxième paragraphe on pourra écrire :
var para2 = document.getElementById("p2")
D'autres méthodes peuvent être utiles pour retrouver des noeuds du DOM. Elles figurent sur le schéma ci-dessus. En voici la liste :
//on récupère le paragraphe d'identifiant p1 var para = document.getElementById("p1"); //on récupère son noeud parent ie le noeud de la balise body var noeudBody = para.parentNode;
//on récupère le paragraphe d'identifiant p2 var para.document.getElementById("p2"); //on récupère la liste de ses noeuds fils var noeudsFils = para.childNodes; //on récupère le deuxième noeud fils ie le noeud de la balise strong var noeudStrong = noeudFils[1];
Vous trouverez sur le site w3schools, une page résumant les différentes propriétés et fonctions permettant de naviguer facilement dans le DOM.
Depuis la norme ECMAS2015, une nouvelle façon de retrouver des éléments du DOM en utilisant des sélecteurs CSS
est apparue. Elle consiste à utiliser, entre autres, la fonction querySelector
sur l'objet document
ou sur un noeud du DOM en lui passant en paramètre, un sélecteur CSS tel qu'un nom de balise HTML, un nom de classe CSS, un
identifiant CSS ou encore une combinaison de ces éléments. Cela permet de récupérer en un appel un
noeud du DOM sans identifiant et sans pour autant naviguer dans le DOM jusqu'au noeud recherché.
On peut trouver ici un exemple d'utilisation de cette fonction
(en commentaires, figurent les versions sans cette fonction pour pouvoir comparer).
Le site MDN propose une
page
décrivant les possibilités de cette fonction et son mode d'utilisation.
NB : Lorsque le navigateur exécute un code javascript dans une page HTML, les éventuelles erreurs générées lors de cette exécution sont visibles dans la console. Il faut donc la laisser ouverte dès le chargement de la page pour pouvoir voir les messages d'erreurs.
On vous donne le fichier exoEvenements1.html, le fichier
exoEvenements1.js et le fichier css associé style.css. Comme vous pouvez le constater, lorsque l'on
passe le pointeur de la souris sur le premier paragraphe, celui-ci est mis en surbrillance.
Le choix de l'élément du DOM mis en surbrillance est effectué dans la fonction rechercherElement
du fichier javascript (vous pouvez ignorer le reste de ce fichier pour le moment).
Sans modifier le fichier html, modifier la fonction rechercherElement
pour
qu'elle réponde successivement aux 3 problèmes suivants :
getElementById
cette fois. A la place, on va utiliser les propriétés de Node
qui permettent de se déplacer dans l'arbre du DOM. Ici on pourra commencer par utiliser parentNode
sur le noeud du DOM correspondant au premier paragraphe ce qui permettra de récupérer le noeud correspondan à la balise body
. Dans un deuxième temps, on pourra utiliser childNodes
sur ce noeud pour récupérer l'ensemble des noeuds fils de la balise body
. Cette propriété est une collection qui peut être accédée par des indices comme pour les tableaux classiques. Il ne reste plus qu'a déterminer le numéro du noeud fils correspondant au second paragraphe. Attention à ne pas oublier les sauts de ligne dans votre décompte !
Le traitement que l'on souhaite effectuer lorsqu'un événement survient doit être défini via une
fonction (appelée souvent handler) qui prend un paramètre de type Event
en paramètre
(paramètre que l'on appelle classiquement event
).
Ce paramètre est un objet représentant l'événement qui a été déclenché.
Pour plus de détails sur ce paramètre, voir MDN
Dans une fonction handler, le mot-clef this
désigne le noeud du DOM auquel est associé le handler qui est
en train de s'exécuter. Ce noeud correspond la plupart du temps à l'élément qui a déclenché l'événement.
NB : : Lorsqu'un événement est déclenché, il est propagé en descendant puis en remontant dans l'arbre du DOM. Cela doit être pris en compte lorsque l'on associe plusieurs handlers pour le même événement mais pour différents noeuds du DOM. Cet aspect ne sera pas traité dans le cadre de cette formation. Pour en savoir plus : MDN (partie "bubbling and capturing")
Dans l'exercice précédent, le traitement effectué lorsque la souris arrive sur l'élément
du DOM choisi est défini dans la fonction surbrillance
. Modifier cette fonction pour
produire les comportements suivants :
alert(string)
de l'objet window
pour générer la fenêtre d'alerte. Pour associer un traitement à un événement émis par un élement du DOM, il faut utiliser la méthode
addEventListener(nomEvénement, nomTraitement)
sur l'élément du DOM en
question. Le nom de l'évément est une chaîne pouvant correspondre à un des noms d'événements donnés
en introduction. Le nom du traitement est celui d'une fonction (le handler) définissant le traitement à effectuer (voir partie précédente).
En appelant plusieurs fois la méthode addEventListener, il est tout à fait possible d'associer plusieurs traitements à un même événement survenant sur un seul et même élément du DOM.
NB: Dans des versions plus anciennes de javascript, pour installer un gestionnaire d'événements, au lieu d'utiliser la
fonction addEventListener
, on utilisait des attributs HTML portant le nom des événements à gérer au niveau
de la balise HTML où cet attribut apparait. Cela est illustré dans l'exemple fourni ici qui est une
ré-écriture de l'exemple apparaissant au début de cette page (clic sur un bouton).
Cette façon de faire est encore présente, sur Internet notamment. Elle est pourtant devenue
obsolète. Elle présente notamment le gros inconvénient de mélanger au sein du même fichier du HTML et du javascript ce qui
nuit considérablement à la lecture et à la maintenance du code.
Dans l'exercice précédent, les associations (element DOM,evenement,traitement) sont établies dans la fonction init
. Pour gérer l'effet de mise en surbrillance au survol de la souris, il a fallu associer des traitements
à 2 événements différents :
Modifier la fonction init
pour répondre à chacun des cas suivants :
surbrillance
, on pourra utiliser la fonction getAttribute
pour connaitre la valeur de l'attribut class
de l'élément du DOM sur lequel on a cliqué de manière à pouvoir ensuite mettre à jour correctement avec la fonction setAttribute
la valeur de cet attribut.
Afin de gagner du temps (les échanges via le réseau sont quelques fois lents...), les navigateurs web essaient
de paralléliser les choses. Et notamment, ils exécutent le code javascript dès qu'il est reçu, même si la page
n'est pas encore complètement chargée ou complètement construite. Du coup, la recherche d'un élément du DOM
(via par exemple un getElementById
) risque d'être effectuée avant que celui-ci n'ait été construit.
Pour éviter cela, on va attendre que le navigateur ait complètement construit le DOM. Et pour ce faire, fort
heureusement, un événement "DOMContentLoaded" est émis au niveau du document lorque c'est fait. Il ne nous reste plus qu'à
associer un traitement à cet événement-là sur le DOM. Voilà pourquoi, dans l'exemple qui sert de support aux
exercices précédents, l'association des traitements aux objets du DOM (et donc la recherche de ces derniers)
est faite dans une fonction init(event)
, qui est associée, dans la première ligne du fichier
à l'événement "DOMContentLoaded" généré par le document (une autre solution, moins judicieuse toutefois, est
d'associer cette fonction d'initialisation à l'événement "load" de l'objet "window").
Un des rôles de Javascript est de valider les données d'un formulaire avant que celui-ci ne soit envoyé au serveur. Le retour à l'utilisateur est alors bien plus rapide que si on attendait que le serveur valide la saisie.
Pour ce faire, plusieurs événements peuvent être utiles :
preventDefault()
du
paramètre event
de la méthode de traitement de l'événement.Un formulaire vous est proposé dans le document exoEvenements4.html. Ce formulaire
permet de saisir les données (fin,debut,pas) nécessaires à l'utilisation de la fonction suite
que vous avez
écrite précédemment. Dans un premier temps, on ne va pas générer la suite de nombres en fonction de ce qui est saisi.
L'objectif ici est de valider le formulaire c'est-à-dire :
generer
:
suite
résultant des valeurs qui ont été saisies.