Interactivité avec JavaScript

De EduTech Wiki
Aller à la navigation Aller à la recherche

Cet article est en construction: un auteur est en train de le modifier.

En principe, le ou les auteurs en question devraient bientôt présenter une meilleure version.



Introduction

Bien que JavaScript soit désormais un langage de programmation multi-purpose utilisé pour créer différents types d'applications, sa fonction primaire et la raison principale pour laquelle ce langage est aussi répandu concernent l'interactivité des pages web, ce qu'on appelle JavaScript côté-client.

Cette page complémente le Tutoriel JavaScript de base et le Tutoriel JavaScript côté client avec une approche plus ciblée sur l'interactivité qui est possible grâce à l'intégration entre JavaScript et le navigateur web. Plutôt que proposer un survol des aspects principaux, cette page illustre de manière plus approfondie et détaillée des examples de base pour mettre en relief le fonctionnement de l'interactivité à la fois d'un point de vue conceptuel et technique.

Prérequis

Pour lire cet article des connaissances de base de HTML5 et CSS sont nécessaires. Il faut également des notions sur les éléments fondamentaux de la programmation et la syntaxe de base de JavaScript (e.g. variables, fonctions, etc. - voir Tutoriel JavaScript de base).

Exemples traités dans l'article

Tous les exemples illustrés dans cette page sont disponibles dans un repository de GitHub. Ils suivent une numérotation qui sera utilisée pour les référencer également dans le texte, par exemple: 00-01.

Lorsque le code des exemples est expliqué dans l'article, pour des raisons d'espace, souvent seulement les parties indispensables à la compérhension du concept expliqué seront affichés. En général, les numéros des lignes intéressées sera fourni pour pouvoir repérer le code dans les fichiers, par exemple 00-01 Lignes 10-20.

Définition d'interactivité

Trois caractéristiques d'une application interactive qui utilise une interface utilisateur.

Malgré l'utilisation répandue du terme interactivité, il n'existe pas une définition unanime qui peut être appliquée dans les nombreux domaines dans lequel ce mot est utilisé. En général, il y a un certain accord, surtout dans le domaine de l'interaction homme-machine, à considérer l'interactivité en relation avec une interface utilisateur : une application est interactive du moment qu'elle permet à l'utilisateur, à travers des éléments identifiables sur l'interface et/ou des gestes à exécuter sur des périphériques (clavier, souris, écran tactile, ...), d'intervenir activement sur l'état de l'application. En termes plus simples, une application peut être considérée interactive si l'utilisateur peut de quelque sorte la modifier en fonction de ses propres actions.

Cette définition entraîne une série de conséquences conceptuelles et techniques qui dépassent l'objectif de cette page et qui concernent le vaste domaine de l'interaction homme-machine et l'expérience utilisateur. Néanmoins, d'un point de vue logique, cette définition comporte aux moins trois inferences qui seront utiles pour le reste de l'article. Ces inferences se réfèrent à l'état d'une application (ce qu'en anglais on appelle state). Pour faciliter la compréhension de ce concept, imaginez tout simplement de faire une capture d'écran à différents moments lorsque vous utilisez une application ou un site web. Chaque fois que vous avez une image différente, vous avez un état différent de l'application. Voici donc les trois inferences :

  1. L'interactivité présuppose le concept de variabilité
    Si l'état à un moment donné de l'application dépend de l'activité (ou non activité) de l'utilisateur, cela implique que l'application peut être différente de ce qu'elle est maintenant. Le plus une application est interactive, le plus d'états différents elle peut avoir à un moment donné suite aux décisions/interactions de l'utilisateur et/ou les états possibles envisagés par le concepteur.
  2. L'interactivité est liée à des événements
    Le concept de variabilité des états d'une application implique des changements qui se manifestent à des moments spécifiques, notamment suite aux actions de l'utilisateur. En informatique, les éléments responsables des changements dans l'état d'une application sont regroupés sous le terme de événements. De manière formelle, on peut définir un événements avec la formule Si p alors q, ce qui correspond à Pour que q s'avère, il faut que p se passe d'abord.
  3. L'interactivité défère le contrôle à l'utilisateur
    Parmi tous les événements possibles qui génèrent des changements dans l'état de l'application, pour qu'une application puisse être considérée interactive, il faut qu'au moins une partie de ces événements soient sous le contrôle directe de l'utilisateur. Le plus une application est interactive, le plus de contrôle l'utilisateur a sur les événements qui peuvent modifier l'application.
En résumé : une application interactive nécessité d'une certaine variabilité, déterminée par exemple par une série d'événements possibles, dont au moins certains sont sous le contrôle directe de l'utilisateur.

.

Principe technique de l'interactivité avec JavaScript

Le Document Object Model (DOM) d'une page web.

Dans une page web, l'interface utilisateur est représenté par le Document Object Model (DOM), c'est-à-dire la représentation en forme d'arborescence des noeuds/ balises HTML. Lorsque le navigateur télécharge une page web, il utilise le code source de cette page pour construire le DOM et l'afficher à l'écran en fonction d'éventuelles propriétés CSS qui déterminent le style des éléments HTML.

