Skip to content

📅 SAISON A Semaine 5 Épisode 3 - Une JournĂ©e en Pair-Programming

📚 Notions du jour

Aujourd’hui, j’ai participĂ© Ă  un atelier en pair-programming avec pour objectif de crĂ©er une application web d’ardoise pixel art, inspirĂ©e du style rĂ©tro de Space Invaders. Le dĂ©fi ? Tout gĂ©nĂ©rer en JavaScript : la grille de pixels, le formulaire de configuration, et mĂȘme la palette de couleurs. Nous avions seulement une maquette comme point de dĂ©part. Pas de code fourni, juste une idĂ©e Ă  concrĂ©tiser !


đŸ–Šïž Mise Ă  jour le 16 octobre 2025

Cet article a Ă©tĂ© mis Ă  jour pour inclure une amĂ©lioration du code permettant de corriger les problĂšmes rencontrĂ©s Ă©noncĂ©s dans la section 🎹 AmĂ©liorations et DĂ©fis.
Ajout de la section suivante : đŸ’Ș Suite et fin !

📐 Étape PrĂ©paratoire : DĂ©couper la Maquette

Le matin, nous avons commencé par analyser la maquette pour identifier les éléments clés :

  1. Un <header> contenant un formulaire avec :
  2. Un input pour définir la taille de la grille (en nombre de pixels).
  3. Un input pour définir la taille des pixels (en pixels).
  4. Un bouton pour valider et générer la grille.
  5. Un <main> contenant :
  6. La grille de pixels (notre ardoise).
  7. Une palette de couleurs en bas, pour choisir la couleur des pixels.

Action : Nous avons créé une structure HTML basique et ajoutĂ© un peu de CSS pour styliser les Ă©lĂ©ments (couleurs, tailles, etc.). L’idĂ©e Ă©tait de prĂ©parer le terrain pour que JavaScript puisse prendre le relais. Nous sommes partis d'une grille de dĂ©part composĂ©e de 8 x 8 pixels (chaque pixel faisant une taille de 50px) codĂ©e en dur dans le HTML pour prĂ©visualiser le rendu attendu.

invader.html - Body content
<!DOCTYPE html>
<html lang="en">
<body>
  <header>
    <form action="">
      <input type="number" min="" max="" step="1" placeholder="Taille de la grille">
      <input type="number" min="" max="" step="1" placeholder="Taille des pixels">
      <button type="submit">Valider</button>
    </form>
  </header>

  <main>
    <div id="grid">
      <!-- Simulate a 8x8 grid -->
      <div class="pixel"></div>
      <!-- <div class="pixel"></div> 
           <div class="pixel"></div>
           <div class="pixel"></div>
           ...
           <div class="pixel"></div>-->
      <div class="pixel"></div>
    </div>
    <div class="palette"></div>
  </main>
  <script src="../js/app.js"></script>
</body>
</html>
style.css - base CSS
:root {
    --pixel-color-grey-light: #D2DAE2;
    --pixel-border-grey-light: #808E9B;
    --pixel-color-grey-dark: #485460;
    --pixel-border-grey-dark: #1D262D;
    --bg-color-main: #665ACE;
    --bg-color-header: #3148AD;
}

header {
    background-color: var(--bg-color-header);
    height: 20dvh;
    display: flex;
    justify-content: center;
    align-items: center;
}

main {
    background-color: var(--bg-color-main);
    height: 80dvh;
    display: flex;
    justify-content: center;
    align-items: center;
}

#grid {
    display: grid;
    grid-template-rows: auto;
    width: auto;
    height: auto;
}

.pixel {
    background-color: var(--pixel-color-grey-light);
    border: 2px solid var(--pixel-border-grey-light);
    height: 50px;
    width: 50px;
}

đŸ’» CrĂ©ation de l’Application avec JavaScript

1ïžâƒŁ GĂ©nĂ©rer la Grille de Pixels

Objectif : GĂ©nĂ©rer une grille dynamique en fonction de la taille choisie par l’utilisateur.

PremiÚre approche : Avant de nous attaquer à la gestion du formulaire, nous avons commencé avec un prompt() pour demander la taille de la grille, en fixant la taille des pixels à 50px pour les tests.

app.js - Grid generation
// Get #grid Element
const grid = document.getElementById("grid");
// Initial test with a prompt
const userInput = Number(prompt("Taille de la grille ?"));

// Use the grid-template-columns CSS property to create the grid
grid.style.gridTemplateColumns = `repeat(${userInput}, 1fr)`;
// Generate the grid
for (let round = 0; round < userInput * userInput; round++) {
  const pixel = document.createElement("div"); // Create a pixel element
  pixel.classList.add("pixel"); // Add .pixel class to the pixel element
  grid.appendChild(pixel); // Append pixel element into #grid element
}
RĂ©sultat : Une grille de pixels gris clair, prĂȘte Ă  ĂȘtre colorĂ©e !

