Il s'agit d'une version statique de l'intranet d'A. Jonquet, certaines fonctionnalités sont donc potentiellement non fonctionnelles.
Rejoindre la version dynamique 🔒
R301
Navigation

Mise en place d'un projet JavaScript

Ce module est l'occasion de mettre en application les bonnes pratiques et les outils associés, largement plébiscités dans le monde du développement JavaScript moderne.

Le TP portera sur la mise en place d'un environnement de travail pour la réalisation d'une bibliothèque JavaScript pouvant être diffusée sous la forme d'un paquet npm.

Le code étant relativement simpliste, nous nous focaliserons sur les bonnes pratiques et les outils.

Remarque importante

Les notes des TP seront obtenues à partir de vos dépôts Git, vous devrez donc prendre grand soin de la qualité de ces dépôts et de leurs « commits ».

De manière similaire, les descriptions de vos « commits » devront être claires et informatives, afin de permettre l'évaluation de la progression de votre travail.

Objectifs de la séance

  • Gestion de versions à l'aide de Git
  • Gestion de paquets npm
  • Mise en place d'un environnement de travail JavaScript
  • Introduction au développement dirigé par les tests
  • Conditionnement de bibliothèque à l'aide de webpack
  • Approfondissement du langage JavaScript

Mise en place du projet

La gestion du projet sera réalisée au travers d'un paquet npm.

Remarque importante

Comme pour les projets Composer, votre projet va générer de nombreux petits fichiers qui seront stockés localement dans le répertoire « node_modules » de votre projet.

Les infrastructures des systèmes d'information de l'université et du département informatique compliquent l'accès rapide à de très nombreuses ressources. Afin d'obtenir des temps de réaction convenables pour les différents outils que vous utiliserez, vous êtes encouragé à travailler dans le répertoire local « /working » de votre poste de travail.

Afin de ne pas laisser votre travail uniquement sur la machine, vous devrez impérativement réaliser un push en fin de séance afin de le sauver sur le serveur Gitlab.

Vous pourrez facilement réinitialiser votre projet sur une nouvelle machine à l'aide de la commande git clone suivie de npm install dans le répertoire du projet. Cette dernière commande permet de réinstaller tous les modules npm dont dépend votre projet.

Vous commencerez par créer un répertoire de travail pour votre projet nommé r301-js-introduction.

Dans ce répertoire, vous allez créer un nouveau paquet npm à l'aide de la commande : npm init --yes, permettant d'initialiser le paquet npm en créant un fichier « package.json » dans le répertoire courant. Cette commande est normalement interactive, mais l'option --yes initialise le fichier « package.json » avec les valeurs par défaut.

Vous pouvez modifier ces valeurs en éditant directement le fichier « package.json », une liste exhaustive des différentes options est disponible dans la documentation de npm.

La gestion de versions et l'archivage seront réalisés à l'aide de Git. Pour un rapide tour d'horizon de Git, vous pouvez vous référez au site de monsieur Nourrit.

Vous commencerez par créer un dépôt local à l'aide de la commande  : git init. Cette commande provoque la création d'un répertoire "caché" « .git » contenant les données du dépôt local.

Git propose de définir dans un fichier « .gitignore » les fichiers ou répertoires à ignorer lors de son suivi de version. En vous basant sur la documentation ou le paragraphe relatif du livre « Pro Git », vous ignorerez le répertoire « node_modules ».

Vous pourrez ensuite indiquer à Git de suivre tous les fichiers actuellement dans votre répertoire : git add . avant de réaliser le premier « commit » de votre dépôt : git commit -m "Initial commit".

Vous associerez votre dépôt local à un dépôt distant nommé « r301-js-introduction ». Vous veillerez à ajouter votre intervenant de TP comme membre du projet avec un rôle de « Reporter ».

Vous pourrez ensuite associer votre dépôt local au dépôt distant à l'aide de la commande :git remote add origin URL_DU_DÉPÔT, puis pousser la réplication de votre dépôt local grâce à la commande : git push.

Travail à réaliser
  • Créer un répertoire local.
  • Y créer un module npm en générant un fichier package.json.
  • Y créer un dépôt Git local.
  • Exclure le répertoire « node_modules » du versionnage.
  • Répliquer le dépôt local sur le serveur distant GitLab.
  • Vérifier les membres et leurs rôles.

Installation d'un lanceur de tests

Les paquets npm sont couramment utilisés afin d'installer et de gérer facilement des outils ou bibliothèques à intégrer à un projet. Vous allez maintenant installer vos premiers modules npm.

