VA
Comment lire ce livre ? Qui sommes nous ?
I. PAGES WEB
II. SERVEUR WEB
III. BASES DE DONNEES
IV. INTERACTION FRONT-BACK
Annexe I. ENSEIGNEMENT NSI
Annexe II. LES FRAMEWORKS

Chapitre 9 - Gestion des événements en Javascript

Les navigateurs peuvent exécuter du code Javascript dans une page web et ainsi supporter des interactions riches et complexes. Il est par exemple possible possible de faire apparaître ou disparaître des éléments d'une page lorsqu'on clique sur un bouton, de faire afficher de nouvelles informations lorsqu'on scrolle la page vers le bas, de remplir automatiquement des champs d'un formulaire en fonction des premiers éléments saisis, ou même d'envoyer régulièrement des requêtes HTTP en tâche de fond afin de mettre à jour la page web de manière silencieuse.

Ce chapitre présente la façon de coder en Javascript ces interactions dans le navigateur. Nous expliquons comment manipuler une page web en Javascript et comment déclencher des traitements en fonction d'événements utilisateur.

Javacript dans le Navigateur

Tous les navigateurs web associent un environnement Javascript unique et indépendant à chacune des pages web qu'ils affichent. A chaque fois que le navigateur charge une page il créé un nouvel environnement Javascript qui est dédié à cette page. Cet environnement dispose de sa propre mémoire et de son propre moteur d'exécution.

Les outils du développeur intégrés dans les navigateurs web proposent un accès à cet environnement Javascript. Grâce à la console il est même possible d'exécuter du code Javascript dans l'environnement associé à la page web courante. Par exemple, la Figure 9.1 présente l'affichage d'une page web avec des instructions Javascript exécutées dans la console Javascript du navigateur (1+1, let message = 'je peux exécuter du code' et console.log(message)). Les instructions qui ont été exécutées ici sont des instructions Javascript classiques. Une variable a été créée (la variable message). Elle reste accessible dans l'environnement tant qu'une autre page web n'est pas rechargée. En effet le chargement d'une nouvelle page aura pour conséquence de construire un environnement neuf dans lequel cette variable n'existera plus.

Alt Text

Figure 9.1 : La console Javascript dans les outils du développeur avec quelques instructions exécutées.

L'environnement Javascript associé à une page web est cloisonné à la page pour laquelle il a été créé. De fait, il n'a pas accès aux environnements des autres pages qui seraient ouvertes et affichées par le navigateur. Il n'a pas non plus accès au contenu du disque dur ou à d'autres ressources de l'ordinateur. Enfin, pour garantir un haut niveau de sécurité, l'environnement permet uniquement d'envoyer des requêtes HTTP vers le serveur qui a fourni la page actuelle ou vers les ressources référencées par cette page actuelle (voir fin du chapitre pour plus de précision).

Les objets "window" et "document" de l'API DOM

L'environnement Javascript associé à une page web est initialisé avec plusieurs objets Javascript qui permettent de manipuler la page affichée. Ces objets sont accessibles grâce à l'API DOM (Document Object Model) qui est une interface de programmation standardisée par le W3C. Notre objectif ici n'est pas de décrire en détail l'API DOM mais d'illustrer son exploitation pour manipuler une page web en consultation et en modification. Une lecture plus attentive de la documentation permettra de découvrir tous les objets et fonctions proposés.

Nous commençons la présentation de l'API DOM par l'objet window qui est particulièrement important. Celui-ci représente la fenêtre du navigateur qui affiche la page web. Cet objet propose plusieurs propriétés qui permettent d'obtenir des informations sur la fenêtre et sur la page affichée. Le Code 9.1 présente certaines de ces propriétés en expliquant leur signification. On voit qu'il est possible de connaître la taille de la fenêtre, l'URL de la page et quelques informations sur le navigateur. On voit aussi qu'il est possible d'accéder au document HTML de la page via la propriété document.