Or, dans une page web non dynamique, le code source qui est téléchargé n'a pas de variabilité potentielle, si ce n'est pour le fait que l'utilisateur peut pointer sur une autre page et donc répéter le même mécanisme de génération du DOM à partir de nouveau code source. Au contraire, si le code source de la page téléchargé contient des scripts JavaScript, alors ces scripts peuvent fournir au navigateurs les instructions nécessaires pour modifier le DOM et, par reflet, l'interface utilisateur.

Voici de suite trois pages similaires qui expliquent ce concept à l'aide des trois inferences introduites plus haut. À ce stade il ne faut comprendre leur code, mais plutôt le concept. Ouvrez les outils développeurs de votre navigateur et choisissez l'option qui vous permet de voir la représentation actuelle du DOM (pour Google Chrome cliquez sur F12 et puis sur le tab Elements). Comparez le code que vous voyez avec le code source de la page (en Chrome clique droit > Afficher le code source de la page).

  1. Page sans variabilité 00-01
    Il n'y a aucune différence (si ce n'est pour quelques détails marginaux) entre le code source et la représentation du DOM. Vous pouvez essayer de cliquer à différents endroits dans la page, mais aucune interactivité va se passer si ce n'est pour des comportements standard du navigateur (e.g. sélectionner du texte). L'interface utilisateur de cette page va rester la même jusqu'au moment où l'utilisateur ferme la page ou pointe vers une autre adresse.
  2. Page avec variabilité liée à un événement temporel 00-02
    Avec la page, vous téléchargez un script avec l'instruction d'afficher un nouveau paragraph chaque 5 seconds. Vous pouvez noter comme à des intervalles régulières, un nouveau noeud <p>...</p> s'ajouter à l'intérieur du <div id="injectTarget>...</div> qui, au départ, ne contient qu'un seul paragraphe. Ce type de variabilité n'est pas intéressante du tout et, surtout, est hors du contrôle de l'utilisateur qui ne peut pas arrêter le script si ce n'est en fermant la page ou pointant vers une autre adresse.
  3. Page avec variabilité liée à un événement déclenché par l'utilisateur 00-03
    Dans ce cas, en revanche, le script s'active lorsque l'utilisateur clique sur le bouton. Seulement à ce moment un nouveau paragraphe, et par reflet un nouveau noeud, s'ajoute à l'intérieur du <div id="injectTarget>...</div>.

Selon la définition de l'interactivité suggérée dans cet article, seulement la troisième page répond aux trois critères nécessaires :

  1. La page présente de la variabilité, avec potentiellement un nombre d'état "différents" infini. Bien entendu, d'un point de vue utilisateur, les états ne diffèrent pas vraiment, car on ajoute à chaque fois le même contenu. Néanmoins, du côté technique, ceci représente tout à fait un nouveau état, car on a à chaque fois une représentation du DOM différente de la précédente.
  2. La variabilité est déclenchée par un événement: le clique sur le bouton.
  3. C'est l'utilisateur qui décide si et quand cliquer sur ce bouton, en ayant ainsi le contrôle sur le comportement de l'application.
En résumé : l'interactivité avec JavaScript consiste dans le changement programmé du DOM à travers les instructions contenu dans un ou plusieurs scripts. Ces changements se reflètent dans la mise à jour de l'interface utilisateur affichée par le navigateur.

Exemples étape par étape

Nous allons présenter une série d'exemples, avec l'explication des passages étape par étape. Les exemples sont organisés en 4 sections :

  1. Boutons
    Introduction du principe de base de de l'interactivité à travers un simple bouton qui peut être cliqué par l'utilisateur. Le principe fondamentale de l'identification d'un élément et l'association à un gestionnaire d'événement sont les deux aspects principaux de cette section.
  2. Plusieurs boutons
    Extension de l'exemple précédent à plusieurs éléments en même temps. Nous allons généraliser le principe de l'identification à plusieurs boutons de manière programmé et verrons comment associer des comportements différents à travers la programmation.
  3. Input
    Gestion de l'information fourni par l'utilisateur. Nous allons traiter des interactions plus articulées par rapport au point-and-click, notamment à travers la saisie de texte.
  4. Form --> à voir si c'est vraiment utile
    Extension de l'exemple précédent à plusieurs éléments en même temps.

Pour chaque section, nous proposons en dernier exemple une petite application pédagogique qui synthétise les concepts expliqués.

Boutons

Nous allons commencer par créer un simple bouton sur lequel l'utilisateur peut cliquer et déclencher un comportement de l'application. Avant de voir l'exemple, il faut d'abord préciser que ce qu'on va faire avec un bouton peut s'appliquer à tout élément d'une page web et que le même principe s'adapte à d'autres types d'interactions (mouseover, mouseut, drag&drop, etc.).

Créer l'élément dans l'interface utilisateur

La première étape consiste tout simplement à créer physiquement le bouton sur la page. Même s'il y existe différentes manières pour le faire, nous allons utiliser la stratégie la plus simple : coder à la main le bouton à travers la balise HTML <button>...</button>. Voici le code complet de l'exemple 01-01

<!DOCTYPE html>
<html lang="en">

<head>
    <title>Interactive button 1/10</title>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
</head>