Au cours de ce TP, vous allez valider le code que vous produirez à l'aide de tests. Dans cette optique, vous allez utiliser un lanceur de tests largement utilisé dans la communauté JavaScript : Jest. Vous commencerez donc par installer le module npm Jest à l'aide de la commande suivante :

npm install --save-dev jest

Cette commande réalise l'installation locale du module Jest.

Les espaces de stockage n'étant plus réellement un problème dans les environnements modernes, vous êtes généralement encouragé à travailler en local, pour pouvoir gérer les versions des modules que vous utilisez, par projet.

Un nouveau répertoire « node_modules » a été créé dans votre répertoire de travail, il contient les modules installés en local, avec notamment un sous-répertoire « .bin » contenant les fichiers exécutables (par exemple, ./node_modules/.bin/jest).

Avant de réaliser votre prochain commit, vous prendrez soin de vérifier que le répertoire « node_modules » n'est pas versionné par Git. En effet, les dépendances d'un projet n'ont pas à être versionnées, car elles peuvent être regénérées à l'aide de la commande npm install.

Une fois l'outil Jest installé, vous pouvez maintenant l'exécuter depuis le répertoire de votre projet avec la commande npx jest.

Pour l'instant la commande devrait échouer, car nous n'avons pas encore mis en place de tests dans notre projet.

Travail à réaliser
  • Installation locale d'un paquet npm : Jest.
  • Contrôle du .gitignore, ignorant le répertoire node_modules.

Support des ES Modules dans les tests

Il existe à l'heure actuelle deux standards pour l'import de code JavaScript dans des fichiers JavaScript : « Common JS » et « ES Module ».

« ES Module » est le standard qui devrait à terme être la solution unique. « Common JS » est la solution développée par NodeJS qui est encore largement répandu dans les paquets npm.

Dans la suite de ce TP, vous utiliserez la syntaxe « ES Module » pour les imports et exports de modules.

Jest à contrario, utilise des modules « Common JS ». Afin de simplifier la gestion des différentes versions de modules JavaScript, nous allons utiliser un transpileur permettant de convertir du code JavaScript écrit d'une version à l'autre : Babel.

Pour installer Babel avec une configuration standard, vous installerez les paquets @babel/core et @babel/preset-env :

npm install --save-dev \
    @babel/core \
    @babel/preset-env

Vous devrez ensuite ajouter la configuration de Babel suivante (« babel.config.js » (télécharger)), dans le répertoire de votre projet :

Enfin, pour que Jest utilise Babel pour transpiler les fichiers JavaScript lors de l'exécution des tests, comme expliqué dans la documentation de Jest, vous ajouterez le plugin jest permettant à Jest d'utiliser Babel : babel-jest.

npm install --save-dev babel-jest

Votre projet est maintenant prêt pour lancer des tests.

Travail à réaliser
  • Installation de Babel.
  • Configuration de Babel.
  • Ajouter le module babel-jest.

Initialisation des tests

Afin de tester le bon fonctionnement de Jest, vous allez ajouter un peu de code avec les tests associés à votre projet.

Vous créerez deux nouveaux répertoires dans votre projet : src et tests. Le premier accueillera le code de votre projet et le second accueillera les tests du projet.

Vous pourrez ensuite ajouter un nouveau fichier de source « introduction.js » (télécharger), dans le répertoire src de votre projet :

Vous noterez l'utilisation des exports nommés, permettant de rendre accessibles vos fonctionnalités à l'extérieur du module.

Vous ajouterez ensuite le fichier de tests associé  « introduction.test.js » (télécharger), dans le répertoire tests de votre projet :

Encore une fois, vous constaterez l'utilisation des imports nommés, permettant d'accéder aux ressources exportées de manière nommée d'un module.

Vous pouvez maintenant relancer la commande Jest pour contrôler que le code source est bien validé par les tests, à l'aide de la commande npx jest.

npm comme Composer propose de définir des scripts personnalisés pour regrouper les différentes commandes utiles du paquet.

Actuellement, le script « test » est déjà défini dans votre projet. Vous remplacerez le contenu actuel par l'exécution de la commande de lancement de Jest.

Travail à réaliser
  • Création des répertoires src et tests dans le projet.
  • Ajout du fichier source introduction.js.
  • Ajout du fichier de tests introduction.tests.js.
  • Correction du script npm test pour qu'il exécute la commande Jest.

Qualité de code, ESLint et Prettier

