Skip to content

🔢 Exercice PokeCount ​

exe-pokeCount.png

Démo ​

https://fallinov.github.io/2024-SFA-JS-EXE-PokeCount/

Objectifs ​

  • CrĂ©er une application web simple pour capturer et sauvegarder des PokĂ©mon.
  • Utiliser JavaScript pour manipuler le document HTML (DOM) et ajouter des fonctionnalitĂ©s interactives.
  • Sauvegarder les captures dans le localStorage du navigateur pour les recharger entre les sessions.
  • AmĂ©liorer le code grâce Ă  des Ă©couteurs d'Ă©vĂ©nements.

Mise en place ​

  1. Clique sur le lien suivant pour créer ton dépôt GitHub pour l'exercice : https://classroom.github.com/a/DF6YJq-Z
  2. Clone ton dépôt GitHub en local avec WebStorm ou un autre éditeur
  3. Créer une nouvelle branche qui porte ton nom
  4. Commence l'exercice et pense à **faire régulièrement des commits et des **push.

Étape 1 : Liaison du JavaScript au HTML ​

Comprendre les fichiers de départ ​

  • index.html : Page HTML de l'exercice qui se compose de :
    • un titre principal (<h1>)
    • un compteur (<h2 id="compteur-el">) initialisĂ© Ă  0 pour suivre le nombre de PokĂ©mon capturĂ©s
    • deux boutons (<button id="capturer-btn"> et <button id="sauvegarder-btn">) pour capturer et sauvegarder les PokĂ©mon
    • un paragraphe (<p id="sauvegarde-el">) destinĂ© Ă  afficher l'historique des captures.
  • style.css : stylise la page avec un fond thĂ©matique PokĂ©mon et des couleurs de boutons.
  • pokemon-bg.webp : Image de fond utilisĂ©e dans le CSS.

Créer un fichier JavaScript et lier au HTML : ​

  • Action : CrĂ©ez un nouveau fichier nommĂ© script.js dans le mĂŞme dossier que index.html.
  • Action : Liez ce fichier JavaScript au fichier HTML en ajoutant la ligne suivante dans index.html, juste avant la fermeture de la balise </body> :
    html
    <script src="script.js"></script>

Afficher un message "Hello World" : ​

  • Action : Ouvrez script.js et commencez par ajouter un bloc de commentaires pour dĂ©crire le fichier :
    javascript
    /**
    * Fichier JavaScript pour l'application PokeCount.
    * @author Steve Fallet <steve.fallet@divtec.ch>
    * @version 0.1 (Version actuelle)
    * @since 2024-01-31 (Date de création)
    */
  • Action : Toujours dans script.js, ajoutez le code suivant pour
    • Demander un interprĂ©tation stircte du code. Le mode "use strict" en JavaScript active un mode d'exĂ©cution plus rigoureux, interdisant certaines pratiques risquĂ©es et facilitant la dĂ©tection d'erreurs dans le code.
    • Afficher "Hello World" dans la console du navigateur
    javascript
    "use strict"; // Interprètation stricte du code
    console.log("Hello World"); // Affiche "Hello World" dans la console
  • Test :
    • Ouvrez index.html dans un navigateur web.
    • Ouvrez la console du navigateur (F12 ou clic droit > Inspecter > Console) pour vĂ©rifier que le message "Hello World" s'affiche correctement, ce qui confirme que le JavaScript est correctement liĂ© Ă  votre fichier HTML.
  • Action : Remplacez console.log par alert pour afficher une boĂ®te de dialogue :
    javascript
    alert("Hello World");
  • Test :
    • Ouvrez index.html dans un navigateur web.
    • VĂ©rifiez que la boĂ®te de dialogue s'affiche correctement.