<body>
    <h1>Interactive button 1/10</h1>
    <!-- The first step is to determine an element that will be interactive. In this case, a button. But it can be wathever you want to. -->
    <button>I will be interactive</button>

</body>

</html>

Nous avons ajouté ici l'intégralité du code du fichier, même si la partie qui nous intéresse, dans ce cas, se limite au contenu du <body>...</body>. Par la suite nous allons montrer l'intégralité du code seulement si des changements ont été appliqués dans le <head>...</head>.

Comme vous pouvez le tester dans la page de l'exmple 01-01, nous avons tout simplement un bouton, dans le style de default de votre navigateur. En effet, le navigateur associe au bouton déjà certains comportement "interactifs" quand vous passez votre souris sur la surface du bouton ou quand vous le cliquez. Cependant, il ne se passe rien après le clique car, en tant que développeurs, nous n'avons pas fourni les instructions pour que le bouton réagisse au clique de l'utilisateur.

Ceci aurait été différent si, au lieu de <button>...</button>, on avait utilisé un lien hypertextuel <a href="http://tecfa.unige.ch>Tecfa</a>. Dans ce cas le navigateur associe automatiquement le comportement de pointer vers l'adresse fournie dans l'attribut href.

En règle général, les éléments n'ont de base aucun comportement interactif, à l'exception de certains balises dont le comportement est géré automatiquement par le navigateur.

Rendre le bouton identifiable

Une interface utilisateur ou une page web se composent généralement de plusieurs éléments, souvent plusieurs éléments du même "type" (e.g. plusieurs paragraphes, plusieurs boutons, etc.). Pour associer à un élément un comportement, il faut donc pouvoir le discriminer, l'identifier par rapport aux autres éléments qui composent l'interface. Ceci peut s'obtenir de différentes manières, nous allons utiliser ici la plus simple: associer un identificateur unique au bouton à travers l'attribut id="...". Voici le code de l'exemple 01-02

<h1>Interactive button 2/10</h1>
<!-- By default, only some specific element on a webpage (e.g. <a href="page.html">page</a>) are interactive -->
<!-- It is thus necessary to identify the element, the simple way is through the id attrbute -->
<button id="interactiveIdentifier">I will be interactive</button>

La valeur de l'attribut id="..." est arbitraire, vous pouvez utiliser ce que vous voulez. Mais c'est de bonne pratique d'utiliser des valeurs saillantes, qui vous permettent par la suite de savoir quel est l'intérêt/utilité de l'élément. Une bonne stratégie consiste à utiliser un identificateur qui donne des informations sur l'action que le bouton est censé faire plutôt que se référer à des caractéristiques de surface. Évitez donc des identificateurs de type id="boutonRouge", car vous pouvez changer d'avis sur la couleur de votre bouton, et utilisez plutôt des valeurs du type id="showMessageBtn" ou id="checkResponseBtn".

Pour qu'un élément soit interactif, il faut d'abord pouvoir l'identifier parmi d'autres éléments. La stratégie la plus simple est de lui donner un identificateur à travers un attribut id avec une valeur saillante, qui permet de deviner son utilité/comportement dans l'application.

Créer une référence au bouton en JavaScript

Une fois que l'élément peut être identifié, l'étape suivante consiste à l'intégrer dans un script. Pour ce faire, nous allons créer une variable (i.e. une boîte qui peut contenir différents choses) et lui affecter la référence à notre bouton. Pour créer la référence, nous allons justement nous servir de l'attribut id="interactiveIdentifier". Voici le code de l'exemple 01-03 :

<h1>Interactive button 3/10</h1>
<!-- Once the elemnt can be identified, you must create a reference to it in JavaScript -->
<button id="interactiveIdentifier">I will be interactive</button>

<!-- You need a script for it -->
<script>
    //Create a symbolic reference (i.e. a variable) to the HTML element
    var theButton = document.getElementById('interactiveIdentifier');
    //Show the reference in the console (open the console to see what it gives)
    console.log(theButton);
</script>

Le code qui nous intéresse plus en détail se trouve à l'intérieur de la balise <script>...</script> :

//Create a symbolic reference (i.e. a variable) to the HTML element
var theButton = document.getElementById('interactiveIdentifier');
//Show the reference in the console (open the console to see what it gives)
console.log(theButton);

Ce code fait deux choses :

  1. Il créer une référence symbolique (i.e. une variable) à notre bouton. Le bouton est identifié à travers la méthode document.getElementById('interactiveIdentifier')
  2. Il output à la console la valeur de la variable

La partie qui nous intéresse le plus est celle où on créer une référence symbolique au bouton. Il y a différentes manières pour le faire et selon le cas ce passage n'est même pas nécessaire, mais cela nous sert pour expliquer le concept illustré à l'image :

Créer une référence à un élément du DOM en JavaScript

Grâce au fait qu'on utilise la valeur de l'attribut id="interactiveIdentifier" en tant qu'argument de la méthode document.getElementById('interactiveIdentifier'), nous sommes maintenant en grès d'accéder à notre bouton dans un script. Pour praticité, nous avons utilisé une variable que nous avons nommés var theButton, mais comme il a été le cas pour l'attribut id, ce nom est arbitraire. Encore une fois, le choix de noms saillants facilite néanmoins la lisibilité et la compréhension de l'intentionalité du code.

