Applications client (suite)

Licence Informatique 1ère année

Jean-Marc Lecarpentier

Enseignement des technologies du Web

 

Travail personnel

Notes de cours

Exercice 1 — Compteur de calories - 2ème partie #

Attention : cet exercice est la suite de la 1ère partie et sera noté sur 10.

Cet exercice fait partie de ceux qui seront évalués. La page doit être accessible et fonctionnelle à l'URL suivante :

https://dev-LOGIN.users.info.unicaen.fr/TW2-2025/TP07/ex1/compteur.html
(en remplaçant LOGIN par votre nom de login). Pensez à vérifier la validité W3C de votre page !

D'autre part, l'élément head doit contenir le code suivant :

<meta name="author" content="LOGINS" />
en remplaçant LOGINS par les noms de login des étudiant·e·s qui ont travaillé sur cette page, séparés par des virgules. (Il faut laisser name="author" tel quel, par contre !) Par exemple, si dupont210 et durand212 ont travaillé ensemble, ils mettent <meta name="author" content="dupont210,durand212" /> dans le head de leur page. Ça permettra à notre script de savoir qui a travaillé avec qui. Attention, le travail en binôme est réservé aux cas où il n'y a pas assez de machines disponibles.

Il est conseillé de vérifier que l'exercice a été correctement rendu en utilisant l'application evalweb.

Vous avez jusqu'au début du TP de la semaine suivante pour terminer l'exercice.

Partie 5 : Enregistrement des repas

Créer une variable globale listeRepas initialisée à une liste vide. On ajoutera dans cette liste les repas enregistrés, qui seront affichés grâce à cette liste (comme on affichait les ingrédients à partir de la liste listeIngredients).

Pour enregistrer un repas, ajouter le formulaire dont le code HTML est donné ci-dessous après la division d'identifiant compteur. Ce formulaire est caché par défaut avec la CSS fournie dans la page. Compléter la fonction afficheRepas pour rendre le formulaire visible quand on affiche les ingrédients, et compléter la fonction raz pour le cacher à nouveau quand on clique sur le bouton Recommencer.

<form id="save">
    <fieldset>
        <legend>Enregistrer</legend>
        <label>Nom du repas : <input name="nom" value="" id="nom"></label>
        <button>Enregistrer</button>
    </fieldset>
</form>
    
Formulaire d'enregistrement d'un repas

Dans la fonction qui initialise la page (init()), faire que ce formulaire capte le submit et que cela appelle la fonction enregistrerRepas, qui devra commencer par bloquer l'envoi du formulaire (event.preventDefault()).

On enregistrera un repas sous la forme d'un objet avec la structure suivante :

{ "nom": "le nom du repas", "repas": listeIngredients }

listeIngredients est la liste des ingrédients telle que définie dans la 1ère partie.

Attention si on ne fait pas attention, la liste des ingrédients est copiée par référence, ce qui induit un bug dans certains cas. Deux possibilités pour l'éviter :

  1. remettre le formulaire des ingrédients à zéro (fonction raz), ce qui réaffecte une nouvelle liste vide à la variable listeIngredients (cassant ainsi la réference)
  2. passer la liste des ingrédients en s'assurant qu'une copie est faite. Pour cela on peut utiliser la syntaxe de décomposition : { "nom": "le nom du repas", "repas": [ ...listeIngredients ] }

Compléter la fonction enregistrerRepas pour ajouter le repas à enregistrer à listeRepas et appeler une fonction afficheListeRepas(liste) qui affichera les repas enregistrés dans listeRepas (partie suivante).

Partie 6 : Affichage des repas

Ajouter en fin de page une division d'identifiant mes-repas avec un titre de niveau 2 :

Division pour l'affichage des repas enregistrés
Division pour l'affichage des repas enregistrés

Écrire de reste de la fonction afficheListeRepas(liste) qui prend en argument une liste de repas et qui :

  • vide la division d'identifiant mes-repas sauf le titre de niveau 2
  • affiche les noms des repas enregistrés (on récrée la liste entière)
