diff --git a/2-ui/99-ui-misc/01-mutation-observer/article.md b/2-ui/99-ui-misc/01-mutation-observer/article.md index 6a458fa02..3969b9d53 100644 --- a/2-ui/99-ui-misc/01-mutation-observer/article.md +++ b/2-ui/99-ui-misc/01-mutation-observer/article.md @@ -1,82 +1,82 @@ # Mutation observer -`MutationObserver` is a built-in object that observes a DOM element and fires a callback in case of changes. +`MutationObserver` est un objet intégré qui observe un élément DOM et déclenche un callback (fonction de rappel) en cas de changement. -We'll first take a look at the syntax, and then explore a real-world use case, to see where such thing may be useful. +Nous examinerons d'abord la syntaxe, puis nous étudierons un cas d'utilisation réel, pour voir où ce genre de chose peut être utile. -## Syntax +## Syntaxe -`MutationObserver` is easy to use. +`MutationObserver` est facile à utiliser. -First, we create an observer with a callback-function: +Tout d'abord, nous créons un observateur avec un callback: ```js let observer = new MutationObserver(callback); ``` -And then attach it to a DOM node: +Et ensuite on l'attache à un nœud DOM: ```js observer.observe(node, config); ``` -`config` is an object with boolean options "what kind of changes to react on": -- `childList` -- changes in the direct children of `node`, -- `subtree` -- in all descendants of `node`, -- `attributes` -- attributes of `node`, -- `attributeFilter` -- an array of attribute names, to observe only selected ones. -- `characterData` -- whether to observe `node.data` (text content), +`config` est un objet avec des options booléennes "sur quel type de changements réagir": +- `childList` -- les changements dans les enfants directs de `node`, +- `subtree` -- dans tous les descendants de `node`, +- `attributes` -- dans les attributs de `node`, +- `attributeFilter` -- dans un tableau de noms d'attributs, pour n'observer que ceux qui sont sélectionnés, +- `characterData` -- s'il faut observer `node.data` (contenu du texte), -Few other options: -- `attributeOldValue` -- if `true`, pass both the old and the new value of attribute to callback (see below), otherwise only the new one (needs `attributes` option), -- `characterDataOldValue` -- if `true`, pass both the old and the new value of `node.data` to callback (see below), otherwise only the new one (needs `characterData` option). +Quelques autres options: +- `attributeOldValue` -- si `true`, passer l'ancienne et la nouvelle valeur de l'attribut au callback (voir ci-dessous), sinon, seule la nouvelle valeur (a besoin de l'option `attributes`). +- `characterDataOldValue` -- si `true`, passer l'ancienne et la nouvelle valeur de `node.data` au callback (voir ci-dessous), sinon, seule la nouvelle valeur (a besoin de l'option `characterData`) -Then after any changes, the `callback` is executed: changes are passed in the first argument as a list of [MutationRecord](https://dom.spec.whatwg.org/#mutationrecord) objects, and the observer itself as the second argument. +Ensuite, après tout changement, le `callback` est exécuté : les changements sont passés dans le premier argument comme une liste d'objets [MutationRecord](https://dom.spec.whatwg.org/#mutationrecord), et l'observer lui-même comme deuxième argument. -[MutationRecord](https://dom.spec.whatwg.org/#mutationrecord) objects have properties: +Les objects [MutationRecord](https://dom.spec.whatwg.org/#mutationrecord) ont les propriétés suivantes: -- `type` -- mutation type, one of - - `"attributes"`: attribute modified - - `"characterData"`: data modified, used for text nodes, - - `"childList"`: child elements added/removed, -- `target` -- where the change occurred: an element for `"attributes"`, or text node for `"characterData"`, or an element for a `"childList"` mutation, -- `addedNodes/removedNodes` -- nodes that were added/removed, -- `previousSibling/nextSibling` -- the previous and next sibling to added/removed nodes, -- `attributeName/attributeNamespace` -- the name/namespace (for XML) of the changed attribute, -- `oldValue` -- the previous value, only for attribute or text changes, if the corresponding option is set `attributeOldValue`/`characterDataOldValue`. +- `type` -- type de mutation, valeurs possibles: + - `"attributes"`: attribut modifié, + - `"characterData"`: données modifiées, utilisées pour les nœuds de texte, + - `"childList"`: éléments enfants ajoutés/supprimés, +- `target` -- où le changement a eu lieu: un élément pour les `attributes`, ou un nœud de texte pour les `characterData`, ou un élément pour une mutation `childList`, +- `addedNodes/removedNodes` -- les nœuds qui ont été ajoutés/supprimés, +- `previousSibling/nextSibling` -- le frère ou la sœur précédent(e) et suivant(e) aux nœuds ajoutés/supprimés, +- `attributeName/attributeNamespace` -- le nom/espace de nommage (pour XML) de l'attribut modifié, +- `oldValue` -- la valeur précédente, uniquement pour les modifications d'attributs ou de texte, si l'option correspondante est définie `attributeOldValue/characterDataOldValue`. -For example, here's a `
` with a `contentEditable` attribute. That attribute allows us to focus on it and edit. +Par exemple, voici un `
` avec un attribut `contentEditable`. Cet attribut nous permet de "focus" contenu et de l'éditer. ```html run
Click and edit, please
``` -If we run this code in the browser, then focus on the given `
` and change the text inside `edit`, `console.log` will show one mutation: +Si nous exécutons ce code dans le navigateur, puis qu'on focus la `
` donné et changeons le texte à l'intérieur de `edit`, `console.log` affichera une mutation: ```js mutationRecords = [{ type: "characterData", oldValue: "edit", target: , - // other properties empty + // autres propriétés vides }]; ``` -If we make more complex editing operations, e.g. remove the `edit`, the mutation event may contain multiple mutation records: +Si nous effectuons des opérations d'édition plus complexes, par exemple en supprimant le `edit`, l'événement de mutation peut contenir plusieurs enregistrements de mutation: ```js mutationRecords = [{ @@ -85,75 +85,75 @@ mutationRecords = [{ removedNodes: [], nextSibling: , previousSibling: - // other properties empty + // autres propriétés vides }, { type: "characterData" target: - // ...mutation details depend on how the browser handles such removal - // it may coalesce two adjacent text nodes "edit " and ", please" into one node - // or it may leave them separate text nodes + // ...les détails de la mutation dépendent de la façon dont le navigateur gère cette suppression + // il peut regrouper deux nœuds de texte adjacents "edit" et ", please" en un seul nœud + // ou il peut leur laisser des nœuds de texte séparés }]; ``` -So, `MutationObserver` allows to react on any changes within DOM subtree. +`MutationObserver` permet donc de réagir à tout changement dans le sous-arbre DOM -## Usage for integration +## Utilisation pour l'intégration -When such thing may be useful? +Quand une telle chose peut-elle être utile ? -Imagine the situation when you need to add a third-party script that contains useful functionality, but also does something unwanted, e.g. shows ads `
Unwanted ads
`. +Imaginez la situation où vous devez ajouter un script tiers qui contient des fonctionnalités utiles, mais qui fait aussi quelque chose d'indésirable, par exemple afficher des annonces `
Unwanted ads
`. -Naturally, the third-party script provides no mechanisms to remove it. +Naturellement, le script tiers ne prévoit aucun mécanisme permettant de le supprimer. -Using `MutationObserver`, we can detect when the unwanted element appears in our DOM and remove it. +Grâce à `MutationObserver`, nous pouvons détecter quand l'élément indésirable apparaît dans notre DOM et le supprimer. -There are other situations when a third-party script adds something into our document, and we'd like to detect, when it happens, to adapt our page, dynamically resize something etc. +Il y a d'autres situations où un script tiers ajoute quelque chose dans notre document, et nous aimerions détecter, quand cela se produit, d'adapter notre page, de redimensionner dynamiquement quelque chose, etc. -`MutationObserver` allows to implement this. +`MutationObserver` permet de faire tout ça. -## Usage for architecture +## Utilisation pour l'architecture -There are also situations when `MutationObserver` is good from architectural standpoint. +Il y a aussi des situations où `MutationObserver` est bon du point de vue architectural. -Let's say we're making a website about programming. Naturally, articles and other materials may contain source code snippets. +Disons que nous faisons un site web sur la programmation. Naturellement, les articles et autres matériels peuvent contenir des extraits de code source. -Such snippet in an HTML markup looks like this: +Voici à quoi ressemble un tel extrait dans un balisage HTML: ```html ...

-  // here's the code
+  // voici le code
   let hello = "world";
 
... ``` -Also we'll use a JavaScript highlighting library on our site, e.g. [Prism.js](https://prismjs.com/). A call to `Prism.highlightElem(pre)` examines the contents of such `pre` elements and adds into them special tags and styles for colored syntax highlighting, similar to what you see in examples here, at this page. +Nous utiliserons également une bibliothèque de surlignage JavaScript sur notre site, par exemple [Prism.js](https://prismjs.com/). Un appel à `Prism.highlightElem(pre)` examine le contenu de ces `pre` et y ajoute des balises et des styles spéciaux pour la mise en évidence syntaxique colorée, comme ce que vous voyez dans les exemples ici. -When exactly to run that highlighting method? We can do it on `DOMContentLoaded` event, or at the bottom of the page. At that moment we have our DOM ready, can search for elements `pre[class*="language"]` and call `Prism.highlightElem` on them: +Quand exactement faut-il appliquer cette méthode de mise en évidence ? Nous pouvons le faire sur l'événement `DOMContentLoaded`, ou en bas de page. À ce moment, nous avons notre DOM prêt, nous pouvons rechercher des éléments `pre[class*="language"]` et appeler `Prism.highlightElem` dessus: ```js -// highlight all code snippets on the page +// mettre en évidence tous les extraits de code sur la page document.querySelectorAll('pre[class*="language"]').forEach(Prism.highlightElem); ``` -Everything's simple so far, right? There are `
` code snippets in HTML, we highlight them.
+Tout est simple jusqu'à présent, n'est-ce pas ? Il y a des `
` en HTML, nous les mettons en évidence.
 
-Now let's go on. Let's say we're going to dynamically fetch materials from a server. We'll study methods for that [later in the tutorial](info:fetch). For now it only matters that we fetch an HTML article from a webserver and display it on demand:
+Maintenant, continuons. Disons que nous allons chercher dynamiquement des éléments sur un serveur. Nous étudierons les méthodes pour cela [plus tard dans le tutoriel](info:fetch). Pour l'instant, il suffit d'aller chercher un article HTML sur un serveur web et de l'afficher à la demande :
 
 ```js
-let article = /* fetch new content from server */
+let article = /* récupérer du nouveau contenu sur le serveur */
 articleElem.innerHTML = article;
 ```
 
-The new `article` HTML may contain code snippets. We need to call `Prism.highlightElem` on them, otherwise they won't get highlighted.
+Le nouvel `article` HTML peut contenir des extraits de code. Nous devons appeler `Prism.highlightElem` sur eux, sinon ils ne seront pas mis en évidence.
 
-**Where and when to call `Prism.highlightElem` for a dynamically loaded article?**
+**Où et quand appeler `Prism.highlightElem` pour un article chargé dynamiquement ?**
 
-We could append that call to the code that loads an article, like this:
+Nous pourrions ajouter cet appel au code qui charge un article, comme ceci:
 
 ```js
-let article = /* fetch new content from server */
+let article = /* récupérer du nouveau contenu sur le serveur */
 articleElem.innerHTML = article;
 
 *!*
@@ -162,38 +162,36 @@ snippets.forEach(Prism.highlightElem);
 */!*
 ```
 
-...But imagine, we have many places in the code where we load contents: articles, quizzes, forum posts. Do we need to put the highlighting call everywhere? That's not very convenient, and also easy to forget.
+...Mais imaginez, nous avons de nombreux endroits dans le code où nous chargeons des contenus : articles, quiz, messages de forum. Faut-il mettre l'appel de mise en évidence partout ? Ce n'est pas très pratique, et aussi facile à oublier.
 
-And what if the content is loaded by a third-party module? E.g. we have a forum written by someone else, that loads contents dynamically, and we'd like to add syntax highlighting to it. No one likes to patch third-party scripts.
+Et si le contenu est chargé par un module tiers ? Par exemple, nous avons un forum écrit par quelqu'un d'autre, qui charge le contenu dynamiquement, et nous aimerions y ajouter une mise en évidence syntaxique. Personne n'aime patcher des scripts tiers.
 
-Luckily, there's another option.
+Heureusement, il y a une autre option.
 
-We can use `MutationObserver` to automatically detect when code snippets are inserted in the page and highlight them.
+Nous pouvons utiliser `MutationObserver` pour détecter automatiquement quand des extraits de code sont insérés dans la page et les mettre en évidence.
 
-So we'll handle the highlighting functionality in one place, relieving us from the need to integrate it.
+Nous allons donc gérer la fonctionnalité de mise en évidence en un seul endroit.
 
-### Dynamic highlight demo
+### Démonstration dynamique de mise en évidence
 
-Here's the working example.
-
-If you run this code, it starts observing the element below and highlighting any code snippets that appear there:
+Si vous exécutez ce code, il commence à observer l'élément ci-dessous et à mettre en évidence tout extrait de code qui y apparaît:
 
 ```js run
 let observer = new MutationObserver(mutations => {
 
   for(let mutation of mutations) {
-    // examine new nodes, is there anything to highlight?
+    // examiner les nouveaux nœuds, y a-t-il quelque chose à mettre en évidence ?
 
     for(let node of mutation.addedNodes) {
-      // we track only elements, skip other nodes (e.g. text nodes)
+      // nous ne suivons que les éléments, nous sautons les autres nœuds (par exemple les nœuds de texte)
       if (!(node instanceof HTMLElement)) continue;
 
-      // check the inserted element for being a code snippet
+      // vérifier que l'élément inséré est un extrait de code
       if (node.matches('pre[class*="language-"]')) {
         Prism.highlightElement(node);
       }
 
-      // or maybe there's a code snippet somewhere in its subtree?
+      // ou peut-être qu'il y a un extrait de code quelque part dans son sous-arbre ?
       for(let elem of node.querySelectorAll('pre[class*="language-"]')) {
         Prism.highlightElement(elem);
       }
@@ -207,60 +205,60 @@ let demoElem = document.getElementById('highlight-demo');
 observer.observe(demoElem, {childList: true, subtree: true});
 ```
 
-Here, below, there's an HTML-element and JavaScript that dynamically fills it using `innerHTML`.
+Ci-dessous, il y a un élément HTML et JavaScript qui le remplit dynamiquement en utilisant `innerHTML`.
 
-Please run the previous code (above, observes that element), and then the code below. You'll see how `MutationObserver` detects and highlights the snippet.
+Veuillez exécuter le code précédent (ci-dessus, qui observe cet élément), puis le code ci-dessous. Vous verrez comment `MutationObserver` détecte et met en évidence l'extrait.
 
-

A demo-element with id="highlight-demo", run the code above to observe it.

+

Voici un élément de démonstration avec id="highlight-demo", exécutez le code ci-dessus pour l'observer.

-The following code populates its `innerHTML`, that causes the `MutationObserver` to react and highlight its contents: +Le code suivant remplit son `innerHTML`, qui fait réagir le `MutationObserver` et met en évidence son contenu: ```js run let demoElem = document.getElementById('highlight-demo'); -// dynamically insert content with code snippets -demoElem.innerHTML = `A code snippet is below: +// insérer dynamiquement du contenu avec des extraits de code +demoElem.innerHTML = `Vous trouverez ci-dessous un extrait de code:
 let hello = "world!"; 
-
Another one:
+
Un autre:
.class { margin: 5px; } 
`; ``` -Now we have `MutationObserver` that can track all highlighting in observed elements or the whole `document`. We can add/remove code snippets in HTML without thinking about it. +Nous avons maintenant `MutationObserver` qui peut suivre tous les surlignages dans les éléments observés ou dans le `document` entier. Nous pouvons ajouter/supprimer des bribes de code en HTML sans y penser. -## Additional methods +## Méthodes supplémentaires -There's a method to stop observing the node: +Il y a une méthode pour arrêter d'observer le nœud: -- `observer.disconnect()` -- stops the observation. +- `observer.disconnect()` -- arrête l'observation. -When we stop the observing, it might be possible that some changes were not processed by the observer yet. +Lorsque nous arrêtons l'observation, il est possible que certaines modifications n'aient pas encore été traitées par l'observateur. -- `observer.takeRecords()` -- gets a list of unprocessed mutation records, those that happened, but the callback did not handle them. +- `observer.takeRecords()` -- obtient une liste des dossiers de mutation non traités, ceux qui se sont produits, mais le rappel n'a pas permis de les traiter. -These methods can be used together, like this: +Ces méthodes peuvent être utilisées ensemble, comme ceci: ```js -// we'd like to stop tracking changes +// nous aimerions cesser de suivre les changements observer.disconnect(); -// handle unprocessed some mutations +// gérer certaines mutations non traitées let mutationRecords = observer.takeRecords(); ... ``` -```smart header="Garbage collection interaction" -Observers use weak references to nodes internally. That is: if a node is removed from DOM, and becomes unreachable, then it becomes garbage collected. +```smart header="Interaction avec le ramassage des ordures" +Les observateurs utilisent des références faibles aux nœuds en interne. Autrement dit, si un nœud est retiré du DOM et devient inaccessible, il devient alors un déchet collecté. -The mere fact that a DOM node is observed doesn't prevent the garbage collection. +Le simple fait qu'un nœud DOM soit observé n'empêche pas le ramassage des ordures. ``` -## Summary +## Résumé -`MutationObserver` can react on changes in DOM: attributes, added/removed elements, text content. +`MutationObserver` peut réagir aux changements dans le DOM : attributs, éléments ajoutés/supprimés, contenu du texte. -We can use it to track changes introduced by other parts of our code, as well as to integrate with third-party scripts. +Nous pouvons l'utiliser pour suivre les changements introduits par d'autres parties de notre code, ainsi que pour intégrer des scripts tiers. -`MutationObserver` can track any changes. The config "what to observe" options are used for optimizations, not to spend resources on unneeded callback invocations. +`MutationObserver` peut suivre tout changement. Les options de configuration "ce qu'il faut observer" sont utilisées pour des optimisations, afin de ne pas dépenser des ressources pour des callback inutiles.