Exercices d'entrainement

Licence Informatique 1ère année

Jean-Marc Lecarpentier

Enseignement des technologies du Web

 

Travail personnel

Exercice 1 — Tableaux et objets, la suite #

Un corrigé de cet exercice est disponible.

Cet exercice a pour objectif d'approfondir la manipulation de divers types en Javascript.

Télécharger cette archive contenant un fichier HTML et un fichier Javascript pour le TP.

IMPORTANT : ne PAS changer les variables définies dans le fichier Javascript. Pour tester vos fonctions, utiliser ces variables et faire un console.log du résultat de chaque fonction. Pour chaque question, le résultat attendu est alors indiqué, ce qui vous permet de vérifier si votre résultat est correct.

Faire les affichages uniquement avec des console.log

Tableaux

Pour certaines questions, il pourra être utile de consulter documentation Javascript sur les tableaux.

Pour chaque cas, tester avec les variables indiqués (les variables sont déjà dans le fichier Javascript fourni) et afficher en console les résultats des fonctions.
Écrire les fonctions qui :

  1. Prend en argument un tableau tab et retourne le dernier élément de celui-ci.
    Tester avec tableau1
    Résultat attendu : Maxime
  2. Prend en argument un tableau tab et retourne un tableau qui ne contient que les éléments de tab d'indice pair.
    Tester avec tableau1
    Résultat attendu : ["Gilles", "Pierre", "Jacques", "Fabrice", "Maxime"]
  3. Prend en argument un tableau tab et un entier n et retourne un tableau des n derniers éléments de tab.
    Attention : penser au cas où n est plus grand que la taille du tableau
    On pourra éventuellement utiliser slice().
    Tester avec tableau1 et n = 4.
    Résultat attendu : ["Anne", "Fabrice", "Margaux", "Maxime"]
  4. Prend en argument un tableau d'entiers et retourne le produit de ses éléments.
    Tester avec tableau2.
    Résultat attendu : 3 065 610 240
  5. Prend en argument un tableau d'entiers tab et un entier n, et retourne un tableau contenant uniquement les éléments de tab divisibles par n.
    Tester avec tableau2 et n = 2 puis n = 3
    Résultat attendu :
    Pour n = 2 : [4, 8, 2, 10, 12, 24, 8]
    Pour n = 3 : [9, 12, 24, 33]
  6. Prend en argument 2 tableaux d'entiers en entrée et retourne le tableau des éléments communs (sans les doublons). On pourra utiliser indexOf() pour tester la présence d'un élément dans un tableau. Attention à ne pas ajouter plusieurs fois le même entier s'il apparait plusieurs fois dans un des deux tableaux.
    Tester avec tableau2 et tableau3
    Résultat attendu : [8, 12]
  7. Prend en argument 2 tableaux d'entiers en entrée et retourne le tableau des éléments n'apparaissant que dans un des deux tableaux.
    Tester avec tableau2 et tableau3
    Résultat attendu : [4, 1, 2, 9, 10, 7, 24, 33, 32, 6, 90, 3 56, 22] (14 éléments)
  8. Optionnel (à faire si vous avez tout fait avant la fin du TP). Prend un tableau d'entiers en entrée et retourne la chaîne de caractères composée des lettres minuscules dont le code ASCII correspondant à chaque entier modulo 26. On pourra utiliser fromCodePoint() et la table des caractères ASCII.
    Tester avec tableau2.
    Résultat attendu : eibcjkhmyih

Objets

On considère l'objet suivant qui modélise un ensemble de personnes :