Affichage des repas enregistrés
Affichage des repas enregistrés

Partie 7 : Enregistrement en stockage local

Pour l'instant les repas sont enregistrés uniquement en mémoire vive. Si vous rechargez votre page, aucun repas enregistré ne s'affiche. On va donc maintenant gérer la persistence de ces données.

Le stockage local ne peut enregistrer que des données scalaires, on va donc avoir besoin de sérialiser les informations à enregistrer, avc JSON.stringify.

Compléter la fonction enregistrerRepas pour que celle-ci enregistre dans le localStorage une clé liste-repas qui contiendra la sérialisation du tableau Javascript listeRepas.

Attention à bien respecter la clé liste-repas.

Vérifier avec les outils de console si vous avez bien les données dans le localStorage :

Données enregistrées
Données enregistrées

Les données sont bien enregistrées, mais si vous rechargez votre page, aucun repas enregistré ne s'affiche.

Il faut donc maintenant que la liste des repas enregistrés dans le localStorage soit, au chargement de la page, chargée en mémoire dans le tableau Javascript listeRepas et que l'affichage des repas soit fait.

Écrire la fonction initStorage (sans argument), qui regarde si le localStorage contient une clé liste-repas, et si oui prend les données, les désérialise, initialise le tableau Javascript listeRepas et appelle la fonction qui affiche les repas.

Pour terminer, appeler initStorage au chargement de la page (fonctionn init).

Normalement, on doit maintenant avoir les repas enregistrés qui s'affichent à nouveau lorsqu'on recharge la page.

Partie 8 : Suppression d'un enregistrement

Compléter la fonction d'affichage des repas pour avoir un bouton de suppression d'un repas et créer la fonction supprimeRepas (appelée quand on clique sur le bouton) et qui va supprimer le repas du tableau Javascript listeRepas(penser à utiliser splice), enregistre en localStorage la nouvelle version de listeRepas, et raffraichit l'affichage des repas enregistrés (il suffit de rappeler la fonction afficheListeRepas).

Bouton de suppression d'un repas
Bouton de suppression d'un repas

Partie 9 : Export HTML des repas enregistrés

On veut pouvoir réaliser l'export des repas enregistrés sous la forme d'un fichier HTML, comme sur l'exemple ci-dessous.

Bouton d'export
Bouton export
Enregistrement du fichier
Enregistrement du fichier
Fichier HTML exporté
Fichier HTML exporté

Créer le bouton d'export et créer la fonction exportHtml qui sera appelée. Cette fonction va procéder avec les étapes suivantes :

  1. créer une chaine de caractères qui contient le code HTML au format texte (et non DOM) de la page d'export. Il faut donc écrire le code HTML de la page entière. Pour cela, utiliser les Template literals afin de faciliter l'écriture du code HTML (évite les multiples concaténations de chaines).
  2. créer un Blob qui va contenir le code HTML créé. Le blob permet de créer une sorte de fichier virtuel qui pourra alors être téléchargé. Pour cela, il faut lui donner le code HTML et le type MIME :
    let page = new Blob([codeHtml], { type: 'text/html;charset=utf-8,' })codeHtml est la variable contenant tout le HTML de la page web d'export.
    Objet Blob et comment en créer un
  3. créer object URL avec le blob (variable page ci-dessus). Cela permet d'avoir une URL vers ce fichier virtuel :
    let objUrl = URL.createObjectURL(page);
    Méthode URL.createObjectURL()
  4. créer un lien en mettant pour l'attribut href la valeur de objUrl créée ci-dessus, et y ajouter un attribut download pour indiquer au navigateur qu'il s'agit d'un domwnload et spécifier un nom de fichier par défaut (voir cet exemple
  5. cliquer automatiquement sur le lien (via Javascript) avec la méthode click(), ce qui déclenche le téléchargement
    Simuler un clic sur un élément
  6. supprimer ensuite le lien créé afin qu'il ne soit pas visible