Différence entre console.log et alert : ​

  • console.log : Affiche des messages dans la console du navigateur, accessible via les outils de dĂ©veloppement. Cela permet de vĂ©rifier discrètement des informations, des valeurs de variables, ou le flux d’exĂ©cution sans interrompre l’expĂ©rience utilisateur.
  • alert : Affiche une boĂ®te de dialogue modale Ă  l’utilisateur avec un message. Cette boĂ®te bloque l’exĂ©cution du script jusqu’à ce que l’utilisateur la ferme, ce qui interrompt l’expĂ©rience utilisateur.

Pourquoi utiliser console.log pour le débogage : ​

  • Non intrusif : console.log permet de dĂ©boguer en arrière-plan sans gĂŞner l’utilisateur, contrairement Ă  alert qui interrompt le flux normal de l’application.
  • FlexibilitĂ© : Vous pouvez afficher plusieurs messages successivement, analyser des objets complexes, et garder une trace des Ă©vĂ©nements dans la console, ce qui est bien plus commode pour diagnostiquer des problèmes dans votre code. En rĂ©sumĂ©, console.log est l’outil de choix pour le dĂ©bogage, car il est discret, puissant et n’affecte pas l’expĂ©rience utilisateur.

Étape 2 : Manipulation du DOM pour modifier un élément ​

Le JavaScript peut être utilisé pour manipuler le contenu d'une page web en modifiant le Document Object Model (DOM). On peut accéder aux éléments HTML, modifier leur contenu, leur style, ou même ajouter de nouveaux éléments dynamiquement.

Récupérer le premier élément <h2> du document HTML et modifier son contenu : ​

  • Action : Utilisez document.querySelector pour rĂ©cupĂ©rer le premier Ă©lĂ©ment <h2> du document et modifiez son contenu pour qu'il affiche 20 :
    javascript
    document.querySelector("h2").textContent = 20;
  • Test : Actualisez la page dans le navigateur. L'Ă©lĂ©ment <h2> doit maintenant afficher 20.

Récupérer un élément par son identifiant unique (ID) : ​

  • Action : Utilisez document.getElementById pour rĂ©cupĂ©rer l'Ă©lĂ©ment avec l'ID compteur-el et modifiez son contenu pour qu'il affiche 100. Ajoutez cette ligne dans script.js :
    javascript
    document.getElementById("compteur-el").textContent = 100;
  • Test : Actualisez la page dans le navigateur. L'Ă©lĂ©ment <h2> doit dĂ©sormais afficher 100.

Différence entre getElementById et querySelector : ​

getElementById et querySelector sont deux méthodes pour récupérer des éléments du DOM en JavaScript.

  • getElementById : Permet de rĂ©cupĂ©rer un Ă©lĂ©ment par son identifiant unique (ID) dĂ©fini dans le HTML. C'est la mĂ©thode la plus rapide pour accĂ©der Ă  un Ă©lĂ©ment spĂ©cifique.
    javascript
    // Sélectionner un élément <div> avec l'ID "main-content"
    const mainContent = document.getElementById("main-content");
    // Sélectionner un élément <header> avec l'ID "site-header"
    const siteHeader = document.getElementById("site-header");
    // Sélectionner un bouton avec l'ID "submit-btn"
    const submitButton = document.getElementById("submit-btn");
  • querySelector : Permet de rĂ©cupĂ©rer un Ă©lĂ©ment grâce Ă  un sĂ©lecteur CSS. Cela signifie que vous pouvez cibler des Ă©lĂ©ments par leur balise, classe, attribut, ou mĂŞme leur position dans le DOM.
    javascript
    // Sélectionner le premier paragraphe du document
    const firstParagraph = document.querySelector("p");
    // Sélectionner un élément par son identifiant (ID)
    const header = document.querySelector("#header");
    // Sélectionner le premier élément avec une classe spécifique
    const firstButton = document.querySelector(".btn");
    // Sélectionner un élément de type <div> avec une classe spécifique
    const specialDiv = document.querySelector("div.special");
    // Sélectionner le premier élément <input> dans un formulaire avec une classe spécifique
    const firstInput = document.querySelector("form input.form-input");