window.innerHeight // Hauteur de la fenêtre
window.innerWidth // Largeur de la fenêtre
window.location // URL de la page
window.navigator // Informations sur le navigateur
window.screen // Informations sur l'écran
window.document // Document HTML de la page

Code 9.1 : Quelques propriétés de l'objet window.

La propriété document de l'objet window référence un objet qui représente le document HTML de la page affichée. Cet objet est directement accessible dans l'environnement Javascript : c'est l'objet document. L'objet document propose de nombreuses propriétés et méthodes qui permettent de manipuler le document HTML. Il propose la propriété body qui permet d'accéder au corps du document HTML (balise <body>). Il propose aussi la propriété head qui permet d'accéder à l'en-tête du document HTML (balise <head>).

Visiter une page web

Tous les éléments du document HTML d'une page web sont représentés par des objets Javascript. Ceux-ci sont structurés sous forme d'un arbre qui reflète la structure du document HTML. Pour accéder à ces objets il faut parcourir cette structure arborescente à partir de l'objet document. Plus précisément il faut utiliser la propriété children qui permet d'obtenir la liste des enfants d'un élément quel qu'il soit. Ainsi document.children permet d'accéder aux enfants de <html>. De même, document.body.children permet d'accéder aux enfants de <body>. La propriété children est un tableau qui contient les enfants dans l'ordre dans lequel ils apparaissent dans le document HTML. Il est donc possible d'accéder à un enfant particulier en utilisant son indice dans le tableau. Par exemple, document.body.children[0] permet d'accéder au premier enfant de <body>.