Afin d'améliorer l'expérience de développement et la qualité du code en général, il est courant de mettre en place un linter permettant de réaliser une analyse statique du code au cours de sa rédaction. Ceci permet d'éviter de nombreuses erreurs ou mauvaises pratiques très rapidement, sans avoir à faire de nombreux aller-retours entre le code et les tests.

ESLint est un linter largement employé dans la communauté JavaScript. Il est intégralement configurable, au point qu'il est très complexe et fastidieux de le faire soi-même. Dans notre cas, nous utiliserons un ensemble de règles issues du guide de développement de Airbnb.

Pour installer ESLint, vous utiliserez l'outil interactif d'ESLint à l'aide de la commande suivante 

npx eslint --init

ESLint vous pose quelques questions pour configurer l'environnement :

  • « How would you like to use ESLint? » : « To check syntax, find problems, and enforce code style »,
  • « What type of modules does your project use? » : « JavaScript modules (import/export) »,
  • « Which framework does your project use? » : « None of these »,
  • « Does your project use TypeScript? » : « No »,
  • « Where does your code run? » : « Browser »,
  • « How would you like to define a style for your project? » : « Use a popular style guide »,
  • « Which style guide do you want to follow? » : « Airbnb: https://github.com/airbnb/javascript »,
  • « What format do you want your config file to be in? » : « JavaScript »,
  • « Would you like to install them now with npm? » : « Yes »,

Une fois les paquets npm installés, vous disposez de l'outil ESLint configuré et prêt dans votre projet, mais avant de l'utiliser, vous allez lui adjoindre un formateur. En effet, même si ESLint dispose de quelques règles sur la mise en forme du code, pour uniformiser le rendu du code d'un projet, il est courant de lui ajouter Prettier.

Pour cela, vous installerez différents paquets : l'outil Prettier, un paquet désactivant les règles d'ESLint en conflit avec Prettier et le plugin ESLint permettant d'exécuter Prettier comme un ensemble de règles d'ESLint :

npm install --save-dev \
    prettier \
    eslint-config-prettier \
    eslint-plugin-prettier

Malheureusement, la configuration du projet n'est pas tout à fait finie. En effet, pour l'instant ESLint ne reconnait pas l'environnement de Jest. Vous ajouterez le plugin ESLint de support de Jest à l'aide de la commande suivante :

npm install --save-dev eslint-plugin-jest

Vous modifierez la configuration d'ESLint ( « .eslintrc.js » (télécharger)) pour y intégrer les paquets que vous venez d'installer.

Vous pouvez maintenant contrôler votre base de code depuis le terminal à l'aide de la commande npx eslint src tests. Et l'option --fix permet de résoudre tous les conflits qu'ESLint peut régler sans votre intervention : npx eslint src tests --fix.

Les paquets npm proposant d'embarquer des commandes pour simplifier leur invocation. Vous ajouterez les instructions suivantes dans la section scripts du fichier « package.json » :

Vous aurez alors accès aux commandes définies dans « scripts » à l'aide de la commande run, par exemple : npm run lint ou npm run fix.

Afin d'améliorer votre experience utilisateur, vous activerez le support d'ESLint dans votre éditeur de code afin d'avoir un retour visuel sur votre code en cours de frappe.

WebStorm/PHPStorm supportent nativement ESLint et doivent juste activer son utilisation dans la configuration générale (utiliser la barre de recherche de la configuration).

Les autres éditeurs comme VSCode devront probablement installer un plugin pour ajouter le support d'ESLint.

Travail à réaliser
  • Installation d'ESLint.
  • Installation de Prettier.
  • Ajout du support de Jest par ESLint.
  • Configuration d'ESLint.
  • Ajout de nouveaux scripts npm.
  • Configuration de l'éditeur de code.

Mise en place des tests

Maintenant que l'infrastructure de développement est bien en place et correctement configurée, vous allez pouvoir commencer à développer votre projet.

Mais avant de commencer vous remplacerez le fichier de tests « introduction.test.js » par le fichier suivant : « introduction.test.js » (télécharger), dans le répertoire tests de votre projet, afin de valider la réalisation de votre code.

En effet, ce fichier contient maintenant un jeu de tests pour l'ensemble des fonctions que vous allez devoir produire. Pour l'instant, en attendant que vous exportiez les fonctions à tester, le fichier devrait produire 4 tests valides.

Vous pourrez tester le bon fonctionnement des tests en exécutant la commande : npm test

Pour améliorer l'expérience de développement, en évitant de relancer la commande à chaque modification du code, vous pourrez utiliser l'option --watch de Jest. Dans le cadre du développement, vous pouvez utiliser la commande suivante :