let annuaire = {
    "Dumat": {
        "nom": "Dumat",
        "prenom": "Marlène",
        "email": "marlene@sarasonic.com",
        "telephone": "06.31.17.18.12"
    },
    "Lepres": {
        "nom": "Lepres",
        "prenom": "Marc",
        "telephone": "06.96.93.50.31"
    },
    "Pico": {
        "nom": "Pico",
        "prenom": "Laurent",
        "email": "laurent.pico@netur.com"
    },
    "Milon": {
        "nom": "Milon",
        "prenom": "Louise"
    }
};
Attention il faut bien sûr que le code que vous allez écrire marche encore et affiche les bonnes informations si on change les données de la liste de personnes. Tester par exemple en ajoutant un email ou téléphone à quelqu'un qui n'en a pas, puis en ajoutant 2 personnes en plus dans l'annuaire.
Nota on pourra chercher les fonctions utiles dans la documentation JS sur les objets, en particulier :
  1. Afficher en console la liste des clés de l'objet annuaire
  2. Afficher en console si l'objet annuaire contient la clé "Toto"
  3. Afficher en console si l'objet annuaire contient la clé "Pico"
  4. Écrire une fonction qui prend en argument un objet obj et qui affiche en console les coordonnées de chaque personne de l'objet obj.

    Si une personne n'a pas d'adresse email ou de téléphone, il faut l'indiquer (voir les exemples ci-dessous).
    Tester avec l'objet annuaire.
    Exemple de rendu :
    Hickman Cole a pour téléphone 06.31.17.18.12
    Hickman Cole a pour adresse email marquitatillman@sarasonic.com
    Welch Triat a pour téléphone 06.96.93.50.31
    Welch Triat n'a pas d'adresse email.
    Gary Cabrera n'a pas de téléphone.
    Gary Cabrera a pour adresse email hopkinslarson@netur.com
    Jody Humphrey n'a pas de téléphone.
    Jody Humphrey n'a pas d'adresse email.
        

Exercice 2 — Créer une table des matières #

Une proposition de correction de cet exercice est disponible.

L'archive toc.zip contient une page web toc.html et un fichier Javascript toc.js.

La page HTML reprend le syllabus du cours TW1 du premier semestre de L1 avec une structure HTML contenant des éléments section et des titres h2 ou h3.

Partie 1

Dans la fonction faireTable présente dans le fichier JS, écrire le programme qui va créer automatiquement la table des matières uniquement pour le 1er niveau et l'afficher dans la balise nav existant dans la page (voir figure ci-dessous).

Page avec table des matières générée en Javascript
Page avec table des matières générée en Javascript

Partie 2

Améliorer le programme pour que la table des matières contienne les liens vers les sections de 1er et 2ème niveau (voir ci-dessous).