Le Code 9.2 présente un exemple de document HTML et le Code 9.3 montre comment accéder à des éléments HTML en parcourant l'arbre des éléments. On voit par exemple qu'il est possible d'accéder à la première image en utilisant l'expression document.body.children[1].children[0] (attention le premier enfant a l'indice 0).

<html>
    <head>
        <title>Page exemple</title>
    </head>
    <body>
        <h1>Titre</h1>
        <div id="images">
            <img src="/public/images/image1.png">
            <img src="/public/images/image2.png">
        </div>
        <div id="commentaires">
            <div class="commentaire">Très belle image</div>
        <div>
    </body>
</html>

Code 9.2 : Exemple de document HTML.

document.body.children[0] // Accès à <h1>
document.body.children[1] // Accès à <div id="images">
document.body.children[1].children[0] // Accès au premier fils de <div id="images">, c'est à dire à la première image

Code 9.3 : Accéder à des éléments HTML en parcourant l'arbre des éléments.

Parcourir l'arbre des éléments HTML peut être fastidieux. Il faut en effet connaître la structure du document HTML pour pouvoir accéder à un élément particulier. Une autre façon consiste à utiliser des méthodes d'accéder aux éléments en fonction de leur attribut id ou de leur classe CSS. La méthode getElementById permet par exemple d'accéder à un élément HTML en fonction de son attribut id. La méthode getElementsByClassName permet quant à elle d'accéder à un ensemble d'éléments en fonction de leur classe CSS. Il existe aussi les méthodes querySelector et querySelectorAll qui permettent d'accéder à des éléments en donnant un sélecteur CSS. Ces méthodes sont utilisables sur l'objet document mais aussi sur tous les autres éléments HTML. Elles effectuent une recherche d'éléments à partir de l'élément sur lequel elles sont appelées. Par exemple document.getElementById("images") est un appel de la méthode getElementById sur l'élément document. Cela permet de chercher un élément qui a l'attribut id égal à images à partir de l'élément document qui est la racine de la page HTML. L'exemple document.body.children[1].querySelectorAll("img") est un appel de la méthode querySelectorAll sur l'élément document.body.children[1]. Cela permet la recherche de tous les éléments <img> à partir du deuxième enfant de l'élément <body>.

Notons qu'il est possible de chainer les méthodes d'accès aux éléments. Par exemple document.getElementById("images").querySelectorAll("img") est un appel de la méthode querySelectorAll sur l'élément retourné par l'appel de la méthode getElementById sur l'élément document. Cela permet de rechercher d'abord l'élément qui a l'attribut id égal à images à partir de document, puis, à partir de cet élément, tous les éléments <img>. Le Code 9.4 présente un exemple d'utilisation de ces méthodes.

document.getElementById("images") // Accès à la balise <div id="images">
document.getElementsByClassName("commentaire") // Accès aux balise <div class="commentaire">
document.querySelector("#images") // Accès à la balise <div id="images">
document.querySelectorAll(".commentaire") // Accès aux balise <div class="commentaire">
document.getElementById("images").querySelectorAll("img") // Accès aux balise <img> à partir de la balise <div id="images">
document.getElementById("images").children[0] // Accès au premier fils à partir de de l'élément <div id="images">

Code 9.4 : Accéder aux éléments grâce aux méthode d'accès.

Dès qu'on accède à un élément en Javascript, il est possible de tout connaître sur lui. On peut par exemple consulter la propriété src d'un élément <img> pour connaître l'URL de l'image cible. On peut aussi consulter la propriété href d'un élément <a> pour connaître l'URL de la page cible. Il y a de nombreuses propriétés consultables qui dépendent du type de l'élément HTML. Il y a néanmoins des propriétés communes à tous les éléments HTML (voir la documentation : https://www.w3schools.com/jsref/dom_obj_all.asp). C'est le cas par exemple de la propriété innerHTML qui permet de consulter le contenu HTML d'un élément (en format texte). Le code 9.5 présente un exemple d'utilisation de ces propriétés et méthodes. Cet exemple cherche l'élément qui a images comme id, puis à partir de celui-ci, cherche tous les éléments <img>, pour afficher leur URL cible (propriété src).

let imagesDiv = document.getElementById("images");
let images = imagesDiv.querySelectorAll("img");
for (let i = 0; i < images.length; i++) {
    if (images[i].src) {
        console.log(src);
    }
}

Code 9.5 : Accès aux images et affichage des URLs cibles.

Modifier une page web

L'accès aux éléments et à leurs propriétés peut se faire en consultation mais aussi en modification. Il est ainsi possible de modifier le contenu d'un élément en changeant les valeurs de ses propriétés.

Il faut comprendre que changer la valeur d'une propriété d'un élément a pour conséquence de demander au navigateur de refaire le painting de la page et donc de charger les ressources nécessaires pour y arriver. Ainsi, si on change la propriété src d'un élément <img> et qu'on donne une nouvelle cible d'image, le navigateur va charger la nouvelle image cible et la remplacer dans la page.

Le Code 9.6 présente un exemple de modification des URLs cibles des images. Ce code itère sur toutes les images contenues dans la balise <div id="images"> et remplace leur propriété src pour faire en sorte que les images à afficher soient les miniatures (small). Il faut noter que ce code va demander au navigateur de refaire le painting à chaque itération. Cela peut être problématique si le nombre d'images est important. Il serait plus intéressant de faire un unique painting après le changement de toutes les images ce qui est beaucoup plus compliqué à réaliser.

let imagesDiv = document.getElementById("images");
let images = imagesDiv.querySelectorAll("img");
for (let i = 0; i < images.length; i++) {
    if (images[i].src) {
        images[i].src = '/public/images/image'+i+'_small.png';
    }
}

Code 9.6 : Modification des URLs cibles des images.

Il est aussi possible de modifier les valeurs des propriétés children ou innerHTML pour changer drastiquement la structure d'une page web. Là encore, ces changements vont entrainer un nouveau painting de la page et donc le chargement de nouvelles ressources. Le Code 9.7 présente un exemple de modification de la structure d'une page web. Appliqué sur le Code 9.2, ce code remplace le contenu de la balise <div id="images"> par <p>Toutes les images ont été supprimées</p>.

let imagesDiv = document.getElementById("images");
imagesDiv.innerHTML = '<p>Toutes les images ont été supprimées</p>';

Code 9.7 : Modification de la structure de la page web : suppression des images.

Enfin, l'objet document de l'API DOM propose la méthode createElement pour créer un nouvel élément HTML. Cette méthode prend comme paramètre le nom de la balise HTML à créer. Par exemple document.createElement("img") crée un nouvel élément <img>. Le nouvel élément est créé mais n'est pas encore inséré dans le document HTML et donc il n'est pas affiché. Il faut pour cela utiliser d'autres méthodes pour l'inserer dans la structure arborescente. Par exemple la méthode appendChild ajoute un élément à la fin de la liste des enfants d'un autre élément. Le Code 9.8 présente un exemple de création d'un élément. Ce code crée un nouvel élément <img>, donne une valeur à sa propriété src, puis l'insère comme dernier enfant de la balise <div id="images">. Appliqué sur le Code 9.2, ce code ajoute la balise <img src="/public/images/image3_small.png"/> comme dernier fils de la balise <div id="images">.

let newImage = document.createElement("img");
newImage.src = '/public/images/image3_small.png';
let imagesDiv = document.getElementById("images");
imagesDiv.appendChild(newImage);

Code 9.8 : Création d'un nouvel élément (une image) et insertion dans la page web.

Gérer les événements

Le support Javascript dans le navigateur permet de gérer les événements qui sont déclenchés par les actions de l'utilisateur. Plus de quatre-vingt types d'événements peuvent être capturés par le navigateur. Il est par exemple possible de capturer les événements déclenchés par les clics de la souris (click, dblclick), par le déplacement de la souris (mousemove, mouseover, mouseenter), par le clavier (keypress, keydown, keyup), par la soumission d'un formulaire (submit), par le changement d'une valeur d'un champ de saisi (change), par le chargement d'une nouvelle page (load), etc.

Une action réalisée par un utilisateur va déclencher un événement du type concerné. Cet événement est un objet Javascript qui contient plusieurs propriétés décrivant l'action qui vient d'être réalisée. Par exemple, la propriété timeStamp contient le temps qui s'est écoulé depuis le chargement de la page jusqu'à la réalisation de l'action (en millisecondes). La propriété target référence l'élément ciblé par l'action (l'élément cliqué par exemple). D'autres propriétés dépendent du type d'événement. Par exemple les événements de type clavier (keypress, keydown, keyup) ont la propriété key qui décrit la touche du clavier qui a été utilisée. L'objet de ce chapitre n'est pas de décrire tous les types d'événements et leurs propriétés mais de présenter comment capturer un événement et comment utiliser les informations qu'il contient.