npm test -- --watch
Travail à réaliser
  • Remplacement du fichier de tests introduction.tests.js.
  • Validation de 4 tests valides.

Somme d'un tableau d'entier

Vous allez enfin réaliser un peu de code en ajoutant une nouvelle fonction au fichier « introduction.js ».

la fonction sum(values) sera exportée nommée. Elle accepte comme paramètre values un tableau de nombres et elle retourne la somme de ces nombres.

Si vous n'êtes pas très familier avec le langage, vous pouvez vous référer à la documentation sur l'utilisation des tableaux de Mozilla, ou plus particulièrement les instructions de parcours ou l'équivalent fonctionnel.

Travail à réaliser
  • Ajout de la fonction sum(values).
  • Validation de 7 tests valides.

Ajout d'une valeur à chaque case d'un tableau

Vous ajouterez la fonction addToAll(values, toAdd) au fichier introduction.js afin de valider les tests.

Cette fonction permet d'ajouter la valeur toAdd à toutes les valeurs d'une copie du tableau values.

Vous pourrez utiliser la méthode map pour réaliser votre fonction, en étudiant l'utilisation des fonctions fléchées.

Travail à réaliser
  • Ajout de la fonction addToAll(values, toAdd).
  • Validation de 10 tests valides.

Calcul de la moyenne des valeurs d'un tableau

Vous ajouterez la fonction average(values) au fichier introduction.js afin de valider les tests.

Cette fonction calcule et retourne la moyenne des valeurs du tableau values, elle doit retourner null lorsque le tableau est vide.

Travail à réaliser
  • Ajout de la fonction average(values).
  • Validation de 13 tests valides.

Identification d'un utilisateur adulte ou mineur

Vous créerez les fonctions isAdult(user) et isChild(user). Ces fonctions reçoivent en paramètre un objet JavaScript contenant une propriété age et retourne un booléen.

  • la fonction isAdult(user) retournera vrai si l'utilisateur a 18 ans ou plus et faux sinon.
  • la fonction isChild(user) retournera vrai si l'utilisateur a moins de 18 ans et faux sinon.
Travail à réaliser
  • Ajout de la fonction isAdult(user).
  • Ajout de la fonction isChild(user).
  • Validation de 19 tests valides.

Extraction de l'âge d'un tableau d'utilisateurs

Vous ajouterez la fonction extractAge(users) au fichier introduction.js afin de valider les tests.

Elle accepte en paramètre un tableau d'utilisateurs, similaires aux objets JavaScript précédents, et elle retournera un nouveau tableau contenant uniquement les âges des utilisateurs.

Travail à réaliser
  • Ajout de la fonction extractAge(users).
  • Validation de 22 tests valides.

Filtrage des utilisateurs par âge

Vous pourrez ensuite ajouter la fonction adultFilter(users, type) au fichier introduction.js afin de valider les tests.

La fonction recevra deux paramètres, le premier, users, contiendra un tableau d'utilisateurs à filtrer, le second, type, sera une chaîne de caractères contenant le type d'utilisateurs souhaité.

  • Si type vaut "adult", alors la fonction retourne un nouveau tableau ne contenant que les utilisateurs d'âge supérieur ou égal à 18 ans.
  • Si type vaut "child", alors la fonction retourne un nouveau tableau ne contenant que les utilisateurs d'âge inférieur à 18 ans.
  • Si type vaut autre chose, alors la fonction retourne le tableau users.

La méthode d'instance filter de la classe Array de JavaScript se prête bien à cet exercice.

Travail à réaliser
  • Ajout de la fonction adultFilter(users, type).
  • Validation de 26 tests valides.

Âge moyen des utilisateurs

La fonction ageAverage(users, type) acceptera deux paramètres, le premier, users, contiendra un tableau d'utilisateurs, le second, type, sera une chaîne de caractères contenant le type d'utilisateurs dont on souhaite l'âge moyen. La fonction retourne l'âge moyen des utilisateurs sélectionnés selon le paramètre type.

Travail à réaliser
  • Ajout de la fonction ageAverage(users, type).
  • Validation de 30 tests valides.

Vérification de l'âge d'un groupe

Vous ajouterez les fonctions isAllAdult(users) et hasChild(users) qui retournent toutes les deux un booléen.

  • isAllAdult(users) retourne vrai si tous les utilisateurs dans users ont un âge supérieur ou égal à 18 et faux sinon.
  • hasChild(users) retourne vrai si au moins un utilisateur dans users a un âge inférieur à 18 et faux sinon.