Lorsque vous ouvrez la console de votre navigateur web dans la page de l'exemple 01-03, vous pouvez bien noter comme il s'affiche tout simplement le noeud HTML représenté par notre bouton :

La variable theButton est maintenant une référence exacte au noeud HTML représenté par le bouton.
Pour associer des comportements interactifs avec JavaScript, il faut pouvoir accéder à l'élément à l'intérieur d'un script. Nous avons exploité l'id du bouton pour l'identifier dans le document et créer une variable pour avoir une référence symbolique à l'élément.

Accéder aux informations du boutons à travers JavaScript

Une fois qu'on a une référence symbolique en JavaScript, on peut accéder aux informations de l'élément. D'abord, on va intégrer un peu de CSS pour styliser le bouton. Pour ce faire, nous allons associer une classe de style au bouton. Voici le code complet de l'exemple 01-04 :

<!DOCTYPE html>
<html lang="en">

<head>
    <title>Interactive button 4/10</title>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <!-- We add some styling to the button through CSS -->
    <style>
        .betterButtonInterface {
            background-color: #066;
            color: #FFF;
            font-size: 20px;
            padding: 5px 10px;
        }
    </style>
</head>

<body>
    <h1>Interactive button 4/10</h1>
    <!-- The interactive element -->
    <button id="interactiveIdentifier" class="betterButtonInterface">I will be interactive</button>

    <!-- You need a script for it -->
    <script>
        //Create a symbolic reference (i.e. a variable) to the HTML element
        var theButton = document.getElementById('interactiveIdentifier');
        //Show the reference in the console (open the console to see what it gives)
        console.log(theButton);
        //We can access the button attributes
        console.log(theButton.id);
        console.log(theButton.className);
        //But also its content
        console.log(theButton.innerHTML);
    </script>

</body>

</html>

Ce qui nous intéresse le plus dans ce code réside en réalité dans le output de la console de la page de l'exemple 01-04. Vous pouvez en effet noter comme à travers la variable theButton on peut récupérer en JavaScript des informations/caractéristiques du noeud/bouton :

  • theButton.id output interactiveIdentifier
  • theButton.className output betterButtonInterface (à noter que c'est className et non class, car class est un mot réservé)
  • theButton.innerHTML output le contenu du noeud, dans ce cas il s'agit simplement du texte/label du bouton I will be interactive
Une fois que nous avons une référence symbolique à un élément du DOM en JavaScript, on peut accéder à des informations/caractéristiques de cet élément.

Ajouter un gestionnaire d'événement

Jusqu'à présent, nous avons ajouté une référence symbolique dans le script et améliorer (vaguement) le style du bouton, mais nous n'avons toujours pas d'interactivité. Il nous faut que le navigateur puisse, parmi tous les cliques possibles sur la page, écouter en particulier les cliques qui sont faits sur la surface de notre bouton. C'est le rôle du gestionnaire d'événement. Voici le code de l'exemple 01-05 :

<h1>Interactive button 5/10</h1>
<!-- The interactive element -->
<button id="interactiveIdentifier" class="betterButtonInterface">I am interactive now!</button>

<!-- You need a script for it -->
<script>
//Create a symbolic reference (i.e. a variable) to the HTML element
var theButton = document.getElementById('interactiveIdentifier');
//Add a listener that just print a message when the button is clicked
theButton.addEventListener('click', function () {
     console.log('theButton has been clicked!');
});
</script>

La partie qui nous intéresse est encore une fois à l'intérieur du tag <script>...</script>, où on retrouve la variable theButton associée à la référence au noeud/bouton, mais en plus cette fois-ci nous avons ajouté le gestionnaire d'événements :

//Create a symbolic reference (i.e. a variable) to the HTML element
var theButton = document.getElementById('interactiveIdentifier');
//Add a listener that just print a message when the button is clicked
theButton.addEventListener('click', function () {
     console.log('theButton has been clicked!');
});

Le code s'explique de la manière suivante :

  1. On réutilise la variable theButton pour exploiter la référence symbolique à notre bouton. Il s'agit tout simplement d'un raccourci, on aurait pu réutiliser document.getElementById('interactiveIdentifier') à la place, mais comme ça c'est plus simple et cela nous permet éventuellement par la suite de réutiliser theButton également ailleurs.
  2. On associe à theButton la méthode addEventListener() qui accepte deux paramètres :
    1. Le type d'événement que nous voulons écouter, dans ce cas click
    2. Une fonction qui est déclenchée lorsque cet événement s'avère. Dans ce cas, nous utilisons une fonction anonyme (i.e. déclarée exactement à l'endroit où elle est appelée), mais on aurait pu également faire autrement.
  3. À l'intérieur de cette fonction, nous avons ajouté le code qui doit être exécutée à chaque fois que l'événement click s'avère. Dans ce cas spécifique, il s'agit d'un simple console.log() qui va confirmer en console que le gestionnaire d'événement a bien marché.

L'image suivante résumé de manière graphique ce principe :

Explication d'un gestionnaire d'événement.

