Avant d'entamer ce défi, assure toi d'avoir déjà fait ceux de la Fiche 1

Ensuite, assure-toi de te munir d'une grande motivation et soif d'apprendre!

Aussi, assure-toi que tu sois bien connecté à ton compte Repl.It.

Pour l'instant, ton chat fonctionne, mais d'une console à une autre. C'est chouette... mais pas idéal pour pouvoir chatter avec tes amis.

Ce qu'il nous faudrait, c'est un beau site web, avec une chouette interface pour écrire nos messages et voir ceux de nos amis.

Qui dit site web, dit... HTML, CSS et JavaScript!

On va donc créer un nouveau projet repl.it qui va remplacer notre ancien projet du côté Client. Notre nouveau projet sera fait en HTML, CSS et JS, alors choisis bien les langages:

Te voilà avec un projet de site web comme on les connaît bien! Vois-tu les 3 fichiers habituels? index.html, script.js et style.css

Dans notre fichier HTML, on va créer la base de l'interface de notre chat. Voici un exemple d'interface:

Tu peux commencer par coder la partie où tes utilsateurs vont écrire leur message:

Comment coder cela? Ça te rappelle peut-être un autre défi qu'on a fait en web développement? Eh oui, les formulaires dans le défi Madlibs!

À toi de coder ton formulaire!

Ton code pourrait ressembler à ceci:

                
                  <form>
                    <input type="text">
                    <input type="button" value="Envoyer">
                  </form>
                
              

Lorsque tu appuies sur ton bouton "Envoyer", rien ne se passe? C'est normal! Nous allons avoir besoin du JavaScript pour communiquer avec le serveur.

Par contre, essaie de faire en sorte que ton formulaire apparaisse toujours au bas de ton écran.

Tu pourrais avoir besoin de la propriété CSS suivante:

              
                position: fixed;
              
            

Voici de quoi a l'air mon HTML:

                
                  <form>
                    <input type="text">
                    <input type="button" value="Envoyer">
                  </form>
                
                

Et voici de quoi a l'air mon CSS:

              
                form {
                  position: fixed;
                  bottom: 0;
                  padding: 10px;
                  background-color:bisque;
                  width: 100%;
                }
              
            

Bien sûr, tu peux choisir une autre couleur d'arrière-plan!

On va maintenant coder l'inteface pour les messages. Pour l'instant, ce ne seront pas des "vrais" messages qui nous viennent de notre serveur, car nous n'avons pas écrit le code JS pour relier les deux projets.

On va faire semblant que dans notre site, il y a déjà une conversation et que quelques messages ont été échangés. Note dans cet exemple d'interface qu'il y a des messages alignés à gauche (en blanc) et d'autres alignés à droite (en bleu). À ton avis, pourquoi cette distinction?

Pour distinguer les messages que l'utilisatrice écrit (à droite, en bleu) de ceux qu'elle reçoit de ses amis (à gauche, en blanc).

À ton tour, essaie de coder les deux premiers messages des amis (à gauche)! Je te conseille vivement d'utiliser des <div></div> pour cela.

Dans ton HTML, il est vraiment important d'emboîter chaque message dans une <div></div> à soi. Par ailleurs, je donne la même class à chacune de ces div pour pouvoir toutes les styliser de la même façon:

                
                  <div id="messages">
                    <div class="friend-message">
                      Salut, ça va? Regarde le beau chat que j'ai codé!
                    </div>
                    <div class="friend-message">
                      J'espère que tu vas aimer!
                    </div>
                  </div>
                
              

En conséquence, je peux avoir ceci dans mon CSS:

              
                .friend-message {
                  background-color: #708d81;
                  color: white;
                  padding: 10px;
                  margin: 10px;
                  width: 60%;
                }
              
              

Tu peux maintenant coder un ou deux message de ton utilisatrice. Ce sera plus compliqué, car il faut que ces messages soit alignés... à droite de ton écran!

Tu auras besoin d'une nouvelle classe CSS dans laquelle tu pourrais utiliser la propriété float: right;