Vous essayerez de trouver les solutions les plus optimales. Les méthodes d'instance every et some de la classe Array de JavaScript peuvent vous aider à réaliser les fonctions.

Travail à réaliser
  • Ajout de la fonction isAllAdult(users).
  • Ajout de la fonction hasChild(users).
  • Validation de 36 tests valides.

Ajout d'une propriété isAdult aux utilisateurs

Pour finir, vous exporterez la fonction addIsAdultProperty(users) retourne un nouveau tableau contenant des copies des utilisateurs initiaux, avec une nouvelle propriété isAdult, valant vrai si l'âge de l'utilisateur est supérieur ou égal à 18 et faux sinon.

Afin de copier les objets, vous pourrez vous référer à la documentation sur les copies de surface et les copies profondes du Mozilla Developer Network, et plus particulièrement sur la syntaxe de décomposition des objets JavaScript.

Travail à réaliser
  • Ajout de la fonction addIsAdultProperty(users).
  • Validation de 40 tests valides.

Mise en place d'un outil de création de bibliothèque

Le support de l'import de module JavaScript dans les navigateurs est encore assez récent. Pour nous assurer un meilleur support des navigateurs plus anciens, vous allez ajouter un outil de création de bibliothèque dont le rôle principal est d'agréger en une seule ressource l'ensemble de la base de code.

De plus, ces outils sont généralement capables d'optimiser la taille de la base de code en minifiant le code et en supprimant les exports non utilisés.

L'un de ces outils, largement répandu dans la communauté JavaScript, est Webpack. De plus, il est possible de l'intégrer à un projet Symfony, mais nous n'irons pas jusque là au cours de ce TP.

Vous commencerez donc par installer Webpack à l'aide de la commande suivante :

npm install --save-dev \
    webpack \
    webpack-cli

Vous ajouterez ensuite le fichier de configuration de Webpack (« webpack.config.js » (télécharger)) suivant à votre projet :

La configuration précise à Webpack que le fichier principal de la bibliothèque est « ./src/index.js » et que le résultat doit être produit dans un fichier « index.js » d'un sous répertoire « public/js » du projet.

Vous ajouterez donc le fichier principal de la bibliothèque « index.js » (télécharger) à votre projet :

Vous devriez maintenant être capable de produire votre bibliothèque à l'aide de la commande npx webpack. Cette commande va produire la génération de la bibliothèque dans le répertoire « public/js ». Vous veillerez à ajouter à votre « .gitignore » ce fichier généré.

La configuration de Webpack ci-dessus précise le mode « développement », aucune optimisation n'est faite sur le code, la priorité est donnée à la rapidité de la construction de la bibliothèque. Vous pouvez construire votre bibliothèque en mode « production » à l'aide l'option --mode=production. Vous pourrez constater que la taille du fichier produit est largement réduite.

Une autre option intéressante, de manière similaire à Jest, est l'option --watch qui permet de reconstruire la bibliothèque automatiquement lors des modifications de la base de code.

Vous ajouterez 3 scripts npm au fichier « package.json » :

  • build, permettant de créer la bibliothèque en mode « développement ».
  • build:prod, permettant de lancer la commande build en mode « production ».
  • build:watch, permettant de lancer la commande build automatiquement lors des modifications de code.
Travail à réaliser
  • Installation de Webpack.
  • Ajout de la configuration de Webpack.
  • Ajout du fichier principal de la bibliothèque.
  • Ajout du fichier généré à « .gitignore ».
  • Ajout des scripts npm.

Le serveur de développement de Webpack

Dans le cadre d'une application Symfony, Webpack peut suffire à la gestion du JavaScript, chaque modification du code source regénère la bibliothèque dans le répertoire « public » de l'application afin que le serveur Symfony fournisse le fichier minifié lors du chargement de la page contenant son utilisation.

Mais dans le cadre de ce TP, nous allons simplifier le projet en nous passant de Symfony et en nous rapprochant d'une expérience de développement front-end. Nous allons utiliser le serveur de développement de Webpack qui permet un rechargement « à chaud » de l'application.

Vous commencerez par installer le serveur de développement de Webpack ainsi qu'un plugin simplifiant la gestion du rechargement à chaud de la page :

npm install --save-dev \
    webpack-dev-server \
    html-webpack-plugin

Le plugin html-webpack-plugin permet de construire automatiquement la page HTML contenant le script généré par Webpack, en utilisant comme base un patron de page HTML.

Vous ajouterez le patron de page HTML (« src/template.html » (télécharger)) suivant dans le répertoire « src » de votre projet :