Vous pouvez essayer de cliquer le bouton sur la page de l'exemple 01-05 en ouvrant la console du navigateur : chaque fois qu'on clique sur le bouton, le chiffre à côté du message theButton has been clicked! va augmenter.

Important : pour rendre un élément interactif il faut lui associer un gestionnaire d'événements. Ce gestionnaire à deux fonctions principales : (1) identifier le type d'événement spécifique (e.g. click, mouseover, ...), et (2) déterminer quelle fonction (i.e. quelles instructions) doit être exécutée à chaque fois que l'événement s'avère.

Ajouter un gestionnaire d'événement (syntaxe alternative)

En programmation il y a toujours moyen de faire la même chose de manière différente. Nous proposons ici une syntaxe alternative, mais moins conseillée, pour obtenir exactement le même résultat de l'exemple précédent. Voici le code le code de l'exemple 01-06, limité au contenu de la balise <script>...</script> :

//Create a symbolic reference (i.e. a variable) to the HTML element
var theButton = document.getElementById('interactiveIdentifier');
//Add a listener that just print a message when the button is clicked (alternative syntaxe)
theButton.onclick = function () {
    console.log('theButton has been clicked!');
};

Le principe est le même :

  1. On identifie un événement, cette fois-ci avec la notation theButton.onclick
  2. On associe à cet événement une fonction anonyme function () { ... }
  3. À l'intérieur de cette fonction, nous plaçons les instructions à exécuter. Dans ce cas, un simple console.log()
On peut ajouter un gestionnaire d'événement avec une syntaxe alternative, mais addEventListener() reste la meilleure option.

Montrer un feedback après le clique du bouton

À ce point, nous avons techniquement un bouton interactif. Cependant, du côté de l'utilisateur, il n'y a rien qui suggère que quelque chose se passe lorsqu'on a cliqué sur le bouton. Du point de vue expérience utilisateur, donc, il est nécessaire que l'algorithme associé au gestionnaire d'événement produise une variation dans l'interface dont l'utilisateur puisse s'apercevoir. C'est ce qu'on va faire avec l'exemple 01-06. Nous allons modifier le contenu d'un noeud que nous allons identifier, tout comme on a fait pour le bouton, à travers l'attribut id="..." :

<h1>Interactive button 7/10</h1>
<!-- The interactive element -->
<button id="interactiveIdentifier" class="betterButtonInterface">I am interactive now!</button>

<!-- If we want to change some element in the DOM after the interaction, we need to identify it (as it was for the button) -->
<p id="elementToChange">I will be changed!</p>

<!-- You need a script for it -->
<script>
//Create a symbolic reference (i.e. a variable) to the INTERACTIVE HTML element
var theButton = document.getElementById('interactiveIdentifier');
//Create a symbolic reference to the ELEMENT TO CHANGE after the interaction
var theOutput = document.getElementById('elementToChange');
//Add a listener that modifies the content of the paragraph
theButton.addEventListener('click', function () {
    //Inside the function we give the instruction to change the content of the paragraph
    theOutput.innerHTML = 'I have been changed through the interaction!';
});
</script>

Lorsqu'on clique sur le bouton dans la page de l'exemple 01-07, on peut s'apercevoir que le texte I will be changed devient I have been changed through the interaction!. Pour obtenir ce simple résultat nous avons :

  1. Ajouté un paragraph avec attribut id="elementToChange pour pouvoir l'identifier dans le script
  2. Créé une référence symbolique à ce noeud à traves var theOutput = document.getElementById('elementToChange'). Encore une fois, le nom de cette variable est arbitraire et devrait suivre plutôt des règles de nomenclature sémantique comme nous avons suggéré plus haut.
  3. Injecté dans la fonction déclenchée par le gestionnaire d'événement une instruction qui permet de modifier le contenu du noeud avec theOutput.innerHTML = 'I have been changed through the interaction!';

L'image suivante représente graphiquement ce processus.

Modification du contenu d'un noeud suite au déclenchement d'un événement.
Important : si on veut modifier un élément de l'interface suite à un événement, il faudra l'identifier pour pouvoir y accéder dans le script, et ensuite insérer à l'intérieur du gestionnaire d'événement une instruction qui modifie l'élément, ainsi que cette instruction soit exécutée seulement lorsque l'événement s'avère.

Ajouter plusieurs manipulations au gestionnaire d'événement

Dans l'exemple précédent, notre gestionnaire d'événement se limite à exécuter une seule instruction lorsqu'il est déclenché. Ceci n'est certainement pas une contrainte, il est tout à fait possible, et d'ailleurs intéressant, de exécuter plusieurs instructions à la fois. Voici le code, limité au contenu de la balise <script>...</script> pour l'exemple 01-08 :

//Create a symbolic reference (i.e. a variable) to the INTERACTIVE HTML element
var theButton = document.getElementById('interactiveIdentifier');
//Create a symbolic reference to the ELEMENT TO CHANGE after the interaction
var theOutput = document.getElementById('elementToChange');
//Add a listener that modifies the content and style of the paragraph, as well as the button itself
theButton.addEventListener('click', function () {
     //You can have multiple istructions inside the event handler
     theOutput.innerHTML = 'I have been changed through the interaction!';
     //You can change the interactive element itself
     theButton.innerHTML = 'I have been clicked!';
     //You can change the style of an element
     theOutput.style.backgroundColor = '#000';
     theOutput.style.color = '#FFF';
     theOutput.style.fontSize = '20px';
});