J'ai donné une nouvelle class="me-message" à chacune des messages de mon utilisatrice pour pouvoir toutes les styliser autrement que les messages des amis:

                
                  <div id="messages">
                    <div class="friend-message">
                      Salut, ça va? Regarde le beau chat que j'ai codé!
                    </div>
                    <div class="friend-message">
                      J'espère que tu vas aimer!
                    </div>
                    <div class="me-message">
                      Wow, c'est super!
                    </div>
                    <div class="me-message">
                      Bravo, dis!
                    </div>
                  </div>
                
              

En conséquence, je peux rajouter ceci dans mon CSS:

              
                .me-message {
                  background-color: #8d0801;
                  color: white;
                  padding: 10px;
                  margin: 10px;
                  width: 60%;
                  float: right;
                }
              
              

Pour l'instant, lorsque tu tapes quelque chose dans le formulaire et que tu appuis sur le bouton "Envoyer", rien ne se passe! Sniff, sniff!😟

On va changer cela avec un peu de JavaScript! Dans ton fichier script.js, ajoute un déclencheur ou un écouteur: le navigateur doit "écouter" voir si l'utilisateur (toi) clique sur le bouton "Envoyer".Te rappelles-tu comment faire pour coder un déclencheur/écouteur?

Dans le défi Madlibs, tu as déjà codé un déclencheur pour le bouton "Raconte-moi une histoire". En anglais, on appelle cela un eventListener.

Tu peux commencer par un déclencheur qui va simplement logguer le message dans la console lorsqu'on clique sur le bouton:

Le code JavaScript de base à ajouter dans ton fichier script.js est le suivant:

              
                function addMyMessage() {
                  // Code à écrire
                }

                const submitButton = document.getElementById("submit");
                submitButton.addEventListener(XXX, addMyMessage);
              
            

Les trois premières lignes définissent une fonction addMyMessage() qu'on va bientôt compléter. La ligne suivante signifie qu'on récupère (get) dans notre fichier HTML la balise qui a l'id "submit". Rajoute l'id "submit" au bon endroit.

Voici la syntaxe: id="submit"

Dans ton fichier index.html, trouve la balise <input type="button" value="Envoyer"> et ajoutes-y ton id: <input type="button" value="Envoyer" id="submit">

La dernière ligne du code JavaScript indique de déclencher la fonction addMyMessage quand l'utlisateur fait quelque-chose XXX. C'est l'événement déclencheur. Voici plusieurs événements possibles:

  • mouseover: l'utilisatrice passe sa souris par-dessus un élément de la page web mais sans cliquer
  • click: l'utilisateur clique sur un élément de la page
  • scroll l'utilisatrice fait défiler la page
  • drag l'utlisateur glisse une section de texte

Remplace les XXX par le bon événement.

Il s'agit de l'évément "click" bien entendu!

submitButton.addEventListener("click", addMyMessage);

Maintenant, on peut coder la fonction addMyMessage. Tout d'abord cette fonction va simplement afficher un texte dans la console. N'importe quel texte... tu choisis!

Pour afficher quelque-chose dans la console, on utilise console.log("beau texte de ton choix").

Ok, tu maîtrises la console! Mais peux-tu faire apparaître dans le console tous les messages que tu écris dans ton chat?? Plus dur!!!

Pour cela, tu devras d'abord récupérer (getElementById) dans notre fichier HTML la balise de la boîte de texte. Ce n'est pas une mauvaise idée de lui donner son propre id, comme ceci, par exemple:

              
               <input type="text" id="message">
              
            

Et dans script.js, tu peux maintenant récupérer l'élément input qui a l'id "message".

                  
                    const message = document.getElementById('message');

                    function addMyMessage() {
                      // Code à écrire
                      console.log("mais qu'il est beau ce chat")
                    }
                  
                