Vous modifierez ensuite la configuration de Webpack pour qu'elle utilise ces deux paquets :

Vous devriez maintenant être capable de lancer le serveur de développement à l'aide de la commande npx webpack serve. Dans votre navigateur, en ouvrant la console de développement, vous constaterez que la bibliothèque est bien fonctionnelle, avec l'affichage du calcul « 1 + 2 = 3 ». Vous constaterez aussi le rafraîchissement à chaud de la page lorsque vous sauvez des modifications du calcul dans « index.js ».

Pour finir, vous ajouterez un script npm « start » permettant de lancer le serveur de développement.

Travail à réaliser
  • Installation des paquets webpack-dev-server et html-webpack-plugin.
  • Ajout du patron de page HTML.
  • Configuration du serveur de développement.
  • Ajout d'un script npm « start ».

Mise en place d'une page HTML de travail

Vous allez maintenant ajouter un peu de code pour interagir avec la page.

Avant toutes choses, vous allez mettre en place une page HTML contenant des éléments avec lesquels interagir. Vous remplacerez le patron de page HTML (« src/template.html » (télécharger)) par le contenu suivant :

Pour que la page soit fonctionnelle, vous ajouterez le script CSS « public/css/index.css » (télécharger) dans le répertoire « public/css » de votre projet.

Vous devriez obtenir une page correspondant à la maquette suivante :

Illustration de l'affichage de l'application
Travail à réaliser
  • Modification du patron de page HTML.
  • Ajout du script de style CSS.

Mise en place des tests de DOM

Comme précédemment, vous allez utiliser des tests pour valider le code que vous produirez, mais pour pouvoir simuler le DOM dans les tests, vous allez devoir ajouter un nouveau paquet :

npm install --save-dev jest-environment-jsdom

Vous pourrez ensuite ajouter le fichier de tests suivant « users-ui.test.js » (télécharger), dans le répertoire « tests » de votre projet.

Puis vous ajouterez un fichier « users-ui.js » (télécharger), dans le répertoire « src » de votre projet.

Vous constaterez, dans ce fichier, la fonction exportée de manière nommée : createHtmlUser(), qui retourne un élément HTML de type « li » avec une classe CSS « user ».

La création d'un élément du DOM, et plus particulièrement HTML, en JavaScript est réalisée à l'aide de la méthode createElement de l'instance document. Pour lui ajouter un contenu textuel, toujours dans le cadre du DOM, un nouveau nœud texte doit être créé, puis ajouté à l'aide de la fonction appendChild. Vous verrez dans la suite du TP que l'on peut simplifier ce processus dans le cadre du HTML.

Pour spécifier les classes CSS d'un élément en DOM, vous auriez recours à createAttribute, mais en DOM HTML vous pouvez utiliser les propriétés classList ou className.

L'exécution du nouveau jeu de tests devrez faire passer 4 nouveaux tests valides, soit 44 au total.

Travail à réaliser
  • Installation de l'environnement de tests du DOM dans Jest.
  • Ajout du fichier de tests « users-ui.test.js ».
  • Ajout du fichier source « users-ui.js ».
  • Validation de 44 tests valides (4 dans « users-ui.test.js »).

Gestion du clic de la souris sur le bouton d'ajout

Vous allez créer une fonction dont le rôle va être d'enregistrer un écouteur de clic sur le bouton d'ajout d'utilisateur (« button.user-data__add »). La fonction de rappel devra créer un nouvel utilisateur (createHtmlUser()) et l'ajouter au conteneur HTML d'utilisateurs (« ul.users »).

Vous ajouterez donc la fonction setAddUserEltCallback(addUserElt, usersElt), export nommé au fichier « users-ui.js ». Cette fonction acceptera en paramètre deux élément HTML :

  • addUserElt l'élément HTML du bouton d'ajout d'un utilisateur (« button.user-data__add »),
  • usersElt l'élément HTML du conteneur d'utilisateurs (« ul.users »).

La fonction ajoutera un écouteur sur le clic de la souris et la fonction de rappel ajoutera un utilisateur (createHtmlUser()) au conteneur HTML d'utilisateurs.

Vous remplacerez ensuite le contenu du script principal de la bibliothèque (« src/index.js ») par l'invocation de cette fonction. Pour retrouver les éléments HTML addUserElt et usersElt, vous pourrez utiliser la méthode querySelector.