Comme vous pouvez le noter sur la page de l'exemple 01-08, lorsque vous cliquez sur le bouton il y différents changements qui concernent à la fois le paragraphe de feedback, mais également la labellisation du bouton lui-même qui change de I am interactive now à I have been clicked.

À l'intérieur de la fonction associée au gestionnaire d'événements on peut en effet mettre autant d'instructions dont on a besoin et on peut faire référence à l'intérieur de cette fonction à tous les éléments qu'on peut identifier. Dans ce cas, nous utilisons les références symboliques aux éléments theButton et theOutput, mais rien n'empêche d'identifier les éléments directement à l'intérieur de la fonction. Il s'agit encore une fois d'une question d'organisation du code.

Comparé à l'exemple précédent, nous utilisons encore une fois .innerHTML = "..." pour modifier le contenu des noeuds référencé par les deux variables. De plus, pour theOutput nous avons expoité la possibilité d'utiliser .style.propriété pour modifier certaines caractéristiques de style du paragraphe comme la couleur du texte et du fond, ainsi que la taille de la police. Veuillez noter que les noms des propriétés n'est pas exactement celle qui est utilisée dans les CSS (fontSize au lieu de font-size, backgroundColor au lieu de background-color) pour respecter les règles syntaxique de JavaScript.

Un événement peut déclencher plusieurs changements au niveau de l'interface utilisateur. Pour ce faire, il suffit que tous les changements soient définis à l'intérieur de la fonction associée au gestionnaire d'événements.

Ajouter de la logique computationnelle au gestionnaire d'événement

Dans la fonction qui réagit au gestionnaire d'événement, nous pouvons injecter toute sorte de logique computationnelle, par exemple pour réagir différemment en fonction de certaines variables. Dans l'exemple 01-09 nous ajoutons une simple instruction de contrôle qui définit le type de feedback à montrer :

  • S'il est plus tôt que midi, l'output est Good morning!
  • Autrement l'output sera Good afternoon!

Le code qui nous intéresse est limité à l'intérieur du <script>...</script> :

//Create a symbolic reference (i.e. a variable) to the INTERACTIVE HTML element
var theButton = document.getElementById('interactiveIdentifier');
//Create a symbolic reference to the ELEMENT TO CHANGE after the interaction
var theOutput = document.getElementById('elementToChange');
//Add a listener that perform some basic logic
theButton.addEventListener('click', function () {
     //You can add some computational logic inside the event listener
     //These instructions check the current time and modify the content of the paragraph depending if it is morning or afternoon
     var now = new Date().getHours();
     if (now < 12) {
           theOutput.innerHTML = '<strong>Good morning!</strong>'
     } else {
            theOutput.innerHTML = '<strong>Good afternoon!</strong>'
     }
});

Grâce à l'intégration de la structure de contrôle, nous avons augmenté la variabilité de notre application mais sans augmenter le nombre d'interactions possibles : l'utilisateur est toujours limité à la seule possibilité de cliquer, ou pas, sur le bouton. En fonction de l'heure dans laquelle vous visitez la page avec l'exemple 00-09, vous allez obtenir un output différent qui s'affiche dans le paragraphe.

La fonction qui est associée au gestionnaire d'événement peut exécuter toute type de logique, de la plus simple à la plus complexe, et augmenter donc la variabilité de l'application avec le même type d'interaction.

Exemple d'application pédagogique

Dans les exemples précédents, nous avons abordé les principes de l'interaction avec l'explication de cas très simple. Dans tout ce cas, les utilisateurs avaient à disposition fondamentalement seulement un type de variation possible lorsqu'ils cliquaient le bouton, à l'exclusion du cas d'un utilisateur qui clique une première fois sur le bouton de l'exemple autour de 11:59 et attend jusqu'à midi pour cliquer la deuxième fois. Dans les autres cas, l'utilisateur ne va pas détecter aucune variation ultérieure sur l'interface utilisateur après le premier clique sur le bouton.

Dans le dernier exemple de cette section, nous allons complexifier légèrement la logique de la fonction associée au gestionnaire d'événement pour créer un canevas d'application avec finalité pédagogique. Chaque fois que l'utilisateur clique sur le bouton, l'interface utilisateur lui propose de dire entre 1 et 10 mots qui commencent avec une lettre au hasard de l’alphabète. L'interface ne propose pas la possibilité de saisir les mots (on verra comment traiter les inputs de l'utilisateur dans la section correspondante plus bas), mais néanmoins nous avons une petite application qui peut servir à tester/améliorer les capacités langagières d'une personne. Dans ce dernier cas, il est peut être utile de tester l'exemple avant de voir son code : page de l'exemple 01-10.

Voici le code complet de l'exemple 01-10, car nous avons ajouté quelques déclarations de style pour améliorer l'interface :

<!DOCTYPE html>
<html lang="en">