Maintenant, logue dans ta console le message que tu as écrit. Indice, tu vas devoir récupérer sa valeur...

                
                const message = document.getElementById('message');

                function addMyMessage() {
                  // Code à écrire
                  console.log(message.value)

                }
                
              

Wow! On a fait du chemin! Dernière, dernière sous-étape: faire apparaître le message dans le chat. Pour cela, le console.log() ne suffit plus! Il faut injecter de l'HTML.

Regarde la fonction .insertAdjacentHTML()

La documentation indique que cette fonction s'utilise ainsi: element.insertAdjacentHTML(position, text);. À toi de trouver par quoi remplacer:

  1. element (il s'agit d'une balise dans ton HTML)
  2. position ('beforebegin', 'afterbegin', 'beforeend' ou 'afterend')
  3. text (le petit morceau d'html que tu vas insérer dans ton fichier html)

Pour l'élément, il faut que tu trouves la balise HTML qui englobe tous tes messages. Je te parie que c'est une div et qu'elle a un id.

Je te donne un exemple. Si j'ai ce code html:

                  
                    <div id="messages">
                      <div class="friend-message">
                        Salut, ça va? Regarde le beau chat que j'ai codé!
                      </div>
                      <div class="friend-message">
                        J'espère que tu vas aimer!
                      </div>
                      <div class="me-message">
                        Wow, c'est super!
                      </div>
                      <div class="me-message">
                        Bravo, dis!
                      </div>
                    </div>
                  
                

la balise qui englobe toutes les balises de message, c'est la balise div qui a l'id "messages". Dans mon javascript, j'écrirais donc let messagesTag = document.getElementById("messages"); et du coup, je pourrais utiliser ma variable messagesTag comme element:

                  
                    let messagesTag = document.getElementById("messages");
                    messagesTag.insertAdjacentHTML(position, text);
                  
                

Pour la partie text, tu dois utiliser une string, c'est à dire une suite de caractères. En Javascript, pour avoir une string, il suffit d'utiliser les guillemets: "". Voici un exemple: "salut"

Par contre, si tu utilises "salut" comme text, à chaque fois que tu vas appuyer sur le bouton "Envoyer", le message "salut" va s'afficher, même si tu as mis quelque chose d'autre que "salut". Ce que tu veux, c'est récupérer ce que tu as écrit dans le formulaire.

Pour cela, tu pourrais utiliser le code utilisé tantôt... message.value

Lorsque tu écris un message dans le chat, il apparaît sur ta page web. Maintenant, on aimerait que le serveur puisse aussi recevoir le message et le faire apparaître dans sa console grâce à la librairie socket.io. Pour cela, il faut que le client HTML et le serveur soit connectés.

Partie client

Dans ton projet client, on va d'abord spécifier où trouver la librairie socket.io dans notre fichier index.html. À la toute fin de l'élément <body>, ajoute cet élément <script>:

            
              <body>
                <!-- ton chouette code -->
                <script src="https://cdn.socket.io/4.4.0/socket.io.min.js" integrity="sha384-1fOn6VtTq3PWwfsOrk45LnYcGosJwzMHv+Xh/Jx5303FVOXzEnw0EpLv30mtjmlj" crossorigin="anonymous">
                <script src="script.js">
              </body>
            
          

Ensuite, dans le fichier script.js, ajoute la connection à la librairie io ainsi:

            
            let socket = io("url_de_ton_serveur");
            
          

Dernière chose pour le client: on va lui demander d'afficher son numéro de connection lorsqu'il se connecte au serveur. Ça sera utile par la suite pour l'identifier, surtout lorsqu'il y aura plusieurs clients qui parleront au serveur!

            
            socket.on('connect', function() {
              console.log(socket.id)
            })
            
          

Pour l'instant, ce code n'affiche rien dans la console, car la partie serveur n'est pas encore codée. Allons-y!

Partie serveur

Reprends ton premier projet Repl.it de serveur. Le code qui établit ton serveur doit plus ou moins avoir l'air de ceci:

            
              const express = require('express');
              const http = require('http');
              const socket = require('socket.io');

              const app = express();
              const server = http.Server(app);
              const io = socket(server);

              server.listen(3000, function() {
                console.log("Je suis le serveur et j'écoute vos demandes!");
              });

              io.on('connection', function(connection){
                console.log("il y a un nouveau client");
                connection.on('message', function(data) {
                  io.emit("broadcast", data);
                });
              });
            
          

La première chose à faire, c'est ajouter au tout tout début de ton code la ligne suivante:

            
              const cors = require('cors');
            
          

Ensuite, tu dois modifier ta variable io. Remplace la ligne const io = socket(server); par ce code:

            
              const io = socket(server, {
                cors: {
                  origin: "*",
                  methods: ["GET", "POST"]
                }
              });
            
          

C'est quoi ces trucs de cors? En gros, c'est un mécanisme de sécurité pour les serveurs. Sur des sites importants, certains ordinateurs clients pourraient envoyer des requêtes malicieuses et le but c'est de vérifier l'origine des requêtes. Comme notre chat n'est pas (encore!) connu dans le monde entier, on peut baisser nos gardes et accepter les requêtes de partout :)

Notre serveur est maintenant prêt à écouter les clients HTML! Tu peux lancer ton serveur en appuyant sur le bouton RUN. Retourne sur l'onglet de ton client HTML et relance le projet. Dans la console du client, tu devrais voir apparaître l'id de ton client. C'est une longue suite de caractères avec des lettres et des chiffres:

Du côté de ton serveur, tu devrais aussi voir un message dans ta console:

Yihaaaaa 💪, le serveur et le client sont connectés. Dernière petite manip: affichons l'identifiant du client (id) dans la console du serveur.

Pour afficher l'id de notre client dans la console du serveur, on peut utiliser la variable connection et faire ressortir l'idcomme ceci: connection.id

Dans le code de ton serveur, tu peux écrire quelque chose comme ceci:

                
                  io.on('connection', function(connection) {
                    console.log("il y a un nouveau client: " + connection.id);
                    })
                  })
                
              