Travail à réaliser
  • Ajout des tests.
  • Réalisation de la fonction setAddUserEltCallback(addUserElt, usersElt) dans le fichier « users-ui.js ».
  • Invocation de la fonction setAddUserEltCallback depuis le script principal.
  • Validation de 46 tests valides (6 dans « users-ui.test.js »).

Finalisation de l'affichage des utilisateurs

Vous allez finaliser l'affichage des utilisateurs dans la page en leur ajoutant un nom, un âge ainsi qu'un bouton de suppression, conformément à la maquette ci-dessous :

Illustration de l'affichage d'un utilisateur

Vous allez modifier la fonction createHtmlUser afin qu'elle ajoute la structure HTML requise.

Le nom de l'utilisateur sera toujours « name », mais l'âge sera reçu en paramètre de la fonction et généré aléatoirement dans la fonction setAddUserEltCallback. Vous pourrez utiliser un intervalle de 12 à 32 ans par exemple. Les fonctions mathématiques floor et random vous seront utiles.

Vous avez pu constater qu'il est un peu fastidieux de générer du DOM avec l'API DOM. Vous pouvez vous simplifier le travail en utilisant la propriété innerHTML qui permet de définir du HTML sous forme de chaîne de caractères lors de la génération du contenu de l'affichage d'un utilisateur.

Pour injecter une variable au milieu d'une chaîne de caractères, vous pouvez concatener les différentes parties de celle-ci, mais une solution plus élégante consiste à utiliser les littéraux de gabarits.

Comme pour le bouton d'ajout d'un utilisateur, le bouton de suppression d'un utilisateur contiendra l'icône Material Symbols « Delete ».

Travail à réaliser
  • Modification de la fonction createElement(age) dans le fichier « users-ui.js ».
  • Validation de 50 tests valides (10 dans « users-ui.test.js »).

Extraction des informations d'un utilisateur

Les données d'un utilisateur sont stockées dans la page HTML, dans les éléments input d'un utilisateur (« li.user »). Vous allez ajouter des fonctions permettant de les extraire de la page HTML.

Pour commencer, vous allez ajouter une fonction extractUser(userElt) au fichier « users.ui.js ». Cette fonction recevra en paramètre un élément HTML représentant un utilisateur (« li.user ») et elle retournera un object JavaScript comportant deux propriétés :

  • name contenant la valeur du champ de saisie « .user__name »
  • et age contenant la valeur du champ de saisie « .user__age » sous forme d'un entier (parseInt)
Travail à réaliser
  • Création de la fonction extractUser(userElt) dans le fichier « users-ui.js ».
  • Validation de 52 tests valides (12 dans « users-ui.test.js »).

Extraction des informations de tous les utilisateurs

Par soucis de simplicité, vous réaliserez la fonction extractUsers(usersElt) qui prendra en paramètre l'élément HTML contenant tous les utilisateurs (« ul.users ») et retournera un tableau contenant des object JavaScript similaire à la question précédente, avec des propriété name et age.

La méthode querySelectorAll retourne une liste d'éléments HTML. Cette liste peut être parcourue, mais elle ne supporte pas les méthodes de la classe Array. Pour transformer un objet parcourable en un tableau, vous pouvez utiliser la méthode de classe from de la classe Array ou l'opérateur de décomposition.

Travail à réaliser
  • Création de la fonction extractUsers(usersElt) dans le fichier « users-ui.js ».
  • Validation de 54 tests valides (14 dans « users-ui.test.js »).

Extraction du type d'utilisateurs

Pour faciliter le calcul de la moyenne en fonction du type d'utilisateurs souhaité, vous allez créer la fonction extractUserType(infoElt) qui prendra en paramètre l'élément HTML affichant les informations des utilisateurs et retournera la valeur de l'input de type radio sélectionné.

Travail à réaliser
  • Création de la fonction extractUserType(infoElt) dans le fichier « users-ui.js ».
  • Validation de 57 tests valides (17 dans « users-ui.test.js »).

Mise à jour de la moyenne des utilisateurs

Vous ajouterez ensuite la fonction updateAgeAverage(usersElt, infoElt) qui recevra en paramètre l'élément HTML contenant les utilisateurs ainsi que l'élément affichant les informations des utilisateurs.