L'API DOM propose la méthode addEventListener pour activer la capture d'un type d'événement. Cette méthode a deux paramètres. Le premier paramètre précise le type d'événement à capturer. Le deuxième paramètre est une fonction qui sera exécutée à chaque occurrence de l'événement. Cette fonction prend en paramètre l'objet événement qui contient les informations sur l'événement capturé.

La méthode addEventListener doit être appelée sur un objet qui référence une balise HTML. Cet objet délimite la zone de capture des événements. Par exemple, le code Code 9.9 appelle la méthode addEventListener sur un objet qui référence la balise HTML dont l'id est images. Dans le Code 9.2 cette balise est la balise <div> qui contient les images. Le code Code 9.9 définie donc une capture des événements (ici les clics) dans cette zone.

let imagesDiv = document.getElementById("images");
imagesDiv.addEventListener('click', (e) => {
    console.log(e.timeStamp);
})

Code 9.9 : Capture des événements de type click dans la zone délimitée par l'élément dont l'id est images.

Le code document.addEventListener('click', (e) => console.log(e.timeStamp)) appelle quant à lui la méthode addEventListener sur l'élément document. La zone délimitée par l'objet document correspond à l'intégralité de la page web. Avec ce code, tous les événements de type clic sont capturés. Un message s'affiche sur la console et précise le temps écoulé.

La propagation des événements

