Après l'introduction au DOM, il est temps d'approfondir ce domaine en abordant les événements en JavaScript. Au cours de ce chapitre, nous étudierons l'utilisation des événements sans le DOM, avec le DOM-0 (inventé par Netscape) puis avec le DOM-2. Nous verrons comment mettre en place ces événements, les utiliser, modifier leur comportement, etc.
Après ce chapitre, vous pourrez d'ores-et-déjà commencer à interagir avec l'utilisateur, vous permettant ainsi de créer des pages web interactives capables de réagir à diverses actions effectuées soit par le visiteur, soit par le navigateur.
Les événements permettent de déclencher une fonction selon qu'une
action s'est produite ou non. Par exemple, on peut faire apparaître une
fenêtrealert()
lorsque l'utilisateur survole une zone d'une page Web.
« Zone » est un terme un peu vague, il vaut mieux parler
d'élément (HTML dans la plupart des cas). Ainsi, vous pouvez très bien ajouter un événement à un élément de votre
page Web (par exemple, une balise<div>
) pour faire en sorte de
déclencher un code JavaScript lorsque l'utilisateur fera une action sur l'élément en question.
Il existe de nombreux événements, tous plus ou moins utiles. Parmi les évènements utiles que nous n'aborderons pas, sachez qu'il en existe des spécifiques pour les plateformes mobiles (smartphones, tablettes, etc...).
Voici la liste des événements principaux, ainsi que les actions à effectuer pour qu'ils se déclenchent :
Nom de l'événement |
Action pour le déclencher |
---|---|
|
Cliquer (appuyer puis relâcher) sur l'élément |
|
Double-cliquer sur l'élément |
|
Faire entrer le curseur sur l'élément |
|
Faire sortir le curseur de l'élément |
|
Appuyer (sans relâcher) sur le bouton gauche de la souris sur l'élément |
|
Relâcher le bouton gauche de la souris sur l'élément |
|
Faire déplacer le curseur sur l'élément |
|
Appuyer (sans relâcher) sur une touche de clavier sur l'élément |
|
Relâcher une touche de clavier sur l'élément |
|
Frapper (appuyer puis relâcher) une touche de clavier sur l'élément |
|
« Cibler » l'élément |
|
Annuler le « ciblage » de l'élément |
|
Changer la valeur d'un élément spécifique aux formulaires
( |
|
Taper un caractère dans un champ de texte ( son support n'est pas complet sur tous les navigateurs ) |
|
Sélectionner le contenu d'un champ de texte
( |
Toutefois, ce n'est pas tout, il existe aussi deux événements
spécifiques à l'élément<form>
, que voici :
Nom de l'événement |
Action pour le déclencher |
---|---|
|
Envoyer le formulaire |
|
Réinitialiser le formulaire |
Tout cela est pour le moment très théorique, nous ne faisons que vous lister quelques événements existants, mais nous allons rapidement apprendre à les utiliser après un dernier petit passage concernant ce qu'on appelle le focus.
Le focus
définit ce qui peut être appelé le « ciblage » d'un élément. Lorsqu'un élément est ciblé, il va recevoir tous les
événements de votre clavier. Un exemple simple est d'utiliser
un<input>
de typetext
: si
vous cliquez dessus alors l'input
possède le focus. Autrement dit : il est
ciblé, et si vous tapez des caractères sur votre clavier vous allez les voir s'afficher dans
l'input
en question.
Le focus peut s'appliquer à de nombreux éléments, ainsi, si vous tapez sur la touche Tabulation de votre clavier alors que vous êtes sur une page Web, vous allez avoir un élément de ciblé ou de sélectionné qui recevra alors tout ce que vous tapez sur votre clavier. Par exemple, si vous avez un lien de ciblé et que vous tapez sur la touche Entrée de votre clavier alors vous serez redirigé vers l'URL contenue dans ce lien.
Bien, maintenant que vous avez vu le côté théorique (et barbant) des événements, nous allons pouvoir passer un peu à la pratique. Toutefois, dans un premier temps, il n'est que question de vous faire découvrir à quoi sert tel ou tel événement et comment il réagit, nous allons donc voir comment les utiliser sans le DOM, ce qui est considérablement plus limité.
Bien, commençons par
l'événementclick
sur un simple<span>
:
onclick="alert('Hello !');"Cliquez-moi !
Comme vous pouvez le constater, il
suffit de cliquer sur le texte pour que la boîte de dialogue s'affiche. Afin d'obtenir ce résultat nous avons ajouté
à notre<span>
un attribut contenant les deux lettres « on » et le nom
de notre événement « click » ; nous obtenons donc « onclick ».
Cet attribut possède une valeur qui est un code JavaScript, vous pouvez y écrire quasiment tout ce que vous souhaitez, mais tout doit tenir entre les guillemets de l'attribut.
this
Ce mot-clé n'est, normalement, pas censé vous servir dès maintenant, cependant il est toujours bon de le connaître pour les événements. Il s'agit d'une propriété pointant sur l'objet actuellement en cours d'utilisation. Donc, si vous faites appel à ce mot-clé lorsqu'un événement est déclenché, l'objet pointé sera l'élément qui a déclenché l'événement. Exemple :
onclick="alert('Voici le contenu de l\'élément que vous avez cliqué :\n\n' + this.innerHTML);"Cliquez-moi !
Afin de bien vous montrer ce qu'est le focus, voici un exemple qui
vous montrera ce que ça donne sur uninput
classique et un lien :
id="input" type="text" size="50" value="Cliquez ici !" onfocus="this.value='Appuyez maintenant sur votre touche de tabulation.';" onblur="this.value='Cliquez ici !';"
href="#" onfocus="document.getElementById('input').value = 'Vous avez maintenant le focus sur le lien, bravo !';"Un lien bidon
Comme vous pouvez le constater,
lorsque vous cliquez sur l'input
, celui-ci « possède » le focus : il
exécute donc l'événement et affiche alors un texte différent vous demandant d'appuyer sur votre touche de
tabulation. L'appui sur la touche de tabulation permet de faire passer le focus à l'élément suivant. En clair, en
appuyant sur cette touche vous faites perdre le focus à l'input
, ce qui
déclenche l'événementblur
(qui désigne la perte du focus) et fait
passer le focus sur le lien qui affiche alors son message grâce à son
événementfocus
.
Passons maintenant à un petit problème : quand vous souhaitez
appliquer un événementclick
sur un lien, que se passe-t-il ? Regardez
donc par vous-mêmes :
href="http://www.siteduzero.com" onclick="alert('Vous avez cliqué !');"Cliquez-moi !
Si vous avez essayé le code, vous avez
sûrement remarqué que la fonctionalert()
a bien fonctionné, mais
qu'après vous avez été redirigé vers le Site du Zéro, or on souhaite bloquer cette redirection. Pour cela, il suffit
juste d'ajouter le codereturn false;
dans notre
événementclick
:
href="http://www.siteduzero.com" onclick="alert('Vous avez cliqué !'); return false;"Cliquez-moi !
Ici,
lereturn false;
sert juste à bloquer l'action par défaut de
l'événement qui le déclenche.
Dans certains cas, vous allez devoir créer des liens juste pour
leur attribuer un événementclick
et non pas pour leur fournir un lien
vers lequel rediriger. Dans ce genre de cas, il est courant de voir ce type de code :
href="javascript: alert('Vous avez cliqué !');"Cliquez-moi !
Plus sérieusement, il s'agit d'une vieille méthode qui permet
d'insérer du JavaScript directement dans l'attributhref
de votre lien juste
en ajoutantjavascript:
au début de l'attribut. Cette technique est
maintenant obsolète et nous serions déçus de vous voir l'utiliser, nous vous en déconseillons donc très fortement
l'utilisation et vous proposons même une méthode alternative :
href="#" onclick="alert('Vous avez cliqué !'); return false;"Cliquez-moi !
Concrètement, qu'est-ce qui change ?
On a tout d'abord remplacé l'immondejavascript:
par un dièse (#) puis
on a mis notre code JavaScript dans l'événement approprié (click
).
Par ailleurs, on libère l'attributhref
, ce qui nous permet, si besoin, de
laisser un lien pour ceux qui n'activent pas le JavaScript ou bien encore pour ceux qui aiment bien ouvrir leurs
liens dans de nouveaux onglets.
OK, j'ai compris, mais pourquoi
unreturn false;
?
Tout simplement parce que le dièse redirige tout en haut de la page Web, ce qui n'est pas ce que l'on souhaite. On bloque donc cette redirection avec notre petit bout de code.
Bien, maintenant que nous avons vu l'utilisation des événements sans le DOM, nous allons passer à leur utilisation au travers de l'interface implémentée par Netscape que l'on appelle le DOM-0 puis au standard de base actuel : le DOM-2.
Cette interface est vieille mais n'est pas forcément dénuée d'intérêt. Elle reste très pratique pour créer des événements et peut parfois être préférée au DOM-2.
Commençons
par créer un simple code avec un événementclick
:
id="clickme"Cliquez-moi !
var element = document.getElementById('clickme');
element.onclick = function() {
alert("Vous m'avez cliqué !");
};
Alors, voyons par étapes ce que nous avons fait dans ce code :
On récupère
tout d'abord l'élément HTML dont l'ID estclickme
;
On accède
ensuite à la propriétéonclick
à laquelle on assigne une fonction
anonyme ;
Dans cette
même fonction, on fait un appel à la fonctionalert()
avec un texte
en paramètre.
Comme vous le voyez, on définit maintenant les événements non plus dans le code HTML mais directement en JavaScript. Chaque événement standard possède donc une propriété dont le nom est, à nouveau, précédé par les deux lettres « on ». Cette propriété ne prend plus pour valeur un code JavaScript brut, mais soit le nom d'une fonction, soit une fonction anonyme. Bref, dans tous les cas, il faut lui fournir une fonction qui contiendra le code à exécuter en cas de déclenchement de l'événement.
Concernant la suppression d'un événement avec le DOM-0, il suffit tout simplement de lui attribuer une fonction anonyme vide :
element.onclick = function() {};
Voilà tout pour les événements DOM-0, nous pouvons maintenant passer
au cœur des événements : le DOM-2 et
l'objetEvent
.
Nous
y voici enfin ! Alors, tout d'abord, pourquoi le DOM-2 et non pas le DOM-0 voire pas de DOM du tout ? Concernant la
méthode sans le DOM, c'est simple : on ne peut pas y utiliser
l'objetEvent
qui est pourtant une mine d'informations sur l'événement
déclenché. Il est donc conseillé de mettre cette méthode de côté dès maintenant (nous l'avons enseignée juste pour
que vous sachiez la reconnaître).
En ce qui concerne le DOM-0, il a deux problèmes majeurs : il est vieux, et il
ne permet pas de créer plusieurs fois le même événement.
Le
DOM-2, lui, permet la création multiple d'un même événement et gère aussi
l'objetEvent
. Autrement dit, le DOM-2 c'est bien, mangez-en
!
En clair, il faut constamment utiliser le DOM-2 ?
Cela est très fortement conseillé surtout lorsque vous en viendrez à utiliser des librairies au sein de vos sites web. Si ces librairies ajoutent des évènements DOM-0 à vos éléments HTML, vous aurez alors deux problèmes :
Ce sont de mauvaises librairies, elles n'ont pas à faire ça. Nous vous conseillons d'en trouver d'autres, le web n'en manque pas.
Les évènements de votre propre code seront écrasés ou bien vous écraserez ceux des librairies. Dans les deux cas, cela s'avère assez gênant.
Comme pour les autres interfaces événementielles, voici un exemple avec
l'événementclick
:
id="clickme"Cliquez-moi !
var element = document.getElementById('clickme');
element.addEventListener('click', function() {
alert("Vous m'avez cliqué !");
});
Concrètement, qu'est-ce qui change par
rapport au DOM-0 ? Alors tout d'abord nous n'utilisons plus une propriété mais une méthode
nomméeaddEventListener()
, et qui prend trois paramètres (bien que
nous n'en ayons spécifié que deux) :
Le nom de l'événement (sans les lettres « on ») ;
La fonction à exécuter ;
Un booléen optionnel pour spécifier si l'on souhaite utiliser la phase de capture ou bien celle de bouillonnement. Nous expliquerons ce concept un peu plus tard dans ce chapitre.
Une petite explication s'impose pour ceux qui n'arriveraient
éventuellement pas à comprendre le code précédent : nous avons bel et bien utilisé la
méthodeaddEventListener()
, elle est simplement écrite sur trois
lignes :
La première
ligne contient l'appel à la méthodeaddEventListener()
, le premier
paramètre, et l'initialisation de la fonction anonyme pour le deuxième paramètre ;
La deuxième ligne contient le code de la fonction anonyme ;
La troisième ligne contient l'accolade fermante de la fonction anonyme, puis le troisième paramètre.
Ce code revient à écrire le code suivant, de façon plus rapide :
var element = document.getElementById('clickme');
var myFunction = function() {
alert("Vous m'avez cliqué !");
};
element.addEventListener('click', myFunction);
Comme indiqué plus haut, le DOM-2 permet la création multiple d'événements identiques pour un même élément, ainsi, vous pouvez très bien faire ceci :
id="clickme"Cliquez-moi !
var element = document.getElementById('clickme');
// Premier événement click
element.addEventListener('click', function() {
alert("Et de un !");
});
// Deuxième événement click
element.addEventListener('click', function() {
alert("Et de deux !");
});
Si vous avez exécuté ce code, vous avez peut-être eu les événements déclenchés dans l'ordre de création, cependant ce ne sera pas forcément le cas à chaque essai. En effet, l'ordre de déclenchement est un peu aléatoire…
Venons-en maintenant à la suppression des événements ! Celle-ci
s'opère avec la méthoderemoveEventListener()
et se fait de manière
très simple :
element.addEventListener('click', myFunction); // On crée l'événement
element.removeEventListener('click', myFunction); // On supprime l'événement en lui repassant les mêmes paramètres
Toute suppression d'événement avec le DOM-2 se fait avec les mêmes paramètres utilisés lors de sa création ! Cependant, cela ne fonctionne pas aussi facilement avec les fonctions anonymes ! Tout événement DOM-2 créé avec une fonction anonyme est particulièrement complexe à supprimer, car il faut posséder une référence vers la fonction concernée, ce qui n'est généralement pas le cas avec une fonction anonyme.
Vous souvenez-vous que notre
méthodeaddEventListener()
prend trois paramètres ? Nous vous avions
dit que nous allions revenir sur l'utilisation de son troisième paramètre plus tard. Eh bien ce « plus tard » est
arrivé !
Capture ? Bouillonnement ? De quoi parle-t-on ?
Ces deux phases sont deux étapes distinctes de l'exécution d'un événement. La première, la capture (capture en anglais), s'exécute avant le déclenchement de l'événement, tandis que la deuxième, le bouillonnement (bubbling en anglais), s'exécute après que l'événement a été déclenché. Toutes deux permettent de définir le sens de propagation des événements.
Mais qu'est-ce que la propagation d'un événement ? Pour expliquer cela, prenons un exemple avec ces deux éléments HTML :
Du texte !
Si nous attribuons une fonction à
l'événementclick
de chacun de ces deux éléments et que l'on clique sur
le texte, quel événement va se déclencher en premier à votre avis ? Bonne question n'est-ce pas ?
Notre réponse se trouve dans les phases de capture et de
bouillonnement. Si vous décidez d'utiliser la capture, alors l'événement du<div>
se
déclenchera en premier puis viendra ensuite l'événement du<span>
. En
revanche, si vous utilisez le bouillonnement, ce sera d'abord l'événement du<span>
qui
se déclenchera, puis viendra par la suite celui du<div>
.
Voici un petit code qui met en pratique l'utilisation de ces deux phases :
id="capt1"
id="capt2"Cliquez-moi pour la phase de capture.
id="boul1"
id="boul2"Cliquez-moi pour la phase de bouillonnement.
var capt1 = document.getElementById('capt1'),
capt2 = document.getElementById('capt2'),
boul1 = document.getElementById('boul1'),
boul2 = document.getElementById('boul2');
capt1.addEventListener('click', function() {
alert("L'événement du div vient de se déclencher.");
}, true);
capt2.addEventListener('click', function() {
alert("L'événement du span vient de se déclencher.");
}, true);
boul1.addEventListener('click', function() {
alert("L'événement du div vient de se déclencher.");
}, false);
boul2.addEventListener('click', function() {
alert("L'événement du span vient de se déclencher.");
}, false);
Et pour finir, un lien vers la spécification du W3C concernant ces phases si vous avez envie d'aller plus loin. Il est conseillé de regarder ce lien ne serait-ce que pour voir le schéma fourni qui explique bien le concept de ces phases.
Maintenant que nous avons vu comment créer et supprimer des événements, nous pouvons passer à l'objet Event !
Event
Tout d'abord, à quoi sert cet objet ? À vous fournir une multitude d'informations sur l'événement actuellement déclenché. Par exemple, vous pouvez récupérer quelles sont les touches actuellement enfoncées, les coordonnées du curseur, l'élément qui a déclenché l'événement… Les possibilités sont nombreuses !
Cet objet est bien particulier dans le sens où il n'est accessible que lorsqu'un événement est déclenché. Son accès ne peut se faire que dans une fonction exécutée par un événement, cela se fait de la manière suivante avec le DOM-0 :
element.onclick = function(e) { // L'argument « e » va récupérer une référence vers l'objet « Event »
alert(e.type); // Ceci affiche le type de l'événement (click, mouseover, etc.)
};
Et de cette façon là avec le DOM-2 :
element.addEventListener('click', function(e) { // L'argument « e » va récupérer une référence vers l'objet « Event »
alert(e.type); // Ceci affiche le type de l'événement (click, mouseover, etc.)
});
Il est important de préciser que
l'objetEvent
peut se récupérer dans un argument autre
quee
! Vous pouvez très bien le récupérer dans un argument
nommétest
,hello
, ou
autre… Après tout, l'objetEvent
est tout simplement passé en référence
à l'argument de votre fonction, ce qui vous permet de choisir le nom que vous souhaitez.
Event
Vous avez déjà découvert la propriététype
qui permet de savoir quel
type d'événement s'est déclenché. Passons maintenant à la découverte des autres propriétés et méthodes que possède
cet objet (attention, tout n'est pas présenté, seulement l'essentiel) :
Une des plus importantes propriétés de notre objet se
nommetarget
. Celle-ci permet de récupérer une référence vers
l'élément dont l'événement a été déclenché (exactement comme lethis
pour
les événements sans le DOM ou avec DOM-0), ainsi vous pouvez très bien modifier le contenu d'un élément qui a été
cliqué :
id="clickme"Cliquez-moi !
var clickme = document.getElementById('clickme');
clickme.addEventListener('click', function(e) {
e.target.innerHTML = 'Vous avez cliqué !';
});
Hum, ce n'est pas un peu la même chose ?
Eh bien non ! Pour expliquer cela de façon simple, certains
événements appliqués à un élément parent peuvent se propager d'eux-mêmes aux éléments enfants ; c'est le cas des
événementsmouseover
,mouseout
,mousemove
,click
…
ainsi que d'autres événements moins utilisés. Regardez donc cet exemple pour mieux comprendre :
id="result"
id="parent1"
Parent
id="child1"Enfant N°1
id="child2"Enfant N°2
var parent1 = document.getElementById('parent1'),
result = document.getElementById('result');
parent1.addEventListener('mouseover', function(e) {
result.innerHTML = "L'élément déclencheur de l'événement \"mouseover\" possède l'ID : " + e.target.id;
});
En testant cet exemple, vous avez
sûrement remarqué que la propriététarget
renvoyait toujours l'élément
déclencheur de l'événement, or nous souhaitons obtenir l'élément sur lequel a été appliqué l'événement. Autrement
dit, on veut connaître l'élément à l'origine de cet événement, et non pas ses enfants.
La solution est simple : utiliser la
propriétécurrentTarget
au lieu
detarget
. Essayez donc par vous-mêmes après modification de cette
seule ligne, l'ID affiché ne changera jamais :
result.innerHTML = "L'élément déclencheur de l'événement \"mouseover\" possède l'ID : " + e.currentTarget.id;
La position du curseur est une information très importante, beaucoup
de monde s'en sert pour de nombreux scripts comme le
drag & drop
. Généralement, on récupère la position du curseur par rapport au coin supérieur gauche de la page Web, cela dit il
est aussi possible de récupérer sa position par rapport au coin supérieur gauche de l'écran. Toutefois, dans ce
tutoriel, nous allons nous limiter à la page Web. Regardez
la documentation de l'objetEvent
si vous souhaitez en apprendre plus.
Pour récupérer la position de notre curseur, il existe deux
propriétés :clientX
pour la position horizontale
etclientY
pour la position verticale. Étant donné que la position du
curseur change à chaque déplacement de la souris, il est donc logique de dire que l'événement le plus adapté à la
majorité des cas estmousemove
.
Comme d'habitude, voici un petit exemple pour que vous compreniez bien :
id="position"
var position = document.getElementById('position');
document.addEventListener('mousemove', function(e) {
position.innerHTML = 'Position X : ' + e.clientX + 'px<br />Position Y : ' + e.clientY + 'px';
});
Pas très compliqué, n'est-ce pas ? Bon, il est possible que vous trouviez l'intérêt de ce code assez limité, mais quand vous saurez manipuler les propriétés CSS des éléments vous pourrez, par exemple, faire en sorte que des éléments HTML suivent votre curseur. Ce sera déjà bien plus sympathique !
Cette fois nous allons étudier une propriété un peu plus « exotique »
assez peu utilisée mais qui peut pourtant se révéler très utile ! Il s'agit
derelatedTarget
et elle ne s'utilise qu'avec les
événementsmouseover
etmouseout
.
Cette propriété remplit deux fonctions différentes selon l'événement utilisé. Avec
l'événementmouseout
, elle vous fournira l'objet de l'élément sur
lequel le curseur vient d'entrer ; avec l'événementmouseover
, elle
vous fournira l'objet de l'élément dont le curseur vient de sortir.
Voici un exemple qui illustre son fonctionnement :
id="result"
id="parent1"
Parent N°1 Mouseover sur l'enfant
id="child1"Enfant N°1
id="parent2"
Parent N°2 Mouseout sur l'enfant
id="child2"Enfant N°2
var child1 = document.getElementById('child1'),
child2 = document.getElementById('child2'),
result = document.getElementById('result');
child1.addEventListener('mouseover', function(e) {
result.innerHTML = "L'élément quitté juste avant que le curseur n'entre sur l'enfant n°1 est : " + e.relatedTarget.id;
});
child2.addEventListener('mouseout', function(e) {
result.innerHTML = "L'élément survolé juste après que le curseur ait quitté l'enfant n°2 est : " + e.relatedTarget.id;
});
La récupération des touches frappées se fait par le biais de trois événements différents. Dit comme ça, cela laisse sur un sentiment de complexité, mais vous allez voir qu'au final tout est beaucoup plus simple qu'il n'y paraît.
Les événementskeyup
etkeydown
sont
conçus pour capter toutes les frappes de touches. Ainsi, il est parfaitement possible de détecter l'appui sur la
touche A voire même sur la touche Ctrl. La différence entre ces deux événements se situe dans
l'ordre de déclenchement :keyup
se déclenche lorsque vous relâchez une
touche, tandis quekeydown
se déclenche au moment de l'appui sur la
touche (commemousedown
).
Cependant, faites bien attention avec
ces deux événements : toutes les touches retournant un caractère retourneront un caractère majuscule, que
la touche Maj soit pressée ou non.
L'événementkeypress
, lui, est d'une toute autre utilité : il sert
uniquement à capter les touches qui écrivent un caractère, oubliez donc les Ctrl, Alt et
autres touches de ce genre qui n'affichent pas de caractère. Alors, forcément, vous vous demandez probablement à
quoi peut bien servir cet événement au final ? Eh bien son avantage réside dans sa capacité à détecter les
combinaisons de touches ! Ainsi, si vous faites la combinaison Maj + A,
l'événementkeypress
détectera bien un A majuscule là où les événementskeyup
etkeydown
se
déclencheront deux fois, une fois pour la touche Maj et une deuxième fois pour la touche A.
Et j'utilise quelle propriété pour récupérer mon caractère, du coup ?
Si nous devions énumérer toutes les propriétés capables de vous
fournir une valeur, il y en aurait trois
:keyCode
,charCode
etwhich
.
Ces propriétés renvoient chacune un code
ASCII
correspondant à la touche pressée.
Cependant, la
propriétékeyCode
est amplement suffisante dans tous les cas, comme
vous pouvez le constater dans l'exemple qui suit :
id="field" type="text"
keydown
id="down"
keypress
id="press"
keyup
id="up"
var field = document.getElementById('field'),
down = document.getElementById('down'),
press = document.getElementById('press'),
up = document.getElementById('up');
document.addEventListener('keydown', function(e) {
down.innerHTML = e.keyCode;
});
document.addEventListener('keypress', function(e) {
press.innerHTML = e.keyCode;
});
document.addEventListener('keyup', function(e) {
up.innerHTML = e.keyCode;
});
Je ne veux pas obtenir un code, mais le caractère !
Dans ce cas, il n'existe qu'une seule solution : la
méthodefromCharCode()
. Elle prend en paramètre une infinité
d'arguments. Cependant, pour des raisons un peu particulières qui ne seront abordées que plus tard dans ce cours,
sachez que cette méthode s'utilise avec le préfixeString.
, comme suit
:
String.fromCharCode(/* valeur */);
Cette méthode est donc conçue pour
convertir les valeurs ASCII vers des caractères lisibles. Faites donc bien attention à n'utiliser cette méthode
qu'avec un événementkeypress
afin d'éviter d'afficher, par exemple, le
caractère d'un code correspondant à la touche Ctrl, cela ne fonctionnera pas !
Pour terminer, voici un court exemple :
String.fromCharCode(84, 101, 115, 116); // Affiche : Test
Eh oui, nous y revenons ! Nous avons vu qu'il est possible de bloquer
l'action par défaut de certains événements, comme la redirection d'un lien vers une page Web. Sans le DOM-2, cette
opération était très simple vu qu'il suffisait d'écrirereturn false;
.
Avec l'objetEvent
, c'est quasiment tout aussi simple vu qu'il suffit
juste d'appeler la méthodepreventDefault()
!
Reprenons l'exemple que nous avions utilisé pour les événements sans le DOM et utilisons donc cette méthode :
id="link" href="http://www.siteduzero.com"Cliquez-moi !
var link = document.getElementById('link');
link.addEventListener('click', function(e) {
e.preventDefault(); // On bloque l'action par défaut de cet événement
alert('Vous avez cliqué !');
});
C'est simple comme bonjour n'est-ce pas ?
En JavaScript, il existe un problème fréquent que nous vous proposons d'étudier et de résoudre afin de vous éviter bien des peines lorsque cela vous arrivera.
Plutôt que de vous expliquer le problème, nous allons vous le faire constater. Prenez donc ce code HTML ainsi que ce code CSS :
id="myDiv"
Texte 1
Texte 2
Texte 3
Texte 4
id="results"
#myDiv, #results {
margin: 50px;
}
#myDiv {
padding: 10px;
width: 200px;
text-align: center;
background-color: #000;
}
#myDiv div {
margin: 10px;
background-color: #555;
}
Maintenant, voyons ce que nous
souhaitons obtenir. Notre but ici est de faire en sorte de détecter quand le curseur entre sur notre
élément#myDiv
et quand il en ressort. Vous allez donc penser qu'il n'y a rien
de plus facile et vous lancer dans un code de ce genre :
var myDiv = document.getElementById('myDiv'),
results = document.getElementById('results');
myDiv.addEventListener('mouseover', function() {
results.innerHTML += "Le curseur vient d'entrer.<br />";
});
myDiv.addEventListener('mouseout', function() {
results.innerHTML += "Le curseur vient de sortir.<br />";
});
Eh bien soit !
Pourquoi ne pas l'essayer ?
Alors ? Avez-vous essayé de faire
passer votre curseur sur toute la surface
du<div>
#myDiv
? Il y a
effectivement quelques lignes en trop qui s'affichent dans nos résultats…
Je ne vois absolument pas d'où ça peut venir…
Si cela peut vous rassurer, personne ne voit bien d'où cela peut venir au premier coup d'œil. En fait, le souci est tout bête et a déjà été fortement évoqué au travers de ce chapitre, relisez donc ceci :
Citation
Certains événements appliqués à un élément parent peuvent se propager d'eux-mêmes aux éléments enfants, c'est le cas des événements
mouseover
,mouseout
,mousemove
,click
… ainsi que d'autres événements moins utilisés.
Voici notre problème : les enfants héritent des propriétés des événements susnommés appliqués aux éléments parents.
Ainsi, lorsque vous déplacez votre curseur depuis
le<div>
#myDiv
jusqu'à
un<div>
enfant, vous allez déclencher
l'événementmouseout
sur#myDiv
et
l'événementmouseover
sur le<div>
enfant.
Afin de pallier ce problème, il existe une solution assez tordue. Vous souvenez-vous de la
propriétérelatedTarget
abordée dans ce chapitre ? Son but va être de
détecter quel est l'élément vers lequel le curseur se dirige ou de quel élément il provient.
Ainsi, nous avons deux cas de figure :
Dans le cas
de l'événementmouseover
, nous devons détecter la
provenance du curseur. Si le curseur vient d'un enfant de#myDiv
alors
le code de l'événement ne devra pas être exécuté. S'il provient d'un élément extérieur
à#myDiv
alors l'exécution du code peut s'effectuer.
Dans le cas
demouseout
, le principe est similaire, si ce n'est que là nous
devons détecter la destination du curseur. Dans le cas où la destination du curseur est un enfant
de#myDiv
alors le code de l'événement n'est pas exécuté, sinon il
s'exécutera sans problème.
Mettons cela en pratique avec
l'événementmouseover
pour commencer. Voici le code d'origine :
myDiv.addEventListener('mouseover', function() {
results.innerHTML += "Le curseur vient d'entrer.";
});
Maintenant, il nous faut savoir si
l'élément en question est un enfant direct demyDiv
ou non. La solution
consiste à remonter tout le long de ses éléments parents jusqu'à tomber soit
surmyDiv
, soit sur l'élément<body>
qui
désigne l'élément HTML le plus haut dans notre document. Il va donc nous falloir une
bouclewhile
:
myDiv.addEventListener('mouseover', function(e) {
var relatedTarget = e.relatedTarget;
while (relatedTarget != myDiv && relatedTarget.nodeName != 'BODY') {
relatedTarget = relatedTarget.parentNode;
}
results.innerHTML += "Le curseur vient d'entrer.";
});
Ainsi, nous retrouverons dans notre
variablerelatedTarget
le premier élément trouvé qui correspond à nos
critères, donc soitmyDiv
, soit<body>
.
Il nous suffit alors d'insérer une condition qui exécutera le code de notre événement uniquement dans le cas où la
variablerelatedTarget
ne pointe pas sur
l'élémentmyDiv
:
myDiv.addEventListener('mouseover', function(e) {
var relatedTarget = e.relatedTarget;
while (relatedTarget != myDiv && relatedTarget.nodeName != 'BODY') {
relatedTarget = relatedTarget.parentNode;
}
if (relatedTarget != myDiv) {
results.innerHTML += "Le curseur vient d'entrer.";
}
});
Cependant, il reste encore un petit
cas de figure qui n'a pas été géré et qui peut être source de problèmes ! Comme vous le savez, la
balise<body>
ne couvre pas forcément la page Web complète de votre
navigateur, ce qui fait que votre curseur peut provenir d'un élément situé encore plus haut que la
balise<body>
. Cet élément correspond à la
balise<html>
— soit l'élémentdocument
en
JavaScript —, il nous faut donc faire une petite modification afin de bien préciser que si le curseur provient
dedocument
il ne peut forcément pas provenir
demyDiv
:
myDiv.addEventListener('mouseover', function(e) {
var relatedTarget = e.relatedTarget;
while (relatedTarget != myDiv && relatedTarget.nodeName != 'BODY' && relatedTarget != document) {
relatedTarget = relatedTarget.parentNode;
}
if (relatedTarget != myDiv) {
results.innerHTML += "Le curseur vient d'entrer.";
}
});
Voilà ! Maintenant, notre événement
mouseover
fonctionne comme nous le souhaitions !
Rassurez-vous, vous avez fait le plus gros, il ne nous reste plus qu'à adapter un peu le code pour l'événement
mouseout
. Cet événement va utiliser le même code que celui de
mouseover
à deux choses près :
Le texte à afficher n'est pas le même ;
Nous
n'utilisons plus mouseover
mais
mouseout
, car nous souhaitons l'élément de destination.
Ce qui nous donne donc ceci :
myDiv.addEventListener('mouseout', function(e) {
var relatedTarget = e.relatedTarget;
while (relatedTarget != myDiv && relatedTarget.nodeName != 'BODY' && relatedTarget != document) {
relatedTarget = relatedTarget.parentNode;
}
if (relatedTarget != myDiv) {
results.innerHTML += "Le curseur vient de sortir.<br />";
}
});
Enfin, nous avons terminé !
Il est grand temps d'essayer le
code complet !
L'étude de ce problème était quelque peu avancée par rapport à vos connaissances actuelles, sachez que vous n'êtes pas obligés de retenir la solution. Retenez cependant qu'elle existe et que vous pouvez la trouver ici, dans ce chapitre, car ce genre de soucis peut être très embêtant dans certains cas, notamment quand il s'agit de faire des animations.
Les événements sont utilisés pour appeler une fonction à partir d'une action produite ou non par l'utilisateur.
Différents événements existent pour détecter certaines actions comme le clic, le survol, la frappe au clavier et le contrôle des champs de formulaires.
Le DOM-0 est
l'ancienne manière de capturer des événements. Le DOM-2 introduit
l'objetEvent
et la fameuse
méthodeaddEventListener()
.
L'objetEvent
permet de récolter toutes sortes d'informations se
rapportant à l'événement déclenché : son type, depuis quel élément il a été déclenché, la position du curseur,
les touches frappées… Il est aussi possible de bloquer l'action d'un événement
avecpreventDefault()
.
Parfois, un événement appliqué sur un parent se propage à ses enfants. Cet héritage des événements peut provoquer des comportements inattendus.