Javascript - Pour rendre vos pages interactives

Auteur: Mohamed CHINY Durée necessaire pour le cours de Javascript - Pour rendre vos pages interactives Niveau recommandé pour le cours de Javascript - Pour rendre vos pages interactives Supports vidéo non disponibles pour ce cours Exercices de renforcement disponibles pour ce cours Quiz disponible pour ce cours

Page 22: Objet event

Toutes les pages
Si vous êtes débutant vous pouvez ignorer cette partie. Cependant, j'aimerais bien que vous la lisiez quand même, car elle renferme quelques astuces pratiques (et abordables par fois).

Une autre manière pour gérer les événements

L'objet event permet de fournir des détails supplémentaires sur l'événement qui vient de se produire. Par exemple, l’événement keyDown indique que l'utilisateur vient d'appuyer sur une touche du clavier, mais on ne sait pas quelle touche exactement. Avec l'objet event il est possible de préciser ce genre de détail et bien plus encore.

L'objet event se propage dans l'arbre du DOM selon le flux d'événement décrit ou par défaut.

Flux d'événements

Jusqu'ici, on sait que l'événement se produit sur un objet, et on le capture par le biais du gestionnaire d'événements (statique ou dynamique).

Examinons ce code de plus près:
<!DOCTYPE html>
<html>
   <head>
      <meta charset="UTF-8" />
   </head>
   <body>
      <section>
         <div>
            <a href="#" onClick="f()">Hyperlien</a>
         </div>
      </section>
   </body>
</html>
Nous avons placé un gestionnaire d'événements sur le lien (balise <a>) en faisant appel à la fonction f() (que je n'ai pas défini, car ce n'est pas ce qui nous intéresse ici). Alors, logiquement, c'est le texte "Hyperlien" du lien hypertexte qui est concerné par l'événement click. Cependant , les choses ne se déroulent pas aussi simplement.