Les événements Javascript sont essentiellement déclenchés par les interactions de l'utilisateur (un clic, une saisie dans un formulaire, un scroll, etc.). La capture des événements est délimitée par une zone définie par l'objet sur lequel est appelée la méthode addEventListener.

Pour prendre en compte la zone de capture, Javascript réalise une propagation des événements. En simplifiant, on considère que l'événement prend source dans l'élément cible qui est le plus profond dans l'arborescence du DOM, puis, qu'il remonte comme une bulle (bubbling en anglais) vers la racine du document. Ainsi, avec notre exemple du Code 9.2, si un clic est réalisé sur une des images, l'événement sera d'abord créé sur l'image ciblée, puis, il va remonter vers la balise qui englobe toutes les images, et remonter encore pour arriver sur le document. Les traitements Javascript qui ont été définis sur ces éléments se feront dans l'ordre de la remonté.

Une fois que l'événement est remonté sur le document, le navigateur prend le relais et réalise le traitement par défaut associé à l'événement. Par exemple, si on clique sur un lien hypertexte (balise <a>), l'événement Javascript va être créé sur l'élément cliqué, puis remonter jusqu'au document, puis le navigateur va réaliser le traitement par défaut, c'est à dire le chargement de la page ciblée par le lien hypertexte (traitement par défaut de la balise <a>). Cela veut dire que les traitements Javascript déclarés s'exécutent avant que le navigateur ne réalise le traitement par défaut.

Javascript propose néanmoins deux méthodes qui permettent de modifier la propagation des événements : stopPropagation et preventDefault.

La méthode stopPropagation est appelée sur un événement. Elle stoppe la propagation vers le haut (le bubbling). Si cette méthode est appelée alors aucun des éléments situés au-dessus dans l'arborescence du DOM ne recevront l'événement. Il est déconseillé d'utiliser cette méthode sauf si on veut vraiment empêcher le traitement d'événements qui auraient été définie sur des balises situées au-dessus dans le DOM.

La méthode preventDefault est elle aussi appelée sur un événement. Elle demande au navigateur de ne pas réaliser le traitement par défaut. L'utilisation de cette méthode est assez fréquente. Un exemple assez classique de l'utilisation de cette méthode est celui des formulaires web. Le Code 9.10 présente un formulaire de login. Le Code 9.11 présente un code Javascript qui capte l'événement de soumission du formulaire (événement submit). Si un tel événement est envoyé, on vérifiera que les champs du formulaire ne sont pas vides sinon le formulaire ne sera pas envoyé (on appelle preventDefault si un des deux champs est vide).

<html>
    <body>
        <form action="/login" id="login-form">
            <input type="text" id="fname" name="fname">
            <input type="text" id="lname" name="lname" >
            <input type="submit" value="Submit">
        </form>
    </body>
</html>

Code 9.10 : Exemple de formulaire HTML.

let form = document.getElementById('login-form');
let fname = document.getElementById('fname');
let lname = document.getElementById('lname');
form.addEventListener('submit', (e) => {
    if (!fname.value || !lname.value) {
        alert('please enter First and Last names')
        e.preventDefault();
    }
})

Code 9.11 : Un contrôle pour vérifier que les champs du formulaire ne sont pas vides. Si tel est le cas, le formulaire n'est pas soumis.

Envoyer des requêtes HTTP

En plus d'accéder aux éléments HTML et de gérer les événements utilisateur, Javascript propose la fonction fetch pour envoyer des requêtes HTTP. Cette fonction a deux arguments : l'URL cible de la requête et un objet qui contient les options de la requêtes. Ces options de la requêtes précisent, entre autres, le type de la requête (method), les en-têtes (headers), le corps de la requête (body), etc.

La fonction fetch est asynchrone et retourne donc une promesse Javascript qu'il faut exploiter avec les méthodes then et catch qui prennent chacune une fonction en paramètre. La fonction attachée à then est exécutée en cas de succès. Elle contient comme paramètre la réponse de la requête. La fonction attachée à la méthode catch est exécutée si la requête est un échec.