<head>
    <title>Interactive button 10/10</title>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <!-- We add some styling to the button and the output through CSS -->
    <style>
        .betterButtonInterface {
            background-color: #066;
            color: #FFF;
            font-size: 20px;
            padding: 5px 10px;
        }

        .message {
            font-size: 50px;
            letter-spacing: 5px;
            font-family: Courier New, Courier, monospace;
            padding: 10px 25px;
            text-align: center;
        }

        .message strong {
            font-size: 90px;
        }
    </style>
</head>

<body>
    <h1>Interactive button 10/10</h1>
    <p>This simple game aims at improving your vocabulary. You will be asked to say aloud a number of words beginning with a
        given letter.</p>
    <!-- The interactive element -->
    <button id="interactiveIdentifier" class="betterButtonInterface">Play!</button>

    <!-- If we want to change some element in the DOM after the interaction, we need to identify it (as it was for the button) -->
    <p id="elementToChange" class="message"></p>

    <!-- You need a script for it -->
    <script>
        //Create a symbolic reference (i.e. a variable) to the INTERACTIVE HTML element
        var theButton = document.getElementById('interactiveIdentifier');
        //Create a symbolic reference to the ELEMENT TO CHANGE after the interaction
        var theOutput = document.getElementById('elementToChange');
        //Define some functions that perform some logic

        //Generate a random number between 1 and 10
        function generateRandomNumber() {
            return Math.floor(Math.random() * 10) + 1;
        }

        //Generate a random letter a-z
        function generateRandomLetter() {
            return String.fromCharCode(97 + Math.floor(Math.random() * 26));
        }
        //Add a listener that return an alphanumeric string
        theButton.addEventListener('click', function () {
            //You can add more complex logic calling functions inside the event listener

            theOutput.innerHTML = 'Say <strong>' + generateRandomNumber() +
                '</strong> word(s) beginning with <strong>' + generateRandomLetter() + '</strong>';

        });
    </script>

</body>

</html>

Comparé aux exemples précédents, il n'y a aucun changement substantiel au niveau de l'interface utilisateur du départ. Nous avons toujours un bouton et un paragraphe de output comme éléments nécessaire à l'interactivité. Nous avons ajouté une simple, mais insuffisante, introduction à la tâche (i.e. depuis l'instruction on ne comprend pas qu'on peut obtenir des nouvelles consignes en cliquant encore sur le bouton). La partie qui nous intéresse est donc contenue à l'intérieur de la balise <script>...</script> :

//Create a symbolic reference (i.e. a variable) to the INTERACTIVE HTML element
var theButton = document.getElementById('interactiveIdentifier');
//Create a symbolic reference to the ELEMENT TO CHANGE after the interaction
var theOutput = document.getElementById('elementToChange');
//Define some functions that perform some logic

//Generate a random number between 1 and 10
function generateRandomNumber() {
   return Math.floor(Math.random() * 10) + 1;
}

//Generate a random letter a-z
function generateRandomLetter() {
    return String.fromCharCode(97 + Math.floor(Math.random() * 26));
}
//Add a listener that return an alphanumeric string
theButton.addEventListener('click', function () {
    //You can add more complex logic calling functions inside the event listener

    theOutput.innerHTML = 'Say <strong>' + generateRandomNumber() +
                '</strong> word(s) beginning with <strong>' + generateRandomLetter() + '</strong>';

});

Si on analyse ce code, on peut s'apercevoir que la structure est restée similaire aux exemples précédents. Nous identifions toujours le bouton et le paragraphe, et par la suite ajoutons un gestionnaire d'événements au bouton. En considération du fait que la logique de notre application s'est un peu complexifiée, nous avons déclaré deux fonctions en dehors du gestionnaire d'événement que nous allons par la suite appeler à son intérieur :

  1. function generateRandomNumber() { ... } qui génère un chiffre aléatoire entre 1 et 10
  2. function generateRandomLetter() { ... } qui génère une lettre entre a et a

La logique interne de ces fonctions dépasse l'objectif de cette page. Nous pouvons tout simplement en faire abstraction et faire confiance à ce qui est écrit dans les commentaires du code. Chaque fois qu'on appelle generateRandomNumber() nous aurons un nombre 1-10, et chaque fois qu'on appelle generateRandomLetter() une lettre a-z.

À ce point, nous pouvons intégrer les deux fonctions à l'intérieur de la fonction associée au gestionnaire d'événement pour déterminer le output du paragraphe dans lequel afficher la consigne avec le nombre des mots à dire qui commencent avec la lettre aléatoirement choisie :

//You can add more complex logic calling functions inside the event listener

theOutput.innerHTML = 'Say <strong>' + generateRandomNumber() +
                '</strong> word(s) beginning with <strong>' + generateRandomLetter() + '</strong>';

Nous avons utilisé une simple concatenation à l'aide de l'opérateur + pour insérer d'abord le nombre et ensuite la lettre aléatoire dans la phrase qui sera affiché en tant que contenu du noeud/paragraphe theOutput.

