Cette page fait partie de notre guide pour apprendre à coder un site web simple. Nous avons déjà codé une page HTML, mais on aimerait la rendre plus flexible, notamment pour supporter plusieurs pages. En effet, j’ai plusieurs pages, je devrais à chaque fois rajouter le header par exemple, alors qu’il devrait être le même partout (ou en tout cas être généré procéduralement). De plus, nous aimerions avoir une sorte de blog, et que les « cartes » présentant les différents articles s’insèrent automatiquement avec leurs informations (titres, image, extrait). Nous l’avons fait avec PHP, ici, nous allons le faire avec Javascript.
Le gros avantage est qu’on n’a pas besoin d’environnement particulier (alors qu’il faut un serveur pour PHP). Donc à votre Visual Studio Code et allons-y !
Factoriser la structure du site
On va commencer par le plus simple: factoriser la structure du site. Le head, header et footer vont aller dans un fichier « structure.js » qui va procéduralement les injecter dans le HTML.
Connecter le HTML et le javascript
Tout d’abord, il faut connecter la page HTML au ficher javascript. Pour cela, rien de plus facile : on place « <script src= »[CHEMIN] »></script> » (ici <script src= »structure.js »></script>) en fin de fichier.
Il faut le mettre en fin de fichier pour que le reste du code ait eu le temps de se charger avant que le javascript ne se déclenche. Par exemple, s’il se déclenchait avant que la balise footer ne soit chargée, le sélecteur ciblant cette balise ne la trouverait pas et ne fonctionnerait pas.
L’injection dans le DOM
Vocabulaire: le « DOM » (Document Object Model) est ce que le navigateur affiche. L’injection va venir modifier le DOM.
L’injection est très facile. On va d’abord sélectionner la partie du document à changer grâce à la fonction querySelector() :
ex: « const head = document.querySelector(‘head’);«
Ensuite, on va affecter le HTML à la zone voulue grâce à .innerHTML (=modifie le contenu html) et en mettant le code souhaité entre backtick (`) (voir ci-contre). Cette notation est appelée « template literals« .
head.innerHTML += `
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<LINK href="style.css" rel="stylesheet" type="text/css">
<LINK href="normalize.css" rel="stylesheet" type="text/css">
`;
La difficulté: les titres
Nous allons avoir plusieurs pages, qui auront chacune leur propre titre. Comment le gérer ? De plus, on veut que les articles aient un H1 qui contient aussi ce titre. Pour cela, on va faire, en substance, comme pour le PHP: on déclare une variable titre dans le fichier HTML et elle va venir peupler le title dans le head.
Pour le H1, on va avoir une solution un peu plus élégante. Alors qu’en PHP, on insérait manuellement le bout de code dans chaque HTML, ici on va pouvoir cibler l’élément englobant le contenu des articles (il s’agit d’une division avec l’id « contenu-articles ») et y insérer, juste après, la balise et le titre grâce au code ci-contre.
Notez que cette segmentation en deux étapes (d’abord on déclare une variable ciblant l’élément du DOM et ensuite on agit dessus) est impérative: si vous souhaitez faire les deux en même temps (ex: h1Element = document.createElement(‘h1’).textContent = titre ;)., vous obtenez une erreur.
const contenuDiv = document.getElementById('contenu-articles');
const h1Element = document.createElement('h1');
h1Element.textContent = titre;
contenuDiv.appendChild('afterend', h1Element);
L’injection des articles de blog
Pour l’injection des miniatures des articles de blogs, on a d’abord créé une fonction permettant de raccourcir le texte. En effet, comme nous l’avions vu avec le tuto sur le PHP, si on ne le raccourcit pas, cela pose problème. C’est la fonction raccourcit. Ensuite, la fonction creeCarte permet de formater une carte en utilisant cette fonction pour générer le titre et l’extrait raccourcis. Enfin, la fonction boucleArticles permet de générer une de ces cartes pour chaque article à afficher. Ce code se trouve dans le fichier boucle.js, qui ne concerne que la page d’accueil.
Page contact et formulaire
En PHP, on avait fait une page contact et une ébauche de formulaire, qui nous permettait « d’attraper » les données de manière éphémère, dans le DOM d’un fichier php. Tentons de faire de même ici.
La grande différence est qu’on ne peut pas appeler, dans la propriété action, un fichier php qui viendrait « gérer » les données qu’on a envoyées. A la place, nous allons « neutraliser » le fonctionnement « normal » du formulaire en ne renseignant pas la propriété « action » et « méthod », mais utilisant un écouteur d’événements dans un fichier « contact.js » et la fonction prevent.default qui évite que la page ne se recharge quand on clique sur submit.
Ainsi, au lieu d’avoir « <form action= »gestion_contact.php » method= »post » id= »formulaire »>« , on a simplement « <form id= »formulaire »>«
Originalité : les filtres
En PHP, nous n’avions pas pu utiliser les filtres pour modifier dynamiquement l’affichage. Javascript en est capable, nous allons donc en faire une petite présentation. J’ai changé l’intitulé des filtres pour ne pas avoir à créer d’autres articles. On va écrire notre code dans le fichier « boucle.js », puisqu’il s’agit d’une fonctionnalité associée et qu’on va modifier notre fonction boucleArticles().
On va d’abord créer une série d’eventListener (écouteurs ou gestionnaires d’événements) sur les boutons. On sélectionne l’ensemble des boutons dans une variable buttons de type tableau (vu qu’on utilise « querySelectorAll »). Puis, on affecte le gestionnaire d’événement à chaque élément de ce dernier en faisant que le clic déclenche la fonction de génération de boucleArticles avec les paramètres souhaités.
Notez que la syntaxe n’est pas « button[0].addEventListener(« click »,boucleArticles(articles));« , mais « buttons[0].addEventListener(« click », () => boucleArticles(articles));«
Notez également qu’on ne recharge pas la page entre deux changements de filtres. C’est tout l’intérêt du javascript.
Ce faisant, on obtient ce qu’on veut. Néanmoins … il manque quelque chose: sur quelle catégorie est-ce qu’on a cliqué ? On ne sait pas. Il faudrait donc pouvoir colorer l’icône actif de catégorie.
Pour cela, on va faire 3 choses :
- Créer une classe de style (.active-filter) et y appliquer une couleur de fond, avec !important pour que la valeur prévale sur la transparence définie dans le style #filtres button.
- Une fonction permettant d’appliquer et d’enlever cette classe (setActiveFilter)
- Adapter les gestionnaires d’événements pour appliquer cette fonction.
L’apparence change légèrement (c’est sur deux lignes et non plus qu’une), mais vous voyez que la logique ne change pas : en cas de clic, on invoque deux fonctions au lieu d’une seule.
Conclusion
Voilà, on a une petite ébauche d’un site simple, qui en plus est un peu interactif. On a néanmoins plusieurs problèmes avec ce code :
- la structure des fichier est chaotique
- le formulaire a besoin d’une base de données pour fonctionner
Nous résolverons ces problèmes dans la prochaine partie du cours.