L'envoi de requêtes HTTP grâce à la fonction fetch est très utilisé pour établir une communication avec le serveur sans que l'utilisateur ne s'en apperçoive. Cela permet par exemple de récupérer de l'information et de changer dynamiquement le contenu de la page web. C'est notament ce qui se fait dans les applications web qui rafraichissent régulièrement des informations telles que des scores ou des commentaires.

Le Code 9.12 illustre l'utilisation de la méthode fetch. On considère que ce code est appelé régulièrement (grâce à la méthode setTimeout). L'objectif est de recevoir les nouveaux commentaires afin de les intégrer dans la page web (grâce aux méthodes Javascript de modification du DOM). On voit dans l'exemple que ce code envoie une requête vers l'URL /commentaires. Comme il n'y a pas d'option dans l'appel, les valeurs par défaut sont utilisées (méthode GET sans en-tête). Dès que la réponse arrive, il faut alors récupérer les derniers commentaires et les ajouter dans le DOM (ce qui n'est pas codé dans l'exemple).

fetch('/commentaires')
.then((result) => {
    //récupérer les nouveaux commentaires
    //les intégrer dans le DOM
})

Code 9.12 : Une requête GET envoyée en Javascript pour avoir les nouveaux commentaires. On considère que ceux-ci seront intégrés dans le DOM.

Intégration de Javascript dans une page web

L'intégration d'un code Javascript dans une page web se fait grâce à la balise <script>. Cette balise peut être placée n'importe où dans le document HTML. Le code Javascript peut être directement intégré dans la balise ou se trouver dans une ressource qui est référencée (propriété src de la balise).

La page du Code 9.13 montre l'intégration de trois scripts dans une page web. Les deux premiers scripts sont intégrés dans les balises <script> alors que le troisième est référencé (fichier script3.js voir Code 9.14). L'exemple montre que ces trois scripts s'exécutent dans l'ordre de leur apparition dans le DOM. Le navigateur les exécute dès qu'il les a lus. L'exemple illustre enfin le fait que ces trois scripts s'exécutent dans le même environnement Javascript. Ils partagent alors toutes les variables déclarées. Dans notre exemple, le deuxième script utilise une variable déclarée par le premier script (la variable script1) et définit une variable qui est utilisée par le troisième script (la variable script2).

<html>
    <head>
        <script>
            console.log('Script1');
            let script1 = true;
        </script>
    </head>
    <body>
        <h1>Javascript</h1>
        <script>
            console.log('Script2');
            if (script1) {
                console.log('Script1 was ok');
            }
            let script2 = true;
        </script>
    </body>
    <script type="text/javascript" src='/public/script3.js'></script>
</html>

Code 9.13 : Illustration d'une intégration de Javascript dans une page web.

console.log('Script3.js');
if (script2) {
    console.log('Script2 was ok');
}

Code 9.14 : Le troisième script exécuté dans la page web.

Pour améliorer la lecture du code, il est conseillé de mettre les scripts dans des ressources et de les référencer plutôt que de les intégrer directement dans les balises. De plus, même si les balises <script> peuvent être placées n'importe où dans le document HTML, il est souvent conseillé de les placer dans la partie <head>. L'avantage est que cela permet de rapidement voir quels sont les scripts qui sont liés à la page web.

Le problème de mettre les scripts dans la balise <head> est qu'ils sont exécutés dès le début de la lecture du document HTML, avant l'intégralité du chargement du DOM. Cela pose des problèmes si le script doit manipuler en lecture ou en écriture des éléments qui ne sont pas encore chargés. Pour faire face à ce problème on utilise la propriété defer de la balise <script> pour demander au navigateur de différer l'exécution du script et d'attendre le chargement de l'intégralité du DOM. Avant l'introduction de la propriété defer il fallait capter l'événement load et exécuter le script en réponse à cet événement. Le Code 9.15 illustre ces deux approches. Les deux premiers scripts voient leur exécution différée (propriété defer). Le troisième script est quand à lui exécuté quand l'événement load est émis. Ces deux façons de faire sont équivalentes. La première a l'avantage d'être plus lisible.