Résultat d'affichage de la grille dans le navigateur


2ïžâƒŁ Rendre les Pixels Cliquables

Objectif : Changer la couleur d’un pixel au clic (noir par dĂ©faut).

Solution : Nous avons pensé à créer une classe dark afin de l'ajouter à un pixel lorsque celui-ci est cliqué. Si un pixel possÚde la classe dark, alors il prend la couleur noir. En cherchant dans la documentation, nous avons trouver que nous pouvions utiliser un addEventListener avec la méthode toggle() de l'objet classListd'un HTML DOM element pour basculer entre les classes CSS.

app.js - Toggling pixel color
// ...

// Generate the grid with toggle event on pixels
for (let round = 0; round < userInput * userInput; round++) {
  const pixel = document.createElement("div"); // Create a pixel element
  pixel.classList.add("pixel"); // Add .pixel class to the pixel element
  // Add "click" event Listener with classList.toggle() method on pixels
  pixel.addEventListener("click", () => {
    pixel.classList.toggle("dark");
  });
  grid.appendChild(pixel); // Append pixel element into #grid element
}

CSS associé :

style.css - Add .dark class
.dark {
    background-color: var(--pixel-color-grey-dark); /* Corresponding to #485460 */
    border: 2px solid var(--pixel-border-grey-dark); /* Corresponding to #1D262D */
}
RĂ©sultat : Une grille interactive oĂč chaque clic inverse la couleur du pixel !

Gif représentant un rendu visuel de la fonctionnalité ajoutée de pouvoir changer la couleur des pixels en gris ou noir


3ïžâƒŁ IntĂ©grer le Formulaire

Objectif : Remplacer le prompt() par un formulaire HTML pour configurer la grille.

Étapes :

  1. Récupérer les valeurs des inputs (taille de la grille et taille des pixels).
  2. Générer la grille en fonction de ces valeurs.
app.js - Generate new grid with the form
// Get #grid Element
const grid = document.getElementById("grid");

// Get the form elements
const form = document.querySelector("form");  // Get the form
const gridSizeInput = document.querySelector(".grid-size"); // Get input for grid size
const pixelSizeInput = document.querySelector(".pixel-size"); // Get input for pixel size

// Add event listener to the form to get inputs values to generate a new grid once submited
form.addEventListener("submit", (event) => {
  // Prevent default form behaviour
  event.preventDefault();
  // Reset the grid
  const pixelsToRemove = document.querySelectorAll('.pixel'); // Get all pixels from the grid
  // Remove pixels
  for (const pixel of pixelsToRemove) {
    pixel.remove();
  }

  // Update the grid generation with form inputs values
  const gridSizeInputValue = gridSizeInput.value; // Get grid size input value
  const pixelSizeInputValue = pixelSizeInput.value; // Get pixel size input value

  grid.style.gridTemplateColumns = `repeat(${gridSizeInputValue}, 1fr)`;

  for (let round = 0; round < Math.pow(gridSizeInputValue, 2); round++) {
    const pixel = document.createElement("div"); // Create a pixel element
    pixel.classList.add("pixel"); // Add .pixel class to the pixel element
    // Add "click" event Listener with classList.toggle() method on pixels
    pixel.addEventListener("click", () => {
      pixel.classList.toggle("dark");
    });
    grid.appendChild(pixel); // Append pixel element into #grid element
  }
  form.reset(); // Reset form inputs
});
Résultat : Un formulaire fonctionnel qui génÚre une grille personnalisée !

Gif représentant un rendu visuel de l'utilisation du formulaire pour générer une nouvelle grille


4ïžâƒŁ Partie Bonus : CrĂ©er la Palette de Couleurs

Objectif : Ajouter une palette de couleurs pour modifier la couleur des pixels.

Étapes :

  1. Créer la palette (une <div> par couleur).
  2. Permettre Ă  l’utilisateur de sĂ©lectionner une couleur.
  3. Appliquer la couleur sélectionnée aux pixels cliqués.

Ajout de la palette dans le fichier html :

invader.html - Palette
<!-- Add a <div> containing the different colors into the <main> section -->
<div class="palette">
  <!-- Add a <div> by color -->
  <div class="grey"></div> 
  <div class="dark"></div>
  <div class="orange"></div>
  <div class="green"></div>
</div>

CSS pour la palette :

style.css
.grey {
    background-color: var(--pixel-color-grey-light);
    border: 2px solid var(--pixel-border-grey-light);
}

.dark {
    background-color: var(--pixel-color-grey-dark);
    border: 2px solid var(--pixel-border-grey-dark);
}

.green {
    background-color: var(--pixel-color-green);
    border: 2px solid var(--pixel-border-green);
}

.orange {
    background-color: var(--pixel-color-orange);
    border: 2px solid var(--pixel-border-orange);
}