Grâce aux deux fonctions qui génèrent un chiffre ou une lettre aléatoire, notre application maintenant dispose d'une grande variabilité, assurée par la probabilité de tomber sur une l'une des 260 combinaisons possibles, tout en gardant une seule interaction sur l'interface utilisateur. Il y des bonnes chances, donc, que l'utilisateur se retrouve avec un état différent à chaque fois qu'il clique sur le bouton. Ce qui, en termes pédagogiques, représente à la fois un challenge est une motivation à utiliser plus souvent l'application car il est "impossible de finir le jeu".

Important: lorsque la logique interne de l'application se complexifie, il est bien de la décomposer en morceaux plus petits en utilisant plusieurs fonctions qui sont par la suite appelée à l'intérieur du gestionnaire d'événements. Si on exploite dans ces fonctions la capacité des ordinateurs à générer des éléments aléatoires, on peut facilement ajouter une grande variabilité même à une interaction simple comme le clique d'un bouton.

Plusieurs boutons

Dans cette section, nous allons appliquer les concepts abordés lors de la section précédente à plusieurs boutons en même temps. L'un des avantages de la programmation est en effet la capacité des ordinateurs à répéter la même opération (ou des opérations assez similaires) de manière vite, efficace et pour un grand nombre de fois, ce qui n'est pas le cas des humains qui ont une tendance naturelle à s'ennuyer assez vite dans les tâches répétitives.

L'interface utilisateur va rester très similaires aux exemples de la section 1 : il y aura toujours une zone de output où afficher des changements suite aux interactions, mais au lieu d'un seule bouton, nous en aurons plusieurs.

Dans cette section et les suivantes, nous considérons certains aspects illustrés dans la première section comme acquis. En conséquence, nous allons réduire les explications aux aspects du code les plus importants. Si des aspects ne sont pas claires, nous vous conseillons de revoir les exemples de la section 1.

Identifier plusieurs boutons sur l'interface utilisateur

Dans ce premier exemple, nous allons voir comment sélectionner plusieurs boutons qui sont présent sur l'interface utilisateur. Encore plus que dans le premier exemple, où on avait un seule bouton, il existe différentes manières pour générer plusieurs boutons. Pour garder cet exemple simple, nous allons encore une fois les codes "à la main" avec des noeuds HTML de type <button>...</button>. Voici le contenu du <body>... de l'exemple 02-01 :

<h1>Multiple buttons 1/5</h1>
<!-- If you have multiple interactive elements, you can't use the id attribute, which is meant to be unique -->
<!-- You can use a class or an attribute to select multiple elements -->
<ul>
    <li>
        <button class="interactiveElement">First interactive button</button>
    </li>
    <li>
        <button class="interactiveElement">Second interactive button</button>
    </li>
    <li>
        <button class="interactiveElement">Third interactive button</button>
    </li>
    <li>
        <button>A button, but not interactive</button>
    </li>
</ul>
<!-- Define an output element -->
<p id="elementToChange">No button clicked yet!</p>
<!-- The instructions through the script -->
<script>
    //Select all buttons with class="interactiveElement"
    var theButtons = document.querySelectorAll('.interactiveElement');
    //Log the content of the theButtons variable, which is a list of Nodes
    console.log(theButtons);
</script>

Plutôt que de créer 3 références symboliques à chaque boutons individuellement avec trois fois la méthode document.getElementById("..."), nous avons sélectionné les boutons à l'aide de leur attribut class="interactiveElement en utilisant la méthode document.querySelectorAll('.interactiveElement'). Cette méthode accepte tous les sélecteurs CSS, et donc grâce au .interactiveElement en argument, tous les éléments avec cette classe seront sélectionnés et stockés dans la référence symbolique theButtons.

La sélection multiple s'applique à tous les éléments qui répondent au critères de sélection, dans ce cas class="interactiveElement"

Vous pouvez bien noter depuis le code que seulement les trois premiers boutons de la liste possèdent cet attribut, mais pas le quatrième. En conséquence, si vous ouvrez la console sur la page de l'exemple 02-01, vous allez obtenir ce résultat :

Lorsque l'identification des éléments concernent plusieurs noeuds, le résultat est une liste de noeuds.

Contrairement aux exemple de la section 1, où la référence symbolique theButton représentait le HTML du noeud/button, theButtons représente une liste de noeuds. Comme vous pouvez le voir depuis le output de la console, cette liste contient en effet 3 noeuds et même si une liste de noeud n'est pas vraiment un array (c.f. Tutoriel JavaScript côté client), la numération des noeuds commence à 0. Si vous saisissez donc theButtons[0] dans votre console, vous allez obtenir seulement le premier bouton, et donc un output tout à fait similaire à l'exemple de la section 1 :

<button class="interactiveElement">First interactive button</button>
Important: pour sélectionner plusieurs éléments en même temps, on peut exploiter la méthode querySelectorAll(), en utilisant par exemple l'attribut class des éléments. Tous les éléments qui répondent aux critères de sélection sont insérés dans une liste de noeuds, qui n'est pas exactement un array, mais dont la numération commence à 0 et par conséquent les éléments de la liste peuvent être extrait avec la notation nomDeLaListe[0], nomDeLaListe[1], ...

Faire une itération entre les noeuds/boutons

Ajouter un gestionnaire d'événements à chaque bouton

Afficher un feedback lorsqu'on clique sur chaque bouton

Exemple d'application pédagogique

Input

Form

Bibliographie