Maintenant que notre serveur détecte les connections des clients, voyons s'il peut aussi recevoir leurs messages!

Partie client - On envoie le message au serveur!

Pour l'instant, quand tu écris un message dans ton formulaire et que cliques sur le bouton Envoyer, le message apparaît dans ton chat, mais le serveur n'est pas mis au courant. On va changer cela!

Dans ton fichier script.js, quelle est la fonction qui fait apparaître le message que tu viens de taper dans le chat?

C'est la fonction addMyMessage()

Dans cette fonction, après le code pour insérer l'HTML insertAdjacentHTML(), on va ajouter une ligne pour envoyer le message au serveur:

            
            socket.emit(EVENT, DATA);
            
          

Bien sûr, tu vas devoir remplacer les mots EVENT et DATA par du code qui fait sens!

La partie EVENT, c'est un peu comme le nom de code de notre événement. Ici, comme on envoie un message au serveur, tu peux l'appeler tout bêtement "message".

La partie DATA, c'est le message qu'on veut envoyer au serveur. Quel est le code qui récupère ce qu'on a écrit dans le formulaire?

message.value

Le tout mis ensemble donne ceci:

                
                socket.emit("message", message.value);
                
              

Partie serveur - On reçoit le message!

Du côté du serveur, on va recevoir le message et l'afficher dans la console. Si tu as bien suivi l'étape 5 de la fiche d'intro, tu devrais déjà avoir un code pour récupérer les messages des clients:

            
            connection.on('message', function(data) {
              // ...
            });
            
          

Si tu mets ton client et ton serveur côte à côte, tu vas pouvoir voir le serveur recevoir tes messages en temps réel 💪💪💪:

Notre serveur est capable de recevoir le message d'un client et de l'afficher dans sa console. Sympa, mais pas super utile! Notre serveur doit maintenant relayer l'information à tous les autres clients.

Partie Serveur - Rediffuser le message

Partie Client - Afficher les messages des autres clients