.palette {
    background-color: #4A45A3;
    padding: 2rem;
    display: flex;
    gap: 1rem;
    align-items: center;
    justify-content: space-between;
    position: absolute;
    right: 0;
    bottom: 0;
}

.palette > * {
    width: 40px;
    height: 40px;
    border-radius: 50%;
    border-width: 4px;

}

/* If a color is clicked, this class will be added to change the color size
and to specify that the color is selected */
.color-selected {
    width: 80px;
    height: 80px; 
}
Rendu avec la palette

Rendu visuel avec la palette ajoutée


Il faut maintenant pouvoir sélectionner les couleurs sur la Palette et les lier aux Pixels.

Solution partielle trouvĂ©e : En cherchant dans la documentation, nous avons utilisĂ© classList.item() pour rĂ©cupĂ©rer la classe de la couleur sĂ©lectionnĂ©e et l’appliquer aux pixels.

app.js - Palette handling
// ...

/**
 * Update "click" event in the grid generation part
 * By Handling "click" event to change pixel color
 */
pixel.addEventListener("click", () => {
  // Get the selected color from palette
  const selectedColor = document.querySelector(".color-selected").classList.item(0);
  // Get current color of the pixel
  const currentPixelColor = pixel.classList.item(1);
  // Replace current color with selected color
  pixel.classList.replace(currentPixelColor, selectedColor);
});

// ...

// Get all color elements from the palette
const paletteColors = document.querySelectorAll(".palette > *");

// Handles click event to select a color from the palette
for (const color of paletteColors) {
  color.addEventListener("click", () => {
    // Toggle 'color-selected' on the clicked color
    color.classList.toggle("color-selected");
  });
}
Résultat final obtenu : Les pixels prennent la couleur sélectionnée dans la palette !

démo du rendu final du challenge du jour


🎹 AmĂ©liorations et DĂ©fis

ProblĂšme rencontrĂ© : La solution proposĂ©e reste Ă  optimiser. En effet, lorsque l'on clique sur une couleur pour la sĂ©lectionner il faudrait que celle-ci devienne sĂ©lectionnĂ©e et que toutes les autres couleurs ne soient plus sĂ©lectionnĂ©es. Le comportement actuel est que lorsqu'on clique sur une couleur, les autres couleurs restent sĂ©lectionnĂ©es si elles ont dĂ©jĂ  Ă©tĂ© sĂ©lectionnĂ©es avant. Ce qui fait que l'on peut sĂ©lectionner toutes les couleurs en mĂȘme temps.
Il faut cliquer à nouveau sur une couleur déjà sélectionnée pour la dé-sélectionner grùce à toggle(). En l'état pour pouvoir changer la couleur des pixels il faut sélectionner une seule couleur et dé-sélectionner manuellement les autres couleurs afin de n'avoir qu'une seule couleur sélectionnée dans la palette. Ensuite on peut cliquer sur les pixels afin de changer leur couleur.


💡 Ce Que J’ai Appris Aujourd’hui

  • Le pair programming est puissant : Travailler Ă  deux permet de rĂ©soudre des problĂšmes plus rapidement et d’apprendre des approches diffĂ©rentes.
  • La documentation est une alliĂ©e : Sans elle, nous n’aurions pas trouvĂ© classList.toggle() ou classList.item().
  • Les petites victoires comptent : Chaque Ă©tape franchie (mĂȘme minuscule) est une avancĂ©e !
  • L’importance des tests : Tester chaque fonctionnalitĂ© au fur et Ă  mesure Ă©vite les bugs cumulatifs.

đŸ’Ș Suite et fin !

Ce paragraphe a été ajouté lors de la mise à jour du 16 octobre 2025.

AprĂšs une bonne nuit de sommeil đŸ›ŒđŸ’€ Ă  rĂȘver de grilles, de pixels et de lignes de code. Je me rĂ©veille 😮 en pensant avoir trouvĂ© comment ne sĂ©lectionner qu'une seule couleur sur la palette sans les sĂ©lectionner toutes en mĂȘme temps. Pour cela je me suis dit que lorsque je sĂ©lectionne une couleur sur la palette, il faut que dĂ©-sĂ©lectionne toutes les couleurs de la palette qui sont sĂ©lectionnĂ©es d'abord (c'est-Ă -dire qu'elles possĂšdent la classe color-selected).

Voici ma solution :

app.js - Select only one color from the palette
/**
 * Handles click event to select a color from the palette
 */
for (const color of paletteColors) {
  color.addEventListener("click", () => {
    // If the color is not already selected
    if (!color.classList.contains("color-selected")) {
      // Remove 'color-selected' from all colors
      for (const color of paletteColors) {
        if (color.classList.contains("color-selected")) {
          color.classList.toggle("color-selected");
        }
      }
    }
    // Toggle 'color-selected' on the clicked color
    color.classList.toggle("color-selected");
  });
}
Résultat final obtenu : Les pixels prennent la couleur sélectionnée dans la palette !

démo du rendu final du challenge avec amélioration