You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
Web-Dev-For-Beginners/translations/fr/3-terrarium/3-intro-to-DOM-and-closures/README.md

762 lines
40 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

# Projet Terrarium Partie 3 : Manipulation du DOM et Closures en JavaScript
```mermaid
journey
title Votre parcours JavaScript DOM
section Fondations
Comprendre le DOM: 3: Student
Apprendre les closures: 4: Student
Connecter les éléments: 4: Student
section Interaction
Configurer les événements de glisser: 4: Student
Suivre les coordonnées: 5: Student
Gérer le mouvement: 5: Student
section Finitions
Ajouter le nettoyage: 4: Student
Tester la fonctionnalité: 5: Student
Compléter le terrarium: 5: Student
```
![DOM et une closure](../../../../translated_images/fr/webdev101-js.10280393044d7eaa.webp)
> Sketchnote par [Tomomi Imura](https://twitter.com/girlie_mac)
Bienvenue dans l'un des aspects les plus passionnants du développement web - rendre les choses interactives ! Le Document Object Model (DOM) est comme un pont entre votre HTML et JavaScript, et aujourd'hui nous l'utiliserons pour donner vie à votre terrarium. Lorsque Tim Berners-Lee a créé le premier navigateur web, il imaginait un web où les documents pourraient être dynamiques et interactifs - le DOM rend cette vision possible.
Nous allons également explorer les closures JavaScript, qui peuvent sembler intimidantes au début. Pensez aux closures comme à la création de « poches de mémoire » où vos fonctions peuvent se souvenir d'informations importantes. C'est comme si chaque plante dans votre terrarium avait sa propre fiche de données pour suivre sa position. À la fin de cette leçon, vous comprendrez à quel point elles sont naturelles et utiles.
Voici ce que nous construisons : un terrarium où les utilisateurs peuvent glisser-déposer les plantes où ils veulent. Vous apprendrez les techniques de manipulation du DOM qui alimentent tout, des uploads de fichiers par glisser-déposer aux jeux interactifs. Donnons vie à votre terrarium.
```mermaid
mindmap
root((DOM & JavaScript))
DOM Tree
Sélection d'Élément
Accès aux Propriétés
Gestion des Événements
Mises à Jour Dynamiques
Events
Événements de Pointeur
Événements de Souris
Événements Tactiles
Écouteurs d'Événements
Closures
Variables Privées
Portée des Fonctions
Persistance de la Mémoire
Gestion d'État
Drag & Drop
Suivi de Position
Mathématiques des Coordonnées
Cycle de Vie des Événements
Interaction Utilisateur
Modern Patterns
Délégation d'Événements
Performance
Multi-Appareils
Accessibilité
```
## Quiz avant la leçon
[Quiz avant la leçon](https://ff-quizzes.netlify.app/web/quiz/19)
## Comprendre le DOM : Votre passerelle vers des pages web interactives
Le Document Object Model (DOM) est la manière dont JavaScript communique avec vos éléments HTML. Lorsque votre navigateur charge une page HTML, il crée une représentation structurée de cette page en mémoire - c'est le DOM. Pensez-y comme un arbre généalogique où chaque élément HTML est un membre de la famille auquel JavaScript peut accéder, modifier ou réarranger.
La manipulation du DOM transforme les pages statiques en sites web interactifs. Chaque fois que vous voyez un bouton changer de couleur au survol, un contenu qui se met à jour sans rafraîchir la page, ou des éléments que vous pouvez glisser, c'est la manipulation du DOM qui s'en charge.
```mermaid
flowchart TD
A["Document"] --> B["HTML"]
B --> C["En-tête"]
B --> D["Corps"]
C --> E["Titre"]
C --> F["Balises Méta"]
D --> G["H1 : Mon Terrarium"]
D --> H["Div : Conteneur de la Page"]
H --> I["Div : Conteneur Gauche"]
H --> J["Div : Conteneur Droit"]
H --> K["Div : Terrarium"]
I --> L["Éléments de Plantes 1-7"]
J --> M["Éléments de Plantes 8-14"]
L --> N["img#plant1"]
L --> O["img#plant2"]
M --> P["img#plant8"]
M --> Q["img#plant9"]
style A fill:#e1f5fe
style B fill:#f3e5f5
style D fill:#e8f5e8
style H fill:#fff3e0
style N fill:#ffebee
style O fill:#ffebee
style P fill:#ffebee
style Q fill:#ffebee
```
![Représentation de l'arbre DOM](../../../../translated_images/fr/dom-tree.7daf0e763cbbba92.webp)
> Une représentation du DOM et du balisage HTML qui le référence. Par [Olfa Nasraoui](https://www.researchgate.net/publication/221417012_Profile-Based_Focused_Crawler_for_Social_Media-Sharing_Websites)
**Voici ce qui rend le DOM puissant :**
- **Fournit** un moyen structuré d'accéder à n'importe quel élément sur votre page
- **Permet** des mises à jour dynamiques de contenu sans rechargement de page
- **Autorise** une réponse en temps réel aux interactions de l'utilisateur comme les clics et les glissements
- **Crée** la base pour les applications web interactives modernes
## Closures en JavaScript : créer un code organisé et puissant
Une [closure JavaScript](https://developer.mozilla.org/docs/Web/JavaScript/Closures) est comme donner à une fonction son propre espace de travail privé avec une mémoire persistante. Considérez comment les pinsons de Darwin aux îles Galápagos ont chacun développé des becs spécialisés basés sur leur environnement spécifique - les closures fonctionnent de manière similaire, créant des fonctions spécialisées qui « se souviennent » de leur contexte spécifique même après que leur fonction parente ait terminé.
Dans notre terrarium, les closures aident chaque plante à se souvenir de sa propre position de manière indépendante. Ce modèle apparaît tout au long du développement professionnel JavaScript, ce qui en fait un concept précieux à comprendre.
```mermaid
flowchart LR
A["dragElement(plant1)"] --> B["Crée une fermeture"]
A2["dragElement(plant2)"] --> B2["Crée une fermeture"]
B --> C["Variables privées"]
B2 --> C2["Variables privées"]
C --> D["pos1, pos2, pos3, pos4"]
C --> E["fonction pointerDrag"]
C --> F["fonction elementDrag"]
C --> G["fonction stopElementDrag"]
C2 --> D2["pos1, pos2, pos3, pos4"]
C2 --> E2["fonction pointerDrag"]
C2 --> F2["fonction elementDrag"]
C2 --> G2["fonction stopElementDrag"]
H["Plante 1 se souvient de sa position"] --> B
H2["Plante 2 se souvient de sa position"] --> B2
style B fill:#e8f5e8
style B2 fill:#e8f5e8
style C fill:#fff3e0
style C2 fill:#fff3e0
```
> 💡 **Comprendre les Closures** : Les closures sont un sujet important en JavaScript, et beaucoup de développeurs les utilisent pendant des années avant de maîtriser tous les aspects théoriques. Aujourd'hui, nous nous concentrons sur l'application pratique - vous verrez les closures émerger naturellement au fur et à mesure que nous construisons nos fonctionnalités interactives. La compréhension se développera en voyant comment elles résolvent des problèmes réels.
![Représentation de l'arbre DOM](../../../../translated_images/fr/dom-tree.7daf0e763cbbba92.webp)
> Une représentation du DOM et du balisage HTML qui le référence. Par [Olfa Nasraoui](https://www.researchgate.net/publication/221417012_Profile-Based_Focused_Crawler_for_Social_Media-Sharing_Websites)
Dans cette leçon, nous allons compléter notre projet de terrarium interactif en créant le JavaScript qui permettra à un utilisateur de manipuler les plantes sur la page.
## Avant de commencer : se préparer au succès
Vous aurez besoin de vos fichiers HTML et CSS des leçons précédentes sur le terrarium - nous allons rendre ce design statique interactif. Si vous nous rejoignez pour la première fois, compléter ces leçons d'abord vous donnera un contexte important.
Voici ce que nous allons construire :
- **Glisser-déposer fluide** pour toutes les plantes du terrarium
- **Suivi des coordonnées** pour que les plantes se souviennent de leur position
- **Une interface interactive complète** avec JavaScript vanilla
- **Un code propre et organisé** utilisant des patterns de closure
## Préparer votre fichier JavaScript
Créons le fichier JavaScript qui rendra votre terrarium interactif.
**Étape 1 : Créez votre fichier script**
Dans votre dossier terrarium, créez un nouveau fichier nommé `script.js`.
**Étape 2 : Liez le JavaScript à votre HTML**
Ajoutez cette balise script dans la section `<head>` de votre fichier `index.html` :
```html
<script src="./script.js" defer></script>
```
**Pourquoi l'attribut `defer` est important :**
- **Assure** que votre JavaScript attend que tout le HTML soit chargé
- **Évite** les erreurs quand JavaScript cherche des éléments pas encore prêts
- **Garantit** que tous vos éléments de plante sont disponibles pour l'interaction
- **Offre** de meilleures performances que de placer les scripts en bas de page
> ⚠️ **Note importante** : L'attribut `defer` empêche des problèmes de timing courants. Sans lui, JavaScript pourrait essayer d'accéder aux éléments HTML avant leur chargement, entraînant des erreurs.
---
## Connecter JavaScript à vos éléments HTML
Avant de rendre les éléments déplaçables, JavaScript doit les localiser dans le DOM. Pensez à cela comme un système de catalogage de bibliothèque - une fois que vous avez le numéro de catalogue, vous pouvez trouver exactement le livre qu'il vous faut et accéder à tout son contenu.
Nous allons utiliser la méthode `document.getElementById()` pour faire ces connexions. C'est comme un système de classement précis - vous fournissez un ID, et il trouve exactement l'élément dont vous avez besoin dans votre HTML.
### Activer la fonctionnalité glisser pour toutes les plantes
Ajoutez ce code à votre fichier `script.js` :
```javascript
// Activer la fonctionnalité de glisser pour les 14 plantes
dragElement(document.getElementById('plant1'));
dragElement(document.getElementById('plant2'));
dragElement(document.getElementById('plant3'));
dragElement(document.getElementById('plant4'));
dragElement(document.getElementById('plant5'));
dragElement(document.getElementById('plant6'));
dragElement(document.getElementById('plant7'));
dragElement(document.getElementById('plant8'));
dragElement(document.getElementById('plant9'));
dragElement(document.getElementById('plant10'));
dragElement(document.getElementById('plant11'));
dragElement(document.getElementById('plant12'));
dragElement(document.getElementById('plant13'));
dragElement(document.getElementById('plant14'));
```
**Ce que ce code réalise :**
- **Localise** chaque élément plante dans le DOM grâce à son ID unique
- **Récupère** une référence JavaScript à chaque élément HTML
- **Passe** chaque élément à une fonction `dragElement` (que nous allons créer ensuite)
- **Prépare** chaque plante à l'interaction glisser-déposer
- **Relie** votre structure HTML à la fonctionnalité JavaScript
> 🎯 **Pourquoi utiliser des IDs plutôt que des classes ?** Les IDs offrent des identifiants uniques pour des éléments spécifiques, tandis que les classes CSS sont destinées au style de groupes d'éléments. Lorsque JavaScript doit manipuler des éléments individuels, les IDs offrent la précision et la performance nécessaires.
> 💡 **Astuce pro** : Remarquez que nous appelons `dragElement()` pour chaque plante individuellement. Cette approche garantit que chaque plante obtient son propre comportement de glissement indépendant, ce qui est essentiel pour une interaction utilisateur fluide.
### 🔄 **Contrôle pédagogique**
**Compréhension de la connexion au DOM** : Avant de passer à la fonctionnalité de glisser, vérifiez que vous pouvez :
- ✅ Expliquer comment `document.getElementById()` localise les éléments HTML
- ✅ Comprendre pourquoi nous utilisons des IDs uniques pour chaque plante
- ✅ Décrire le rôle de l'attribut `defer` dans les balises script
- ✅ Reconnaître comment JavaScript et HTML se connectent via le DOM
**Auto-test rapide** : Que se passerait-il si deux éléments avaient le même ID ? Pourquoi `getElementById()` ne retourne qu'un seul élément ?
*Réponse : Les IDs doivent être uniques ; en cas de duplication, seul le premier élément est retourné*
---
## Construire la closure dragElement
Nous allons maintenant créer le cœur de notre fonctionnalité de glissement : une closure qui gère le comportement de déplacement pour chaque plante. Cette closure contiendra plusieurs fonctions internes qui travaillent ensemble pour suivre les mouvements de la souris et mettre à jour les positions des éléments.
Les closures sont parfaites pour cette tâche car elles nous permettent de créer des variables « privées » qui persistent entre les appels de fonction, donnant à chaque plante son propre système indépendant de suivi des coordonnées.
### Comprendre les closures avec un exemple simple
Laissez-moi vous démontrer les closures avec un exemple simple qui illustre le concept :
```javascript
function createCounter() {
let count = 0; // C'est comme une variable privée
function increment() {
count++; // La fonction interne se souvient de la variable externe
return count;
}
return increment; // Nous renvoyons la fonction interne
}
const myCounter = createCounter();
console.log(myCounter()); // 1
console.log(myCounter()); // 2
```
**Ce qui se passe dans ce pattern de closure :**
- **Crée** une variable privée `count` qui existe uniquement dans cette closure
- **La fonction interne** peut accéder et modifier cette variable externe (le mécanisme de closure)
- **Lorsque nous retournons** la fonction interne, elle maintient sa connexion à ces données privées
- **Même après** que `createCounter()` ait fini son exécution, `count` persiste et se souvient de sa valeur
### Pourquoi les closures sont parfaites pour la fonctionnalité de glissement
Pour notre terrarium, chaque plante doit se souvenir de ses coordonnées actuelles. Les closures offrent la solution parfaite :
**Avantages clés pour notre projet :**
- **Maintien** des variables de position privées pour chaque plante indépendamment
- **Préservation** des données de coordonnées entre événements de glissement
- **Prévention** des conflits de variables entre différents éléments déplaçables
- **Création** d'une structure de code propre et organisée
> 🎯 **Objectif d'apprentissage** : Vous n'avez pas besoin de maîtriser chaque aspect des closures maintenant. Concentrez-vous sur la façon dont elles nous aident à organiser le code et à maintenir l'état pour notre fonctionnalité de glissement.
```mermaid
stateDiagram-v2
[*] --> Ready: Chargement de la page
Ready --> DragStart: Utilisateur appuie (pointerdown)
DragStart --> Dragging: Souris/doigt bouge (pointermove)
Dragging --> Dragging: Continuer le déplacement
Dragging --> DragEnd: Utilisateur relâche (pointerup)
DragEnd --> Ready: Réinitialiser pour la prochaine glissade
state DragStart {
[*] --> CapturePosition
CapturePosition --> SetupListeners
SetupListeners --> [*]
}
state Dragging {
[*] --> CalculateMovement
CalculateMovement --> UpdatePosition
UpdatePosition --> [*]
}
state DragEnd {
[*] --> RemoveListeners
RemoveListeners --> CleanupState
CleanupState --> [*]
}
```
### Créer la fonction dragElement
Construisons maintenant la fonction principale qui gèrera toute la logique de glissement. Ajoutez cette fonction juste en dessous de vos déclarations d'éléments plante :
```javascript
function dragElement(terrariumElement) {
// Initialiser les variables de suivi de position
let pos1 = 0, // Position X précédente de la souris
pos2 = 0, // Position Y précédente de la souris
pos3 = 0, // Position X actuelle de la souris
pos4 = 0; // Position Y actuelle de la souris
// Configurer le gestionnaire d'événement de glisser initial
terrariumElement.onpointerdown = pointerDrag;
}
```
**Comprendre le système de suivi de position :**
- **`pos1` et `pos2`** : Stockent la différence entre les anciennes et nouvelles positions de la souris
- **`pos3` et `pos4`** : Suivent les coordonnées actuelles de la souris
- **`terrariumElement`** : L'élément plante spécifique que nous rendons déplaçable
- **`onpointerdown`** : L'événement qui déclenche lorsque l'utilisateur commence à glisser
**Voici comment fonctionne le pattern closure :**
- **Crée** des variables de position privées pour chaque élément plante
- **Maintient** ces variables tout au long du cycle de vie du glissement
- **Assure** que chaque plante suit ses propres coordonnées indépendamment
- **Offre** une interface propre via la fonction `dragElement`
### Pourquoi utiliser les événements pointer ?
Vous vous demandez peut-être pourquoi nous utilisons `onpointerdown` au lieu du plus familier `onclick`. Voici la raison :
| Type dévénement | Adapté pour | Le bémol |
|------------------|-------------|------------|
| `onclick` | Clics simples sur boutons | Ne gère pas le glissement (seulement clics et relâchements) |
| `onpointerdown` | Souris et tactile | Récent, mais bien supporté aujourdhui |
| `onmousedown` | Souris de bureau uniquement | Ne fonctionne pas sur mobile |
**Pourquoi les événements pointer sont parfaits pour ce que nous construisons :**
- **Fonctionne bien** que l'utilisateur utilise une souris, un doigt ou un stylet
- **Offre la même sensation** sur ordinateur portable, tablette ou téléphone
- **Gère** le véritable mouvement de glissement (pas seulement clic)
- **Crée** une expérience fluide que les utilisateurs attendent des applis web modernes
> 💡 **Préparation au futur** : Les événements pointer sont la manière moderne de gérer les interactions utilisateur. Au lieu décrire un code séparé pour souris et tactile, vous avez les deux gratuits. Plutôt sympa, non ?
### 🔄 **Contrôle pédagogique**
**Compréhension de la gestion dévénements** : Faites une pause pour confirmer votre compréhension :
- ✅ Pourquoi utilisons-nous les événements pointer au lieu des événements souris ?
- ✅ Comment les variables de closure persistent-elles entre les appels de fonction ?
- ✅ Quel rôle joue `preventDefault()` pour un glissement fluide ?
- ✅ Pourquoi attachons-nous les écouteurs au document plutôt qu'aux éléments individuels ?
**Lien avec le monde réel** : Pensez aux interfaces glisser-déposer que vous utilisez quotidiennement :
- **Transferts de fichiers** : Glisser des fichiers dans une fenêtre de navigateur
- **Tableaux Kanban** : Déplacer des tâches entre colonnes
- **Galeries d'images** : Réarranger lordre des photos
- **Interfaces mobiles** : Glisser et balayer sur écran tactile
---
## La fonction pointerDrag : Capturer le début dun glissement
Quand un utilisateur appuie sur une plante (que ce soit avec un clic souris ou un toucher), la fonction `pointerDrag` entre en action. Cette fonction capture les coordonnées initiales et met en place le système de glissement.
Ajoutez cette fonction dans votre closure `dragElement`, juste après la ligne `terrariumElement.onpointerdown = pointerDrag;` :
```javascript
function pointerDrag(e) {
// Empêcher le comportement par défaut du navigateur (comme la sélection de texte)
e.preventDefault();
// Capturer la position initiale de la souris/tactile
pos3 = e.clientX; // Coordonnée X où le glissement a commencé
pos4 = e.clientY; // Coordonnée Y où le glissement a commencé
// Configurer les écouteurs d'événements pour le processus de glissement
document.onpointermove = elementDrag;
document.onpointerup = stopElementDrag;
}
```
**Étape par étape, voici ce qui se passe :**
- **Empêche** les comportements par défaut du navigateur qui pourraient perturber le glissement
- **Enregistre** les coordonnées précises où lutilisateur a commencé le geste de glissement
- **Établit** des écouteurs dévénements pour le mouvement de glissement en cours
- **Prépare** le système pour suivre le déplacement souris/doigt sur tout le document
### Comprendre la prévention dévénements
La ligne `e.preventDefault()` est cruciale pour un glissement fluide :
**Sans cette prévention, les navigateurs pourraient :**
- **Sélectionner** du texte lors du glissement sur la page
- **Déclencher** des menus contextuels au clic droit et glissement
- **Interférer** avec notre comportement personnalisé de glissement
- **Créer** des artefacts visuels pendant lopération de glissement
> 🔍 **Expérimentez** : Après avoir fini cette leçon, essayez de retirer `e.preventDefault()` et observez limpact sur lexpérience de glissement. Vous comprendrez vite pourquoi cette ligne est essentielle !
### Système de suivi des coordonnées
Les propriétés `e.clientX` et `e.clientY` nous donnent les coordonnées précises de la souris/toucher :
| Propriété | Ce quelle mesure | Cas dusage |
|-----------|-------------------|-------------|
| `clientX` | Position horizontale relative à la fenêtre | Suivi des mouvements gauche-droite |
| `clientY` | Position verticale relative à la fenêtre | Suivi des mouvements haut-bas |
**Comprendre ces coordonnées :**
- **Fournit** des informations de positionnement pixel-perfect
- **Se met à jour** en temps réel au fur et à mesure que lutilisateur déplace son pointeur
- **Reste** cohérent à travers différentes tailles décran et niveaux de zoom
- **Permet** des interactions de glisser-lâcher fluides et réactives
### Mise en place des écouteurs dévénements au niveau du document
Remarquez comment nous attachons les événements de déplacement et darrêt à lensemble du `document`, pas seulement à lélément plante :
```javascript
document.onpointermove = elementDrag;
document.onpointerup = stopElementDrag;
```
**Pourquoi attacher au document :**
- **Continue** à suivre même lorsque la souris quitte lélément plante
- **Empêche** linterruption du glisser si lutilisateur se déplace rapidement
- **Fournit** un glissement fluide sur tout lécran
- **Gère** les cas limites où le curseur sort de la fenêtre du navigateur
> ⚡ **Note de performance** : Nous nettoierons ces écouteurs au niveau du document lorsque le glisser sarrête afin déviter les fuites mémoire et les problèmes de performance.
## Compléter le système de glisser : déplacement et nettoyage
Nous allons maintenant ajouter les deux fonctions restantes qui gèrent le déplacement effectif lors du glisser et le nettoyage lorsque le glisser sarrête. Ces fonctions travaillent ensemble pour créer un mouvement fluide et réactif des plantes à travers votre terrarium.
### La fonction elementDrag : suivi du mouvement
Ajoutez la fonction `elementDrag` juste après laccolade fermante de `pointerDrag` :
```javascript
function elementDrag(e) {
// Calculer la distance parcourue depuis le dernier événement
pos1 = pos3 - e.clientX; // Distance horizontale parcourue
pos2 = pos4 - e.clientY; // Distance verticale parcourue
// Mettre à jour le suivi de la position actuelle
pos3 = e.clientX; // Nouvelle position X actuelle
pos4 = e.clientY; // Nouvelle position Y actuelle
// Appliquer le déplacement à la position de l'élément
terrariumElement.style.top = (terrariumElement.offsetTop - pos2) + 'px';
terrariumElement.style.left = (terrariumElement.offsetLeft - pos1) + 'px';
}
```
**Comprendre les mathématiques des coordonnées :**
- **`pos1` et `pos2`** : calculent la distance parcourue par la souris depuis la dernière mise à jour
- **`pos3` et `pos4`** : stockent la position actuelle de la souris pour le calcul suivant
- **`offsetTop` et `offsetLeft`** : récupèrent la position actuelle de lélément sur la page
- **Logique de soustraction** : déplace lélément de la même quantité que celle parcourue par la souris
```mermaid
sequenceDiagram
participant User
participant Mouse
participant JavaScript
participant Plant
User->>Mouse: Début du glissement à (100, 50)
Mouse->>JavaScript: événement pointerdown
JavaScript->>JavaScript: Stocker la position initiale (pos3=100, pos4=50)
JavaScript->>JavaScript: Configurer les écouteurs move/up
User->>Mouse: Déplacer à (110, 60)
Mouse->>JavaScript: événement pointermove
JavaScript->>JavaScript: Calculer : pos1=10, pos2=10
JavaScript->>Plant: Mettre à jour : left += 10px, top += 10px
Plant->>Plant: Rendu à la nouvelle position
User->>Mouse: Relâcher à (120, 65)
Mouse->>JavaScript: événement pointerup
JavaScript->>JavaScript: Supprimer les écouteurs
JavaScript->>JavaScript: Réinitialiser pour le prochain glissement
```
**Voici la décomposition du calcul du mouvement :**
1. **Mesure** la différence entre les anciennes et nouvelles positions de la souris
2. **Calcule** combien déplacer lélément en fonction du mouvement de la souris
3. **Met à jour** les propriétés CSS de position de lélément en temps réel
4. **Stocke** la nouvelle position comme base pour le prochain calcul de mouvement
### Représentation visuelle des calculs
```mermaid
sequenceDiagram
participant Mouse
participant JavaScript
participant Plant
Mouse->>JavaScript: Déplacer de (100,50) à (110,60)
JavaScript->>JavaScript: Calculer : déplacé de 10px à droite, 10px vers le bas
JavaScript->>Plant: Mettre à jour la position de +10px à droite, +10px vers le bas
Plant->>Plant: Rendu à la nouvelle position
```
### La fonction stopElementDrag : nettoyage
Ajoutez la fonction de nettoyage après laccolade fermante de `elementDrag` :
```javascript
function stopElementDrag() {
// Supprimer les écouteurs d'événements au niveau du document
document.onpointerup = null;
document.onpointermove = null;
}
```
**Pourquoi le nettoyage est essentiel :**
- **Empêche** les fuites mémoire dues aux écouteurs dévénements persistants
- **Arrête** le comportement de glisser dès que lutilisateur relâche la plante
- **Permet** à dautres éléments dêtre glissés indépendamment
- **Réinitialise** le système pour la prochaine opération de glisser
**Ce qui se passe sans nettoyage :**
- Les écouteurs dévénements continuent de fonctionner même après larrêt du glisser
- La performance se dégrade à mesure que les écouteurs non utilisés saccumulent
- Comportements inattendus lors dinteractions avec dautres éléments
- Les ressources du navigateur sont gaspillées à gérer des événements inutiles
### Comprendre les propriétés CSS de position
Notre système de glisser manipule deux propriétés CSS clés :
| Propriété | Ce quelle contrôle | Comment nous lutilisons |
|------------|---------------------|-------------------------|
| `top` | Distance par rapport au bord supérieur | Positionnement vertical lors du glisser |
| `left` | Distance par rapport au bord gauche | Positionnement horizontal lors du glisser |
**Points clés à propos des propriétés offset :**
- **`offsetTop`** : distance actuelle du haut de lélément parent positionné
- **`offsetLeft`** : distance actuelle du bord gauche de lélément parent positionné
- **Contexte de positionnement** : ces valeurs sont relatives à lancêtre positionné le plus proche
- **Mises à jour en temps réel** : changement immédiat lorsque nous modifions les propriétés CSS
> 🎯 **Philosophie de design** : Ce système de glisser est intentionnellement flexible il ny a pas de « zones de dépôt » ou de restrictions. Les utilisateurs peuvent placer les plantes où ils veulent, leur donnant un contrôle créatif total sur la conception de leur terrarium.
## Synthèse : votre système complet de glisser
Félicitations ! Vous venez de construire un système sophistiqué de glisser-déposer en JavaScript vanilla. Votre fonction complète `dragElement` contient désormais une closure puissante qui gère :
**Ce que votre closure accomplit :**
- **Maintient** des variables de position privées pour chaque plante indépendamment
- **Gère** tout le cycle de vie du glisser du début à la fin
- **Fournit** un mouvement fluide et réactif sur tout lécran
- **Nettoie** correctement les ressources pour prévenir les fuites mémoire
- **Crée** une interface intuitive et créative pour la conception de terrariums
### Tester votre terrarium interactif
Testez maintenant votre terrarium interactif ! Ouvrez votre fichier `index.html` dans un navigateur web et essayez la fonctionnalité :
1. **Cliquez et maintenez** sur une plante pour commencer à la glisser
2. **Déplacez votre souris ou doigt** et regardez la plante suivre en douceur
3. **Relâchez** pour déposer la plante à sa nouvelle position
4. **Expérimentez** avec différents agencements pour explorer linterface
🥇 **Succès** : Vous avez créé une application web pleinement interactive en utilisant des concepts fondamentaux que les développeurs professionnels utilisent quotidiennement. Cette fonctionnalité de glisser-déposer utilise les mêmes principes que les téléversements de fichiers, les tableaux Kanban, et bien dautres interfaces interactives.
### 🔄 **Point pédagogique**
**Compréhension complète du système** : Vérifiez votre maîtrise du système complet de glisser :
- ✅ Comment les closures maintiennent-elles un état indépendant pour chaque plante ?
- ✅ Pourquoi le calcul des coordonnées est-il nécessaire pour un mouvement fluide ?
- ✅ Que se passerait-il si on oubliait de nettoyer les écouteurs dévénements ?
- ✅ Comment ce modèle sadapte-t-il à des interactions plus complexes ?
**Réflexion sur la qualité du code** : Passez en revue votre solution complète :
- **Conception modulaire** : chaque plante a sa propre instance de closure
- **Efficacité événementielle** : bonne configuration et nettoyage des écouteurs
- **Compatibilité multi-appareils** : fonctionne sur bureau et mobile
- **Conscience de la performance** : pas de fuites mémoire ni calculs redondants
![terrarium fini](../../../../translated_images/fr/terrarium-final.0920f16e87c13a84.webp)
---
## Défi GitHub Copilot Agent 🚀
Utilisez le mode Agent pour compléter le défi suivant :
**Description :** Améliorez le projet terrarium en ajoutant une fonctionnalité de réinitialisation qui remet toutes les plantes à leurs positions originales avec des animations fluides.
**Consigne :** Créez un bouton de réinitialisation qui, lorsquon clique dessus, anime toutes les plantes pour revenir à leurs positions originales dans la barre latérale en utilisant des transitions CSS. La fonction doit stocker les positions originales au chargement de la page et faire revenir en douceur les plantes à ces positions sur 1 seconde lorsque le bouton reset est pressé.
En savoir plus sur le [mode agent](https://code.visualstudio.com/blogs/2025/02/24/introducing-copilot-agent-mode).
## 🚀 Défi supplémentaire : développez vos compétences
Prêt à faire passer votre terrarium au niveau supérieur ? Essayez dimplémenter ces améliorations :
**Extensions créatives :**
- **Double-cliquez** sur une plante pour la faire passer devant (manipulation du z-index)
- **Ajoutez un retour visuel** comme un léger halo au survol des plantes
- **Implémentez des limites** pour empêcher les plantes dêtre déplacées hors du terrarium
- **Créez une fonction de sauvegarde** qui mémorise les positions des plantes avec localStorage
- **Ajoutez des effets sonores** lors de la prise et du dépôt des plantes
> 💡 **Opportunité dapprentissage** : Chacun de ces défis vous enseignera de nouveaux aspects de la manipulation du DOM, de la gestion des événements et du design de lexpérience utilisateur.
## Quiz post-lecture
[Quiz post-lecture](https://ff-quizzes.netlify.app/web/quiz/20)
## Revue & auto-apprentissage : approfondir votre compréhension
Vous maîtrisez les fondamentaux de la manipulation du DOM et des closures, mais il y a toujours plus à explorer ! Voici quelques pistes pour développer vos connaissances et compétences.
### Approches alternatives du glisser-déposer
Nous avons utilisé les événements pointer pour une flexibilité maximale, mais le développement web offre plusieurs approches :
| Approche | Idéal pour | Valeur pédagogique |
|----------|------------|--------------------|
| [API HTML Drag and Drop](https://developer.mozilla.org/docs/Web/API/HTML_Drag_and_Drop_API) | Téléversements de fichiers, zones de glisser formelles | Comprendre les capacités natives du navigateur |
| [Événements tactiles](https://developer.mozilla.org/docs/Web/API/Touch_events) | Interactions spécifiques au mobile | Modèles de développement mobile-first |
| Propriétés CSS `transform` | Animations fluides | Techniques doptimisation des performances |
### Sujets avancés de manipulation DOM
**Étapes suivantes dans votre parcours :**
- **Délégation dévénements** : gérer efficacement les événements sur plusieurs éléments
- **Intersection Observer** : détecter quand les éléments entrent ou sortent du viewport
- **Mutation Observer** : surveiller les changements dans la structure DOM
- **Web Components** : créer des éléments UI réutilisables et encapsulés
- **Concepts de Virtual DOM** : comprendre comment les frameworks optimisent les mises à jour DOM
### Ressources essentielles pour continuer à apprendre
**Documentation technique :**
- [Guide MDN sur les événements pointer](https://developer.mozilla.org/docs/Web/API/Pointer_events) - référence complète
- [Spécification W3C Pointer Events](https://www.w3.org/TR/pointerevents1/) - documentation officielle
- [Approfondissement des closures JavaScript](https://developer.mozilla.org/docs/Web/JavaScript/Closures) - patterns avancés de closures
**Compatibilité des navigateurs :**
- [CanIUse.com](https://caniuse.com/) - vérification du support des fonctionnalités selon navigateur
- [Données de compatibilité MDN](https://github.com/mdn/browser-compat-data) - informations détaillées
**Opportunités de pratique :**
- **Construisez** un jeu de puzzle utilisant des mécaniques similaires de glisser
- **Créez** un tableau Kanban avec gestionnaire de tâches par glisser-déposer
- **Concevez** une galerie dimages avec arrangement des photos par glisser
- **Expérimentez** avec les gestes tactiles pour les interfaces mobiles
> 🎯 **Stratégie dapprentissage** : La meilleure façon de solidifier ces concepts est de pratiquer. Essayez de construire des variations dinterfaces glissantes chaque projet vous apprendra quelque chose de nouveau sur linteraction utilisateur et la manipulation du DOM.
### ⚡ **Ce que vous pouvez faire dans les 5 prochaines minutes**
- [ ] Ouvrir les DevTools du navigateur et taper `document.querySelector('body')` dans la console
- [ ] Essayer de modifier le texte dune page web avec `innerHTML` ou `textContent`
- [ ] Ajouter un écouteur dévénement clic à un bouton ou un lien
- [ ] Inspecter la structure du DOM avec le panneau Éléments
### 🎯 **Ce que vous pouvez accomplir cette heure**
- [ ] Terminer le quiz post-formation et revoir les concepts de manipulation DOM
- [ ] Créer une page web interactive qui répond aux clics
- [ ] Pratiquer la gestion des événements avec différents types (clic, survol, touche)
- [ ] Construire une liste de tâches ou un compteur simple via manipulation DOM
- [ ] Explorer la relation entre éléments HTML et objets JavaScript
### 📅 **Votre parcours JavaScript sur une semaine**
- [ ] Compléter le projet terrarium interactif avec fonctionnalité glisser-déposer
- [ ] Maîtriser la délégation dévénements pour gérer efficacement les interactions
- [ ] Apprendre sur la boucle dévénements et JavaScript asynchrone
- [ ] Pratiquer les closures en construisant des modules avec état privé
- [ ] Explorer les API DOM modernes comme Intersection Observer
- [ ] Construire des composants interactifs sans frameworks
### 🌟 **Votre maîtrise JavaScript sur un mois**
- [ ] Créer une application single-page complexe avec JavaScript vanilla
- [ ] Apprendre un framework moderne (React, Vue ou Angular) et le comparer au DOM vanilla
- [ ] Contribuer à des projets open source JavaScript
- [ ] Maîtriser des concepts avancés comme les web components et les custom elements
- [ ] Construire des applications web performantes avec des patterns DOM optimaux
- [ ] Enseigner la manipulation du DOM et les fondamentaux JavaScript
## 🎯 Votre feuille de route pour la maîtrise du DOM en JavaScript
```mermaid
timeline
title Progression d'apprentissage DOM & JavaScript
section Fondations (15 minutes)
Compréhension du DOM : Méthodes de sélection d'éléments
: Navigation dans la structure en arbre
: Modèles d'accès aux propriétés
section Gestion des événements (20 minutes)
Interaction utilisateur : Bases des événements pointeurs
: Configuration des écouteurs d'événements
: Compatibilité multi-appareils
: Techniques de prévention d'événements
section Closures (25 minutes)
Gestion du scope : Création de variables privées
: Persistance des fonctions
: Modèles de gestion d'état
: Efficacité mémoire
section Système de glisser (30 minutes)
Fonctionnalités interactives : Suivi des coordonnées
: Calcul de position
: Mathématiques du mouvement
: Procédures de nettoyage
section Modèles avancés (45 minutes)
Compétences professionnelles : Délégation d'événements
: Optimisation des performances
: Gestion des erreurs
: Considérations d'accessibilité
section Compréhension des frameworks (1 semaine)
Développement moderne : Concepts du DOM virtuel
: Bibliothèques de gestion d'état
: Architectures de composants
: Intégration des outils de build
section Niveau expert (1 mois)
API DOM avancées : Intersection Observer
: Mutation Observer
: Éléments personnalisés
: Composants web
```
### 🛠️ Résumé de votre boîte à outils JavaScript
Après avoir terminé cette leçon, vous avez acquis :
- **Maîtrise du DOM** : sélection déléments, manipulation de propriétés, navigation dans larbre DOM
- **Expertise événementielle** : gestion des interactions multi-appareils avec les événements pointer
- **Compréhension des closures** : gestion détat privé et persistance des fonctions
- **Systèmes interactifs** : implémentation complète du glisser-déposer depuis zéro
- **Conscience de la performance** : nettoyage correct des événements et gestion mémoire
- **Patrons modernes** : techniques dorganisation de code utilisées en développement professionnel
- **Expérience utilisateur** : création dinterfaces intuitives et réactives
**Compétences professionnelles acquises** : Vous avez construit des fonctionnalités utilisant les mêmes techniques que :
- **Tableaux Trello/Kanban** : glisser des cartes entre les colonnes
- **Systèmes de téléversement de fichiers** : prise en charge du glisser-déposer de fichiers
- **Galeries dimages** : interfaces darrangement de photos
- **Applications mobiles** : modèles dinteractions tactiles
**Prochaine étape** : vous êtes prêt à explorer les frameworks modernes comme React, Vue ou Angular qui sappuient sur ces concepts fondamentaux de manipulation DOM !
## Devoir
[Travaillez un peu plus avec le DOM](assignment.md)
---
<!-- CO-OP TRANSLATOR DISCLAIMER START -->
**Avis de non-responsabilité** :
Ce document a été traduit à laide du service de traduction automatique [Co-op Translator](https://github.com/Azure/co-op-translator). Bien que nous nous efforçions dassurer lexactitude, veuillez noter que les traductions automatiques peuvent contenir des erreurs ou des inexactitudes. Le document original dans sa langue dorigine doit être considéré comme la source faisant autorité. Pour les informations critiques, une traduction professionnelle réalisée par un humain est recommandée. Nous déclinons toute responsabilité en cas de malentendus ou de mauvaises interprétations résultant de lutilisation de cette traduction.
<!-- CO-OP TRANSLATOR DISCLAIMER END -->