<html>
    <head>
        <script type="text/javascript" src='/public/script1.js' defer></script>
        <script type="text/javascript" src='/public/script2.js' defer></script>
    </head>
    <body>
        <h1>Javascript</h1>
        
    </body>
    <script>
        document.addEventListener('load', (e) => {
            console.log('Script3.js');
            if (script2) {
                console.log('Script2 was ok');
            }
        });
    </script>
</html>

Code 9.15 : Illustration du chargement différé d'un script.

Ce qu'il faut retenir

Ce chapitre présente la façon de coder des interactions riches dans une page web. Il faut retenir les trois points suivants:

  • Tous les navigateurs proposent un environnement Javascript dans chaque page web. Cet environnement permet l'exécution de code Javascript.
  • Les environnements Javascript des navigateurs web proposent des objets qui permettent la manipulation en lecture et en écriture des pages web. C'est l'API DOM qui définit ces objets et leurs méthodes.
  • Il est possible de coder des traitements qui seront exécutés en réaction à des événements utilisateurs. Cela se fait en captant les événements et en leur associant des traitements.

Pour s'exercer

Questions de cours

  1. Est-ce que le langage Javascript peut être utilisé pour développer le front et le back ?

    • a) Non, Javascript ne peut être utilisé que pour développer le serveur web (donc le back).
    • b) Non, Javascript ne peut être utilisé que pour développer l'affichage et les interactions dans le navigateur web (donc le front).
    • c) Oui, c'est possible. Javascript est le seul langage exploitable pour développer l'affichage et les interactions dans le navigateur web (donc le front). Il peut aussi être utilisé pour développer le serveur web (donc le back).
  2. Qu'est-ce que l'API DOM ?

    • a) C'est une API Javascript du front qui permet de manipuler les éléments d'une page web.
    • b) C'est une API Javascript du back qui permet de traiter les requêtes envoyées par les navigateurs web.
    • c) C'est une API Javascript permettant de traiter les requêtes HTTP.
  3. Quels sont les objets fournis par l'API DOM ?

    • a) Server et Client qui permettent d'envoyer des requêtes et de recevoir les réponses.
    • b) Window qui représente la fenêtre du navigateur web et Document qui représente la racine du document HTML.
    • c) Request et Response qui représentent une requête et une réponse HTTP.
  4. Est-il possible de modifier une page web sans envoyer de requête HTTP ?

    • a) Oui, avec Javascript on peut avoir accès aux éléments du DOM et modifier leurs propriétés.
    • b) Non, il faut obligatoirement envoyer une requête HTTP.
    • c) Non, cela est impossible car il faudrait avoir accès à la base de données.
  5. Est-ce que l'API DOM propose des moyens pour réagir aux événements utilisateurs ?

    • a) Non, l'API sert uniquement à naviguer sur le web.
    • b) Oui, on peut enregistrer une fonction Javascript qui sera exécutée à chaque fois que l'utilisateur réalise une action.
    • c) Non, on peut uniquement savoir si une nouvelle requête a été émise.

Réponses: 1-c, 2-a, 3-b, 4-a, 5-b

Exercice 1 - Utilisation de Javascript sur vanillacademy

L'objectif de cet exercice est de comprendre les instructions Javascript en les exécutant sur le site https://vanillacademy.com

  1. Avec votre navigateur web, ouvrez la page https://vanillacademy.com et ouvrez la console JS qui se trouve dans les outils du développeur (shift+ctrl+J).

  2. Tapez la commande suivante et précisez quel élément du DOM la variable titrePage référence ?

let titrePage = document.querySelector('h1')
  1. Que se passe-t-il dans la page web quand vous tapez la commande suivante ?
titrePage.textContent = "Super Cours !"
  1. Que se passe-t-il dans la page web quand vous tapez la commande suivante ?