Regardons un peu comment la hiérarchie est établie dans ce cas:
OBJET DOCUMENT
SECTION
DIV
AHyperlien
Chacun des rectangles représente un objet déclaré dans le dernier code (l'objet document étant le document HTML lui même).

Le fait de cliquer sur l'hyperlien (objet A), revient à cliquer également sur son conteneur qui est l'objet DIV, ce qui implique qu'on a aussi cliqué sur son parent qui est l'objet SECTION ce qui signifie aussi qu'on a cliqué sur leur parent à tous, l'objet DOCUMENT.

Le flux de propagation de l'événement click évolue comme ceci:
  1. Phase capture: L'événement se propage du haut en bas, c'est à dire de l'objet du plus haut niveau (dans la hiérarchie) à l'objet du plus bas niveau sur lequel la souris est placée au moment du déclenchement de l'événement. Cette phase s'appelle la capture.
  2. Phase bouillonnement (bubbling):Une fois l'événement a atteint la cible, il se propage dans le sens inverse en remontant la hiérarchie jusqu'à atteindre l'objet document. Cette phase s'appelle bouillonnement (bubbling en anglais).

C'est de cette manière qu'un événement est capturé en Javascript, mais on peut changer ce comportement par défaut si on souhaite, et on peut même interrompre le flux de propagation de l'événements (c'est ce qu'on va voir aussi dans cette partie).

Méthodes, attributs et sous-objets de l'objet event

Méthodes associées à event

Deux méthodes sont les plus connus pour l'objet event:
  • preventDefault(): Cette méthode empêche le navigateur d'entamer une action par défaut. Par exemple, le fait de cliquer sur un bouton de type submit redirige le navigateur vers la page définie dans l'attribut action du formulaire, ce qui représente le comportement par défaut. Or, si on déclare convenablement la méthode preventDefault(), le navigateur n'entamera pas la redirection.

    On peut remplacer cette méthode par un simple return false.
  • stopPropagation(): Cette méthode empêche la propagation du flux d'événement. Si le flux se propage automatiquement sur les deux phases qu'on a vu dans le paragraphe précédent, la méthode stopPropagation() permet de rompre ce flux de telle sorte à empêcher la capture répétée de l'événement par les objets qui s’emboîtent les uns dans les autres et exécuter la même fonction plusieurs fois.

Exemple:
<!DOCTYPE html>
<html>
   <head>
      <meta charset="UTF-8" />
      <script language="javascript">
         function f(e){
            e.preventDefault();
         }
      </script>
   </head>
   <body>
      <a href="index.php" onClick="f(event)">Page d'accueil</a>
   </body>
</html>
L'objet event est passé à travers la fonction appelée sur l'objet en question.

Dans cet exemple, même si on clique sur le lien, il ne se passera rien. Par contre, en temps normal, on est censé être redirigé vers la page d'accueil (index.php).

Ce résultat peut être réussi sans faire appel à l'objet event. Voici le code:
<!DOCTYPE html>
<html>
   <head>
      <meta charset="UTF-8" />
   </head>
   <body>
      <a href="index.php" onClick="return false">Page d'accueil</a>
   </body>
</html>
L'instruction return false peut aussi empêcher le navigateur d'exécuter une action par défaut.

Attributs associées à event

Il existe plusieurs attributs pour l'objet event. Je vais énumérer ceux qui sont les plus utilisés en pratique:
  • clientX: retourne la position (coordonnée) horizontale du pointeur de la souris par rapport à la fenêtre du navigateur.
  • clientY: retourne la position verticale du pointeur de la souris par rapport à la fenêtre du navigateur. Notez que l'origine est le point haut à gauche.
  • screenX: retourne la position horizontale du pointeur de la souris par rapport à l'écran.
  • screenY: retourne la position verticale du pointeur de la souris par rapport à l'écran.
  • keyCode: retourne e code ASCII de la touche activée du clavier.
  • altKey: indique si la touche ALT du clavier est activé. Elle retourne une valeur booléenne.
  • shiftKey: indique si la touche SHIFT est activé. Elle retourne une valeur booléenne.
  • ctrlKey: indique si la touche CTRL est activé. Elle retourne une valeur booléenne.
  • button: indique sur quel bouton de la souris on a appuyé. 0 pour le bouton gauche, 1 pour le bouton central et 2 pour la bouton droit.
  • currentTarget: retourne l'élément (objet) qui a déclenché l'événement.
  • target: retourne l'élément (objet) enfant le plus profond (du plus bas niveau hiérarchique) survolé lors du déclenchement de l'événement.

Exemple:

Nous allons voir 4 façons de cibler le même objet HTML à l'aide de Javascript:

Première façon:
<!DOCTYPE html>
<html>
   <head>
      <meta charset="UTF-8" />
      <script language="javascript">
         function f(){
            alert(document.getElementById("bouton").getAttribute("value"));
         }
      </script>
   </head>
   <body>
      <input type="button" id="bouton" value="Actionner le bouton" onClick="f()" />
   </body>
</html>
Deuxième façon:
<!DOCTYPE html>
<html>
   <head>
      <meta charset="UTF-8" />
      <script language="javascript">
         function f(){
            alert(document.getElementsByTagName("input").item(0).getAttribute("value"));
         }
      </script>
   </head>
   <body>
      <input type="button" id="bouton" value="Actionner le bouton" onClick="f()" />
   </body>
</html>
Troisième façon:
<!DOCTYPE html>
<html>
   <head>
      <meta charset="UTF-8" />
      <script language="javascript">
         function f(objet){
            alert(objet.getAttribute("value"));
         }
      </script>
   </head>
   <body>
      <input type="button" id="bouton" value="Actionner le bouton" onClick="f(this)" />
   </body>
</html>
Quatrième façon:
<!DOCTYPE html>
<html>
   <head>
      <meta charset="UTF-8" />
      <script language="javascript">
         function f(e){
            alert(e.target.getAttribute("value"));
         }
      </script>
   </head>
   <body>
      <input type="button" id="bouton" value="Actionner le bouton" onClick="f(event)" />
   </body>
</html>
Pour cette dernière façon, il est parfois plus simple de remplacer target par currentTarget.

Sous-objet de l'objet event

Je ne vois qu'un seul sous-objet pour l'objet event. Il s'agit de dataTransfer qui s'avère très utile lors d'une opération de glisser-déposer (drag & drop).

L'objet dataTransfer dispose de plusieurs attributs et méthodes. Les plus importants sont:
  • effectAllowed: Cet attribut permet d'indiquer l'effet à appliquer à l'objet à glisser. Par exemple la valeur copy crée une copie de l'objet au moment de déposer celui-ci. Mais la valeur move reste la plus utilisée, car elle permet de déposer l'élément lui même et non pas une copie de lui.
  • setData(): Cette méthode permet de définir l'objet à glisser. Elle accepte deux paramètres: le type de donnée définissant l'objet (par exemple: text) et la donnée elle même (dont on vient de définir le type).
  • getData(): Cette méthode permet de récupérer la donnée définie par setData(). En paramètre, il suffit de renseigner le type (par exemple: text) pour récupérer la donnée.

Exemple: Drag & Drop

<!DOCTYPE html>
<html>
   <head>
      <meta charset="UTF-8" />
      <style>
         .zone{
            width:40%;
            height:300px;
            display:inline-block;
            margin:20px;
            padding:20px;
            border:solid 2px #EE6600;
         }
         #objet{
            width:100px;
            height:100px;
            background-color:#4444AA;
         }
      </style>
      <script language="javascript">
         function start(e){
            e.dataTransfer.effectAllowed="move";
            e.dataTransfer.setData("text",e.target.getAttribute("id"));
         }
         function over(){
            return false;
         }
         function drop(e){
            e.currentTarget.appendChild(document.getElementById(e.dataTransfer.getData("text")));
            e.stopPropagation();
            e.preventDefault();
         }
      </script>
   </head>
   <body>
      <div class="zone" onDragStart="start(event)">
         <div id="objet" draggable="true"></div>
      </div>
      <div class="zone" onDragOver="return over()" onDrop="drop(event)">
      </div>
   </body>
</html>
Résultat: faites glisser le rectangle bleu vers l'autre zone.
Le glisser-déspoer ne fonctionne que de la zone 1 vers la zone 2. Si vous voulez qu'il fonctionne dans les deux sens, il suffit de déclarer les trois événements (onDragStart, onDragOver et onDrop) sur les deux DIV. (Faites juste copier-coller, il n'y a rien de nouveau à définir).