Utilisez getElementById pour les éléments avec un identifiant unique, et querySelector pour des sélections plus complexes.


Étape 3 : Création et affichage de variables ​

Avant de commencer, mettez en commentaire ou supprimez les codes précédents pour éviter les conflits. Nous allons créer des variables pour stocker le compteur de Pokémon et l'élément <h2 id="compteur-el"> du document.

Créer une variable pour représenter l'élément HTML <h2 id="compteur-el"> et une pour le compteur du jeu : ​

  • Action : Dans script.js, crĂ©ez deux variables :
    • Une variable compteur pour stocker la valeur du compteur (initialement 0).
    • Une variable compteurEl pour stocker la rĂ©fĂ©rence Ă  l'Ă©lĂ©ment <h2 id="compteur-el">. Utilisez const pour cette rĂ©fĂ©rence puisque l'Ă©lĂ©ment ne changera pas.
    javascript
    let compteur = 0;
    const compteurEl = document.getElementById("compteur-el");

Pourquoi utilise-t-on const pour compteurEl ? ​

Nous utilisons const pour déclarer la variable compteurEl car elle représente une référence à un élément HTML qui ne changera pas. En d'autres termes, la valeur de compteurEl (la référence à l'élément <h2>) restera la même tout au long du script, même si le contenu ou les attributs de cet élément peuvent être modifiés. En revanche, let est utilisé pour compteur car cette variable est destinée à être modifiée régulièrement, chaque fois qu'un Pokémon est capturé. L'utilisation de const pour compteurEl garantit que cette référence ne sera pas accidentellement réassignée à un autre élément plus tard dans le code, ce qui contribue à la stabilité et à la clarté du code.


Étape 4 : Préparation pour la capture de Pokémon ​

Créer une fonction pour capturer un Pokémon : ​

  • Action : CrĂ©ez une fonction capturer() qui incrĂ©mente le compteur et actualise le texte de <h2 id="compteur-el">.
    javascript
    function capturer() {
        compteur += 1; // Incrémenter le compteur de 1
        compteurEl.textContent = compteur; // Actualiser le texte de l'élément <h2>
    }

Lier la fonction au bouton "CAPTURER" : ​

  • Action : Assurez-vous que le bouton "CAPTURER" dans index.html appelle la fonction capturer() grâce Ă  l'attribut onclick :
    html
          <button id="capturer-btn" onclick="capturer()">CAPTURER</button>
  1. Test : Actualisez la page dans le navigateur. Cliquez sur le bouton "CAPTURER" et vérifiez que le compteur augmente à chaque clic.

Étape 5 : Changer la couleur du compteur toutes les cinq captures ​

Nous souhaitons modifier la couleur du texte du compteur toutes les cinq captures pour rendre le jeu plus interactif.

  • Moins de 5 captures : couleur verte
  • De 5 Ă  10 captures : couleur jaune
  • Plus de 10 captures : couleur rouge

Modifier le code de la fonction capturer() pour modifier la couleur du texte du compteur en fonction du nombre de captures : ​

  • Action : Modifiez la fonction capturer() pour changer la couleur du texte du compteur selon le nombre de captures. Utilisez une condition if...else if...else pour dĂ©terminer la couleur :
    javascript
    function capturer() {
        compteur += 1; // Incrémenter le compteur de 1
        compteurEl.textContent = compteur; // Mettre à jour le texte de l'élément <h2>
        if (compteur < 5) {
            compteurEl.style.color = "green"; // Couleur verte pour moins de 5 captures
        } else if (compteur < 10) {
            compteurEl.style.color = "yellow"; // Couleur jaune pour 5 Ă  9 captures
        } else {
            compteurEl.style.color = "red"; // Couleur rouge pour 10 captures ou plus
        }
    }
  • Test : Actualisez la page dans le navigateur. Capturez des PokĂ©mon pour vĂ©rifier que la couleur du texte du compteur change correctement.