titrePage.style.color = 'red'
  1. Tapez la commande permettant de centrer le titre.

  2. Ouvrez la page : https://vanillacademy.com/chapitre/1. Quels éléments du DOM la variable images référence-t-elle quand vous exécutez la commande suivante ?

let images = document.querySelectorAll('img')
  1. Que se passe-t-il dans la page web quand vous tapez la commande suivante ?
images[0].style.border = 'solid 2px red'
  1. Que se passe-t-il dans la page web quand vous tapez la commande suivante ?
images[0].style.border = 'none'
  1. Que se passe-t-il dans la page web quand vous tapez la commande suivante ?
images.forEach((image) => image.style.border = 'yellow 2px solid')
  1. Tapez la commande permettant de changer le display de toutes les images (soit en inline soit en block).

  2. Que se passe-t-il quand vous tapez la commande suivante ?

let titrePage = document.querySelector('h1')
titrePage.addEventListener('click', () => console.log('click'))
  1. Tapez la commande permettant de changer le display de toutes les images (soit en inline soit en block) quand on clique sur le titre du chapitre.

  2. Que se passe-t-il quand vous tapez la commande suivante ?

window.addEventListener("scroll",() => console.log('scroll'))
  1. Que se passe-t-il quand vous tapez les commandes suivantes ?
let firstP = document.querySelectorAll('p')[0];
let nouvelleImage = document.createElement('img')
nouvelleImage.src = '/figures/chapitre1/chap1-fig1.png'
firstP.appendChild(nouvelleImage)
  1. Tapez la commande permettant de rajouter une image sous le titre quand on scrolle.

Projet - mur d'images

Nous allons reprendre notre projet qui permet d'afficher des images (voir Chapitre 8, projet).

Le but de cet exercice est de proposer un zoom sur la page de l'image. Un clic gauche sur l'image fait un zoom plus alors qu'un clic droit fait un zoom moins.

Vous pouvez voir le résultat attendu ici.

Récupérez le code que vous avez réalisé dans le chapitre 8 et copiez-le dans un nouveau répertoire nommé chap9-projet.

  1. Ouvrez la page présentant l'image n°1 : http://localhost:8080/page-image/1

  2. Dans la console JS, écrivez un script qui permet de définir la variable mainImage qui référence la balise <img> de l'image centrale.

  3. Toujours dans la console JS, utilisez la variable mainImage pour ajouter un listener de l'événement click qui ajoute 10 à la largeur de l'image.

  4. Toujours dans la console JS, ajoutez un listener de l'événement contextmenu qui enlève 10 à la largeur de l'image quand le bouton droit est cliqué. Vous ferez attention à supprimer le comportement par défaut de cet événement (e.preventDefault()).

  5. Recopiez vos scripts dans un fichier page-image.js que vous référencerez dans la page qui affiche une image. Vous vérifierez que ces scripts sont bien exécutés par le navigateur.

Le but de cet exercice est d'interdire la soumission du formulaire permettant de mettre un commentaire sur une image. Le bouton de soumission sera indisponible tant que le commentaire sera vide.

Vous pouvez voir le résultat attendu ici.

  1. Ouvrez à nouveau la page présentant l'image n°1 : http://localhost:8080/page-image/1

  2. Dans la console JS, proposez un script qui permet de définir la variable submitButton qui référence le bouton de soumission du formulaire.

  3. Proposez un script qui permet de désactiver le bouton en mettant la propriété disabled du bouton à true.

  4. Dans la console JS, quel élément du DOM la variable commentaire référence-t-elle quand vous exécutez la commande suivante ? Et à quoi correspond la propriété value ?

commentaire
commentaire.value
  1. Toujours dans la console JS, proposez un script qui enregistre un listener de l'événement keyup qui rend le bouton de soumission non cliquable quand la valeur du commentaire est vide, et qui le rend cliquable quand la valeur du commentaire n'est pas vide.

  2. Recopiez vos scripts dans le fichier page-image.js. Vous vérifierez que ces scripts sont bien exécutés par le navigateur.