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 :
- Prend en argument un tableau
tab
et retourne le dernier élément de celui-ci.
Tester avectableau1
Résultat attendu : Maxime - Prend en argument un tableau
tab
et retourne un tableau qui ne contient que les éléments detab
d'indice pair.
Tester avectableau1
Résultat attendu : ["Gilles", "Pierre", "Jacques", "Fabrice", "Maxime"] - Prend en argument un tableau
tab
et un entiern
et retourne un tableau desn
derniers éléments detab
.
Attention : penser au cas oùn
est plus grand que la taille du tableau
On pourra éventuellement utiliser slice().
Tester avectableau1
etn = 4
.
Résultat attendu : ["Anne", "Fabrice", "Margaux", "Maxime"] - Prend en argument un tableau d'entiers et retourne le produit de ses éléments.
Tester avectableau2
.
Résultat attendu : 3 065 610 240 - Prend en argument un tableau d'entiers
tab
et un entiern
, et retourne un tableau contenant uniquement les éléments detab
divisibles parn
.
Tester avectableau2
etn = 2
puisn = 3
Résultat attendu :
Pourn = 2
: [4, 8, 2, 10, 12, 24, 8]
Pourn = 3
: [9, 12, 24, 33] - 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 avectableau2
ettableau3
Résultat attendu : [8, 12] - 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 avectableau2
ettableau3
Résultat attendu : [4, 1, 2, 9, 10, 7, 24, 33, 32, 6, 90, 3 56, 22] (14 éléments) - 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 avectableau2
.
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 :
- comment tester si un objet possède une propriété donnée
- comment itérer sur les clés d'un objet (Attention : ce n'est pas le for...in de Python !!)
- Afficher en console la liste des clés de l'objet
annuaire
- Afficher en console si l'objet
annuaire
contient la clé "Toto" - Afficher en console si l'objet
annuaire
contient la clé "Pico" - Écrire une fonction qui prend en argument un objet
obj
et qui affiche en console les coordonnées de chaque personne de l'objetobj
.
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'objetannuaire
.
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).

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.

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.

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.




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
- que l'on puisse remettre à zéro le lexique.
- é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 :

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 :
- utiliser un
for ... in
pour itérer sur les clés. - 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).

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.
- 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 - Créer la fonction callback qui supprime un contact. On pourra utiliser la fonction
confirm()
pour demander confirmation, de la suppression :Confirmer la suppression delete
.
Penser ensuite à vider la section qui affiche le détail d'un contact et à mettra à jour la liste des contacts. - 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 endisplay: 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 lesubmit
et l'afficher dans la sectiondetails
.
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 attributdata-*
ou bien mettre un champ caché dans le formulaire (input
de typehidden
). - 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. - 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.
- 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.
- É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éthodechance.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 :

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).