Cette fonction extraira de la page les informations nécessaires (données utilisateurs et type d'utilisateur), elle calculera la moyenne des âges (ageAverage(users, type)) et elle affichera cette moyenne dans l'élément HTML concerné (« info__age-average »).

Les données des utilisateurs peuvent être obtenues à l'aide de extractUsers(usersElt) et le type d'utilisateurs peut être obtenu à l'aide de extractUserType(infoElt).

Plusieurs solutions sont envisageables pour l'ajout de texte dans un élément. La plus simple et la plus efficace est probablement d'utiliser la propriété innerText de l'élément.

De plus, la moyenne tombe rarement juste. Pour que l'affichage soit plus élégant, vous utiliserez conjointement les fonctions parseFloat et toFixed afin de contraindre l'affichage de la moyenne à 2 décimales.

Vous pourrez ensuite utiliser la fonction updateAgeAverage dans la fonction setAddUserEltCallback afin que la moyenne soit mise à jour lors de chaque ajout d'utilisateur.

Dans cette optique, vous ajouterez un nouveau paramètre infoElt à la fonction setAddUserEltCallback, qui recevra l'élément HTML affichant les informations utilisateurs (« article.info »).

Ce paramètre sera optionnel, vous prendrez soin dans la fonction setAddUserEltCallback de tester la présence du paramètre avant d'invoquer la fonction updateAgeAverage.

Travail à réaliser
  • Création de la fonction updateAgeAverage(usersElt, infoElt) dans le fichier « users-ui.js ».
  • Ajout d'un paramètre optionnel infoElt à la fonction setAddUserEltCallback(addUserElt, usersElt, infoElt).
  • Utilisation conditionnelle de la fonction updateAgeAverage dans la fonction setAddUserEltCallback.
  • Validation de 61 tests valides (21 dans « users-ui.test.js »).

Modification d'un utilisateur

Vous ajouterez une fonction setUserEltCallbacks(userElt, usersElt, infoElt) au fichier « users-ui.js ». Cette fonction aura pour rôle d'enregistrer les gestionnaires d'événements d'un utilisateur.

Vous commencerez en ajoutant un gestionnaire d'événement sur le bouton de suppression de l'utilisateur passé en paramètre (userElt). Le gestionnaire d'événement réagira au clic de la souris pour supprimer l'utilisateur et mettre à jour la moyenne si l'élément HTML d'affichage des informations utilisateurs a été passé en paramètre (infoElt).

Vous ajouterez ensuite un gestionnaire d'événement sur le champ de saisie de l'âge d'un utilisateur. Le gestionnaire d'événement réagira au changement de valeur pour mettre à jour la moyenne si l'élément HTML d'affichage des informations utilisateurs a été passé en paramètre (infoElt).

Vous ajouterez l'invocation à la fonction setUserEltCallbacks lors de l'ajout d'un nouvel utilisateur à la page HTML, dans la fonction de rappel de la fonction setAddUserEltCallback.

Travail à réaliser
  • Création de la fonction setUserEltCallbacks(userElt, usersElt, infoElt) dans le fichier « users-ui.js ».
  • Gestion de la suppression d'un utilisateur.
  • Gestion du changement d'age d'un utilisateur.
  • Validation de 64 tests valides (24 dans « users-ui.test.js »).

Modification du type d'utilisateur

Enfin, pour que la modification des boutons radios mette à jour la moyenne des utilisateurs, vous ajouterez la fonction setAgeTypeEltEvents(usersElt, infoElt) qui devra enregistrer un gestionnaire d'événements sur les boutons radios. Les gestionnaires d'événements réagiront au changement de valeur des boutons radios en mettant à jour la moyenne si l'élément HTML d'affichage des informations utilisateurs a été passé en paramètre (infoElt).

Vous invoquerez ensuite cette fonction depuis le script principal de la bibliothèque (« src/index.js »).

Travail à réaliser
  • Création de la fonction setAgeTypeEltEvents(usersElt, infoElt) dans le fichier « users-ui.js ».
  • Validation de 68 tests valides (28 dans « users-ui.test.js »).
  • Invocation de la fonction dans le script principal.

Facultatif - détection des mineurs

Vous ajouterez une nouvelle fonction updateUserClassName(userElt) qui ajoutera ou supprimera une classe CSS « user--child » à l'élément HTML passé en paramètre en fonction de la valeur du champ de saisie de l'âge de l'utilisateur.

Pour la modification des classes CSS, vous pourrez utiliser la propriété classList d'un élément, et plus particulièrement les méthodes add et remove de celle-ci.

Vous utiliserez cette fonction dans vos différentes fonctions de rappels afin que les classes CSS soient mises à jour lors des interactions de l'utilisateur.

Travail à réaliser
  • Création de la fonction updateUserClassName(userElt) dans le fichier « users-ui.js ».
  • Utilisation de la fonction updateUserClassName dans les différentes fonctions de rappels.
A. Jonquet DUT-INFO/REIMS