Attention une des sous-sections contient elle-même une (sous-sous-)section qui ne doit pas être prise en compte dans la table des métières. Pour pouvoir sélectionner les éléments section à inclure, on pourra utiliser querySelectorAll en l'appliquant non pas au document (i.e. à l'arbre DOM entier) mais à un sous-arbre donné (voir l'exemple de la documentation). Et pour pouvoir spécifier un sélecteur adéquat on pourra utiliser la pseudo-classe :scope.

Nota : il y a alors des parties de codes qui se répètent, on pourra donc factoriser en créant une ou plusieurs fonctions auxiliaires.

Table des matières complète
Table des matières complète

Complément optionnel

À la fin de chaque titre de section, ajouter en Javascript un lien de retour à la table des matières. On pourra utiliser le caractère ↑ pour le lien. Le lien étant toujours le même, penser à optimiser le code en ne créant ce lien qu'une seule fois et le cloner ensuite pour le placer n fois dans la page.

Avec liens de retour à la table des matières
Avec liens de retour à la table des matières

Exercice 3 — Un lexique en Javascript #

Une proposition de correction de cet exercice est disponible.

Une page HTML contient des acronymes que l'on souhaite pouvoir expliciter à l'aide d'un lexique (voir captures ci-dessous). Lorsque l'utilisateur clique sur un acronyme, la signification de celui-ci est affichée dans une division d'identifiant lexique. La liste des acronymes et leur explication est stockée dans un objet Javascript. Le fichier HTML de la page web, le fichier JS des définitions et le fichier JS (vide) du TP sont donnés dans le fichier lexique.zip.

Les acronymes sont placés dans des balises abbr (abbréviation) car la balise acronym n'existe plus en HTML5.

Lexique Lexique Lexique Lexique

1- Initialisation des évènements

Dans la balise script placée en fin de body (pour que le DOM soit bien construit), écrire le code pour que toutes les balises abbr captent le clic et que le clic déclenche la fonction expliquer. Dans le fichier lexique.js, écrire la fonction expliquer en commençant par afficher en console l'élément abbr qui a capté le clic puis le terme à expliquer qui déduit à partir de cet élément.

2- Affichage des définitions

À partir des données de l'objet lexique, afficher dans la division d'identifiant lexique la définition de l'acronyme cliqué. Les définitions s'affichent les unes à la suite des autres.

3- Affichage des liens

Ajouter en plus un lien s'il y en a un pour l'acronyme à expliquer (on pourra vérifier si un URL est donné avec la méthode hasOwnProperty).

4- Améliorations

Améliorer le système pour

  1. que l'on puisse remettre à zéro le lexique.
  2. éviter que la même définition soit affichée 2 fois

Exercice 4 — Carnet d'adresses Javascript #

Une proposition de correction de cet exercice est disponible.

On souhaite gérer ses contacts avec une application Javascript fonctionnant dans le navigateur. Pour cela, les adresses sont stockées avec un objet Javascript. Chaque contact est donc modélisé sous la forme :

    {
        "nom": "Jennings",
        "prenom": "Raquel",
        "pseudo": "Holloway",
        "email": "barronriley@xumonk.com",
        "telephone": "06.82.76.56.44",
        "date": "1976-03-21"
    }

Le carnet d'adresses est modélisé sous la forme d'un objet où chaque clé est un identifiant et la valeur est un objet de type adresse :

{
    "341fffed-7a31-4540-91ae-dcb063582745": {
        "nom": "Jennings",
        "prenom": "Raquel",
        "pseudo": "Holloway",
        "email": "barronriley@xumonk.com",
        "telephone": "06.82.76.56.44",
        "date": "1976-03-21"
        },
    "975f185f-1755-4ade-b1ed-154f3d7bd8b0": {
        ...
    }
}

L'archive address-book.zip contient un fichier book.html, un fichier book.js à compléter avec vos programmes Javascript et un fichier address-book.js contenant une liste de contacts par défaut. La page HTML contient une zone pour afficher la liste des contacts et une zone pour afficher le détail d'un contact.

Partie 1 : affichage des contacts

Écrire le code Javascript qui affiche la liste des contacts (prénom, pseudo et nom) au chargement de la page en utilisant un tableau HTML (élément table qui permet d'aligner les colonnes) comme ci-dessous :

Carnet d'adresses
Affichage au chargement de la page

Indication : attention le carnet d'adresses est un objet et non un tableau. Il faut donc parcourir chaque clé de cet objet. Pour cela 2 méthodes :

  1. utiliser un for ... in pour itérer sur les clés.
  2. récupérer la liste des clés avec Object.keys(monObjet) puis parcourir le tableau produit pour accéder à chaque valeur de l'objet (à partir de sa clé).

Compléter pour afficher le détail d'un contact lorsque l'on clique sur un nom. On veut afficher les détails d'un seul contact à la fois. Il faut donc vider la section avant d'afficher les détails d'un contact. On pourra utiliser les attributs data-* et la propriété Javascript dataset pour faire que chaque élément tr de la liste de gauche connaisse son identifiant (i.e. sa clé dans l'objet représentant le carnet d'adresses).

Détails d'un contact
Détails d'un contact

Indication : pour l'affichage de la date, on peut créer un objet Date à partir de la chaine au format AAAA-MM-JJ qui est dans le carnet d'adresse (i.e. new Date("1956-08-23") crée l'objet Date représentant le 23 aout 1956), puis formatter cet objet Date avec toLocaleDateString.

Partie 2 : gestion des contacts

Dans cette partie on va ajouter les fonctionnalités de gestion (ajout/modification/suppression de contacts).

Lisez bien les indications... qui vous guident pour aller au bout de l'exercice.

  1. En-dessous des détails d'un contact, ajouter un bouton pour modifier et supprimer un contact et leur ajouter le capteur d'évènement click. Penser à leur ajouter un attribut data-* qui reprend l'identifiant du contact afin de pouvoir ensuite le récupérer dans la fonction callback.
    Boutons modifier/supprimer
    Boutons modifier/supprimer
  2. Créer la fonction callback qui supprime un contact. On pourra utiliser la fonction confirm() pour demander confirmation, de la suppression :
    Confirmer la suppression
    Confirmer la suppression
    Pour supprimer une clé et sa valeur dans un objet en Javascript il faut utiliser l'opérateur delete.
    Penser ensuite à vider la section qui affiche le détail d'un contact et à mettra à jour la liste des contacts.
  3. Créer la fonction callback qui affiche le formulaire de modification.
    Pour éviter de créer le formulaire avec de nombreux appels à document.createElement() etc, on pourra ajouter, dans le fichier HTML, le code HTML du formulaire (avec ses champs non remplis) et le mettre en display: none avec CSS. Ainsi pour créer le formulaire de modification, il suffira de cloner le formulaire caché, le remplir avec les données du contact à modifier, lui faire capter le submit et l'afficher dans la section details.
    Pour accéder facilement aux champs d'un formulaire, utiliser la propriété elements des objets élément form. Voir l'exemple de la documentation MDN.
    Penser encore une fois qu'il faudra pouvoir obtenir l'identifiant du contact pour ensuite enregistrer les changements. On peut ici utiliser de nouveau un attribut data-* ou bien mettre un champ caché dans le formulaire (input de type hidden).
  4. Créer la fonction callback qui enregistre les données du formulaire en modifiant l'objet qui représente le carnet d'adresses.
    Penser à nouveau à vider la section qui affiche le formulaire d'un contact et à mettra à jour la liste des contacts.
  5. Ajouter dans le HTML un bouton pour ajouter un contact (on pourra le mettre au dessus de la colonne de gauche par exemple) et lui faire capter le click.
  6. Créer la fonction qui affiche un formulaire vierge pour créer un contact. Le principe du clonage du formulaire caché peut être repris. C'est même ici plus simpke puisque les champs du formulaire restent vides.
  7. Écrire le code pour enregistrer le nouveau contact dans l'objet qui contient tous les contacts.
    On aura besoin ici de créer la propriété date et lui mettre la date du jour.
    On a aussi besoin de créer un identifiant interne qui sera la clé à ajouter. Pour cela, on va utiliser l'utilitaire chancejs qui permet de générer toutes sortes de codes. En particulier la méthode chance.guid() fait exactement ce dont on a besoin.
    Penser encore à vider la section qui affiche le formulaire et à mettre à jour la liste des contacts.

Partie 3 : persistence des contacts

On dispose désormais d'une petite application qui permet de gérer une liste de contacts. Mais si on recharge la page alors les changements effectués sur la liste sont perdus. Dans cette partie nous allons mettre en place une persistence des données locale (c'est à dire uniquement dans le navigateur). Ainsi si on recharge la page ou que le navigateur est fermé alors on retouvera la liste modifiée lorsqu'on revient sur la page.

Pour cela nous allons utiliser les fonctionnalités de Web Storage et en particulier localStorage qui permet de stocker des données dans le navigateur.

Les données stockées dans localStorage sont au format texte. Il faut donc transformer la liste personnes en texte pour pouvoir l'enregistrer. La méthode JSON.stringify() permet de faire cela.

Inversement, lors du chargement des données contenues dans le localStorage, il faut transformer le texte stocké en variable Javascript. JSON.parse() permet de faire cela.

Écrire le code Javascript qui permet d'enregistrer la liste des contacts. Il faudra, au chargement de la page, regarder si des données existent dans le localStorage du navigateur. Si oui alors on les charge pour le carnet d'adresses. Sinon on utilise par défaut l'objet initAddressBook fourni dans le fichier address-book.js.
Attention il faut donc enregistrer le carnet d'adresses à chaque changement dans celui-ci (ajout, modification ou suppression d'un contact).

Vérifier que la persistence fonctionne bien : fermer le navigateur puis revenir sur la page de l'exercice. La liste des contacts doit bien être la liste modifiée.
Attention cela ne marche QUE si votre page est sur le serveur et que vous la consultez via HTTP (i.e. si l'URL commence par file:// alors ça ne marche pas.

Remarque : pour voir les données enregistrées dans le localStorage, utiliser les outils de développement web avec l'onglet Stockage :

Onglet stockage des outils de développement Firefox
Onglet stockage des outils de développement Firefox

Partie 4 : tri des contacts

Compléter les programmes pour que si on clique sur l'entête de colonne Nom de la table, l'affichage de la liste est alors faite par ordre alphabétique des noms.

On pourra utiliser la liste des clés du carnet d'adresse et la trier en utilisant les noms correspondants comme critère de tri. Pour cela oun pourra utiliser la méthode sort des tableaux avec une fonction de comparaison (voir exemple sur la documentation).