Étape 6 : Sauvegarde des captures ​

Créer une variable pour stocker les captures sauvegardées : ​

  • Action : CrĂ©ez une variable sauvegardeEl pour stocker la rĂ©fĂ©rence Ă  l'Ă©lĂ©ment <p id="sauvegarde-el"> :
    javascript
    const sauvegardeEl = document.getElementById("sauvegarde-el");

Créer une fonction pour sauvegarder les captures : ​

  • Action : CrĂ©ez une fonction sauvegarder() qui ajoute la valeur actuelle du compteur au paragraphe sauvegarde-el et rĂ©initialise le compteur Ă  0.
    javascript
    function sauvegarder() {
        let compteurStr = compteur + " Pokémons - ";
        sauvegardeEl.textContent += compteurStr; // Ajouter la valeur actuelle du compteur
        compteur = 0;
        compteurEl.textContent = compteur;
    }

Lier la fonction au bouton "SAUVEGARDER" : ​

  • Action : Assurez-vous que le bouton "SAUVEGARDER" dans index.html appelle la fonction sauvegarder() :
    html
    <button id="sauvegarder-btn" onclick="sauvegarder()">SAUVEGARDER</button>
  • Test :
    • Actualisez la page dans le navigateur.
    • Capturez quelques PokĂ©mon, puis cliquez sur "SAUVEGARDER".
    • VĂ©rifiez que les captures sont ajoutĂ©es Ă  la liste et que le compteur se rĂ©initialise.

Étape 7 : Amélioration du code avec des écouteurs d'événements ​

Les écouteurs d'événements (event listeners) permettent de réagir à des interactions de l'utilisateur, comme un clic, sans mélanger HTML et JavaScript. Introduction aux Callbacks Avant de commencer cette étape, il est important de comprendre le concept de callback en JavaScript. Un callback est une fonction que vous passez en argument à une autre fonction, et qui sera exécutée plus tard, généralement en réponse à un événement. Les callbacks sont couramment utilisés pour diriger les interactions utilisateur de manière asynchrone, comme répondre à un clic sur un bouton. Exemple d'utilisation d'un Callback Lorsque vous utilisez un écouteur d'événement avec addEventListener, vous passez un callback qui sera exécuté lorsque l'événement spécifié se produit. Par exemple :

javascript
const capturerBtn = document.getElementById("capturer-btn");
capturerBtn.addEventListener("click", capturer);

Dans cet exemple, la fonction capturer est passée comme callback à addEventListener. Elle sera appelée automatiquement chaque fois que l'utilisateur cliquera sur le bouton "CAPTURER". Les callbacks permettent ainsi de rendre votre application interactive en réagissant aux actions de l'utilisateur de manière dynamique.

Retirer les attributs onclick du HTML : ​

  • Action : Ouvrez index.html et retirez les attributs onclick des boutons "CAPTURER" et "SAUVEGARDER". Les boutons devraient ressembler Ă  ceci :
    html
    <button id="capturer-btn">CAPTURER</button>
    <button id="sauvegarder-btn">SAUVEGARDER</button>

Ajouter des écouteurs d'événements dans JavaScript : ​

  • Action : Dans script.js, rĂ©cupĂ©rez les rĂ©fĂ©rences aux boutons et ajoutez des Ă©couteurs d'Ă©vĂ©nements pour lier les fonctions capturer() et sauvegarder() :
    javascript
    const capturerBtn = document.getElementById("capturer-btn");
    const sauvegarderBtn = document.getElementById("sauvegarder-btn");
    capturerBtn.addEventListener("click", capturer);
    sauvegarderBtn.addEventListener("click", sauvegarder);
  • Test :
    • Actualisez la page dans le navigateur.
    • VĂ©rifiez que le bouton "CAPTURER" incrĂ©mente toujours le compteur et que le bouton "SAUVEGARDER" sauvegarde correctement les captures.

Pourquoi cette étape est-elle importante ? ​

L'utilisation d'écouteurs d'événements améliore la séparation entre le HTML (contenu) et le JavaScript (fonctionnalité). Cela rend le code plus modulaire, plus facile à maintenir, et extensible pour des projets plus complexes.


Étape 8 : Utiliser le localStorage pour sauvegarder les captures ​

Actuellement, les captures sont stockées temporairement dans la page web, mais elles sont perdues si l'utilisateur recharge la page ou ferme le navigateur. Pour résoudre ce problème, nous allons utiliser le localStorage. Le localStorage est une fonctionnalité du navigateur qui permet de stocker des données localement sur l'ordinateur de l'utilisateur. Cela signifie que les données peuvent être conservées même après le rechargement de la page ou la fermeture du navigateur. Sauvegarder les captures dans le localStorage :

  • Action : Modifiez la fonction sauvegarder() pour stocker les captures dans le localStorage du navigateur :
    javascript
    function sauvegarder() {
        let compteurStr = compteur + " Pokémons - ";
        sauvegardeEl.textContent += compteurStr; // Ajouter la valeur actuelle du compteur
        localStorage.setItem("captures", sauvegardeEl.textContent); // Sauvegarder les captures dans le localStorage
        compteur = 0;
        compteurEl.textContent = compteur;
    }
  • Test : Visualisez les donnĂ©es sauvegardĂ©es dans le localStorage en ouvrant les outils de dĂ©veloppement du navigateur (F12 ou clic droit > Inspecter > Application > Local Storage). Charger les captures sauvegardĂ©es au chargement de la page Dans cette Ă©tape, nous allons charger les captures sauvegardĂ©es dès que la page est chargĂ©e. Pour cela, nous allons utiliser un Ă©couteur d'Ă©vĂ©nement associĂ© Ă  l'Ă©vĂ©nement load. Cet Ă©vĂ©nement se dĂ©clenche lorsque la page a complètement fini de se charger. Au lieu de dĂ©finir une fonction nommĂ©e sĂ©parĂ©e, nous allons utiliser une fonction anonyme directement dans notre Ă©couteur d'Ă©vĂ©nement. Une fonction anonyme est une fonction sans nom, utilisĂ©e ici parce qu'elle est spĂ©cifique Ă  cette action unique et ne nĂ©cessite pas d'ĂŞtre rĂ©utilisĂ©e ailleurs.
  • Action : Ajoutez le code suivant pour charger les captures sauvegardĂ©es au chargement de la page :
    javascript
    window.addEventListener("load", () => { // Attendre que la page soit chargée pour exécuter le code
        sauvegardeEl.textContent = localStorage.getItem("captures") || ""; // Charger les captures sauvegardées ou une chaîne vide
    });

Dans cet exemple, la fonction que nous passons à addEventListener est une fonction anonyme. Elle est définie avec la syntaxe () => { ... } et sera exécutée une seule fois lorsque l'événement load se déclenchera. L'utilisation d'une fonction anonyme ici permet de garder le code simple et directement lié à l'événement spécifique, sans ajouter de complexité inutile.

  • Test : Actualisez la page dans le navigateur. Capturez quelques PokĂ©mon, sauvegardez-les, puis rechargez la page.

Challenges supplémentaires ​

  • Ajouter un bouton "RESET" pour rĂ©initialiser le compteur et les captures, sans oublier le localStorage.
  • Afficher l'historique des captures dans une liste Ă  puce.
  • GĂ©rer le stockage des captures dans un tableau JavaScript.
  • Permettre Ă  l'utilisateur de supprimer des captures de l'historique.

🦤 La solution du prof ​

Le site du prof ​

https://fallinov.github.io/2024-SFA-JS-EXE-PokeCount/

Le code du prof ​

https://github.com/fallinov/2024-SFA-JS-EXE-PokeCount