Skip to content

Commit 2e02d6d

Browse files
authored
Merge pull request #337 from joaquinelio/mutation
Mutation observer
2 parents f6cd4d8 + 2e0cc49 commit 2e02d6d

File tree

1 file changed

+94
-94
lines changed

1 file changed

+94
-94
lines changed
Lines changed: 94 additions & 94 deletions
Original file line numberDiff line numberDiff line change
@@ -1,82 +1,82 @@
11

22
# Mutation observer
33

4-
`MutationObserver` is a built-in object that observes a DOM element and fires a callback in case of changes.
4+
`MutationObserver` es un objeto incorporado que observa un elemento DOM y dispara un callback cuando hay cambios en él.
55

6-
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.
6+
Primero veremos su sintaxis, luego exploraremos un caso de la vida real para ver dónde puede ser útil.
77

8-
## Syntax
8+
## Sintaxis
99

10-
`MutationObserver` is easy to use.
10+
`MutationObserver` es fácil de usar.
1111

12-
First, we create an observer with a callback-function:
12+
Primero creamos un observador con una función callback:
1313

1414
```js
1515
let observer = new MutationObserver(callback);
1616
```
1717

18-
And then attach it to a DOM node:
18+
Y luego lo vinculamos a un nodo DOM:
1919

2020
```js
2121
observer.observe(node, config);
2222
```
2323

24-
`config` is an object with boolean options "what kind of changes to react on":
25-
- `childList` -- changes in the direct children of `node`,
26-
- `subtree` -- in all descendants of `node`,
27-
- `attributes` -- attributes of `node`,
28-
- `attributeFilter` -- an array of attribute names, to observe only selected ones.
29-
- `characterData` -- whether to observe `node.data` (text content),
24+
`config` es un objeto con opciones booleanas "a qué clase de cambios reaccionar":
25+
- `childList` -- cambios en los hijos directos de `node`,
26+
- `subtree` -- en todos los descendientes de `node`,
27+
- `attributes` -- atributos de `node`,
28+
- `attributeFilter` -- un array de nombres de atributos, para observar solamente a los seleccionados,
29+
- `characterData` -- establece si debe observar cambios de texto en `node.data` o no,
3030

31-
Few other options:
32-
- `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),
33-
- `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).
31+
Algunas otras opciones:
32+
- `attributeOldValue` -- si es `true`, tanto el valor viejo como el nuevo del atributo son pasados al callback (ver abajo), de otro modo pasa solamente el nuevo (necesita la opción `attributes`),
33+
- `characterDataOldValue` -- si es `true`, tanto el valor viejo como el nuevo de `node.data` son pasados al callback (ver abajo), de otro modo pasa solamente el nuevo (necesita la opción `characterData`).
3434

35-
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.
35+
Entonces, después de cualquier cambio, el `callback` es ejecutado: los cambios son pasados en el primer argumento como una lista objetos [MutationRecord](https://dom.spec.whatwg.org/#mutationrecord), y el observador en sí mismo como segundo argumento.
3636

37-
[MutationRecord](https://dom.spec.whatwg.org/#mutationrecord) objects have properties:
37+
Los objetos [MutationRecord](https://dom.spec.whatwg.org/#mutationrecord) tienen como propiedades:
3838

39-
- `type` -- mutation type, one of
40-
- `"attributes"`: attribute modified
41-
- `"characterData"`: data modified, used for text nodes,
42-
- `"childList"`: child elements added/removed,
43-
- `target` -- where the change occurred: an element for `"attributes"`, or text node for `"characterData"`, or an element for a `"childList"` mutation,
44-
- `addedNodes/removedNodes` -- nodes that were added/removed,
45-
- `previousSibling/nextSibling` -- the previous and next sibling to added/removed nodes,
46-
- `attributeName/attributeNamespace` -- the name/namespace (for XML) of the changed attribute,
47-
- `oldValue` -- the previous value, only for attribute or text changes, if the corresponding option is set `attributeOldValue`/`characterDataOldValue`.
39+
- `type` -- tipo de mutación, uno de:
40+
- `"attributes"`: atributo modificado,
41+
- `"characterData"`: dato modificado, usado para nodos de texto,
42+
- `"childList"`: elementos hijos agregados o quitados,
43+
- `target` -- dónde ocurrió el cambio: un elemento para `"attributes"`, o un nodo de texto para `"characterData"`, o un elemento para una mutación de `"childList"`,
44+
- `addedNodes/removedNodes` -- nodos que fueron agregados o quitados,
45+
- `previousSibling/nextSibling` -- los nodos "hermanos", previos y siguientes a los nodos agregados y quitados,
46+
- `attributeName/attributeNamespace` -- el nombre o namespace (para XML) del atributo cambiado,
47+
- `oldValue` -- el valor previo, solamente cambios de atributo o cambios de texto si se establece la opción correspondiente `attributeOldValue`/`characterDataOldValue`.
4848

49-
For example, here's a `<div>` with a `contentEditable` attribute. That attribute allows us to focus on it and edit.
49+
Por ejemplo, aquí hay un `<div>` con un atributo `contentEditable`. Ese atributo nos permite poner el foco en él y editarlo.
5050

5151
```html run
5252
<div contentEditable id="elem">Click and <b>edit</b>, please</div>
5353

5454
<script>
5555
let observer = new MutationObserver(mutationRecords => {
56-
console.log(mutationRecords); // console.log(the changes)
56+
console.log(mutationRecords); // console.log(los cambios)
5757
});
5858
59-
// observe everything except attributes
59+
// observa todo exceptuando atributos
6060
observer.observe(elem, {
61-
childList: true, // observe direct children
62-
subtree: true, // and lower descendants too
63-
characterDataOldValue: true // pass old data to callback
61+
childList: true, // observa hijos directos
62+
subtree: true, // y descendientes inferiores también
63+
characterDataOldValue: true // pasa el dato viejo al callback
6464
});
6565
</script>
6666
```
6767

68-
If we run this code in the browser, then focus on the given `<div>` and change the text inside `<b>edit</b>`, `console.log` will show one mutation:
68+
Si ejecutamos este código en el navegador, el foco en el `<div>` dado y el cambio en texto dentro de `<b>edit</b>`, `console.log` mostrará una mutación:
6969

7070
```js
7171
mutationRecords = [{
7272
type: "characterData",
7373
oldValue: "edit",
7474
target: <text node>,
75-
// other properties empty
75+
// otras propiedades vacías
7676
}];
7777
```
7878

79-
If we make more complex editing operations, e.g. remove the `<b>edit</b>`, the mutation event may contain multiple mutation records:
79+
Si hacemos operaciones de edición más complejas, como eliminar el `<b>edit</b>`, el evento de mutación puede contener múltiples registros de mutación:
8080

8181
```js
8282
mutationRecords = [{
@@ -85,75 +85,75 @@ mutationRecords = [{
8585
removedNodes: [<b>],
8686
nextSibling: <text node>,
8787
previousSibling: <text node>
88-
// other properties empty
88+
// otras propiedades vacías
8989
}, {
9090
type: "characterData"
9191
target: <text node>
92-
// ...mutation details depend on how the browser handles such removal
93-
// it may coalesce two adjacent text nodes "edit " and ", please" into one node
94-
// or it may leave them separate text nodes
92+
// ...detalles de mutación dependen de cómo el navegador maneja tal eliminación
93+
// puede unir dos nodos de texto adyacentes "edit " y ", please" en un nodo
94+
// o puede dejarlos como nodos de texto separados
9595
}];
9696
```
9797

98-
So, `MutationObserver` allows to react on any changes within DOM subtree.
98+
Así, `MutationObserver` permite reaccionar a cualquier cambio dentro del subárbol DOM.
9999

100-
## Usage for integration
100+
## Uso para integración
101101

102-
When such thing may be useful?
102+
¿Cuándo puede ser práctico esto?
103103

104-
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 `<div class="ads">Unwanted ads</div>`.
104+
Imagina la situación cuando necesitas añadir un script de terceros que contiene funcionalidad útil pero que también hace algo no deseado, por ejemplo añadir publicidad `<div class="ads">Unwanted ads</div>`.
105105

106-
Naturally, the third-party script provides no mechanisms to remove it.
106+
Naturalmente el script de terceras partes no proporciona mecanismos para removerlo.
107107

108-
Using `MutationObserver`, we can detect when the unwanted element appears in our DOM and remove it.
108+
Usando `MutationObserver` podemos detectar cuándo aparece el elemento no deseado en nuestro DOM y removerlo.
109109

110-
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.
110+
Hay otras situaciones, como cuando un script de terceras partes agrega algo en nuestro documento y quisiéramos detectarlo para adaptar nuestra página y cambiar el tamaño de algo dinámicamente, etc.
111111

112-
`MutationObserver` allows to implement this.
112+
`MutationObserver` permite implementarlo.
113113

114-
## Usage for architecture
114+
## Uso para arquitectura
115115

116-
There are also situations when `MutationObserver` is good from architectural standpoint.
116+
Hay también situaciones donde `MutationObserver` es bueno desde el punto de vista de la arquitectura.
117117

118-
Let's say we're making a website about programming. Naturally, articles and other materials may contain source code snippets.
118+
Digamos que estamos haciendo un sitio web acerca de programación. Naturalmente, los artículos y otros materiales pueden contener fragmentos de código.
119119

120-
Such snippet in an HTML markup looks like this:
120+
Tal fragmento en un markup HTML se ve como esto:
121121

122122
```html
123123
...
124124
<pre class="language-javascript"><code>
125-
// here's the code
125+
// aquí el código
126126
let hello = "world";
127127
</code></pre>
128128
...
129129
```
130130

131-
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.
131+
También usaremos una librería JavaScript de "highlighting" para resaltar elementos en nuestro sitio, por ejemplo [Prism.js](https://prismjs.com/). Una llamada a `Prism.highlightElem(pre)` examina el contenido de tales elementos `pre` y les agrega tags y styles especiales para obtener sintaxis resaltada con color, similares a los que ves en esta página.
132132

133-
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:
133+
¿Exactamente cuándo ejecutar tal método de highlighting? Podemos hacerlo en el evento `DOMContentLoaded`, o al final de la página. En el momento en que tenemos nuestro DOM listo buscamos los elementos `pre[class*="language"]` y llamamos `Prism.highlightElem` en ellos:
134134

135135
```js
136-
// highlight all code snippets on the page
136+
// resaltar todos los fragmentos de código en la página
137137
document.querySelectorAll('pre[class*="language"]').forEach(Prism.highlightElem);
138138
```
139139

140-
Everything's simple so far, right? There are `<pre>` code snippets in HTML, we highlight them.
140+
Todo es simple hasta ahora, ¿verdad? Hay fragmentos de código `<pre>` en HTML y los resaltamos.
141141

142-
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:
142+
Continuemos. Digamos que vamos a buscar dinámicamente material desde un servidor. Estudiaremos métodos para ello [más adelante](info:fetch) en el tutorial. Por ahora solamente importa que buscamos un artículo HTML desde un servidor web y lo mostramos bajo demanda:
143143

144144
```js
145-
let article = /* fetch new content from server */
145+
let article = /* busca contenido nuevo desde un servidor */
146146
articleElem.innerHTML = article;
147147
```
148148

149-
The new `article` HTML may contain code snippets. We need to call `Prism.highlightElem` on them, otherwise they won't get highlighted.
149+
El nuevo elemento HTML `article` puede contener fragmentos de código. Necesitamos llamar `Prism.highlightElem` en ellos, de otro modo no se resaltarían.
150150

151-
**Where and when to call `Prism.highlightElem` for a dynamically loaded article?**
151+
**¿Dónde y cuándo llamar `Prism.highlightElem` en un artículo cargado dinámicamente?**
152152

153-
We could append that call to the code that loads an article, like this:
153+
Podríamos agregar el llamado al código que carga un "article", como esto:
154154

155155
```js
156-
let article = /* fetch new content from server */
156+
let article = /* busca contenido nuevo desde un servidor */
157157
articleElem.innerHTML = article;
158158

159159
*!*
@@ -162,38 +162,38 @@ snippets.forEach(Prism.highlightElem);
162162
*/!*
163163
```
164164

165-
...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.
165+
...Pero imagina que tenemos muchos lugares en el código donde cargamos contenido: artículos, cuestionarios, entradas de foros. ¿Necesitamos poner el llamado al "highlighting" en todos lugares? No es muy conveniente, y es fácil de olvidar además.
166166

167-
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.
167+
¿Y si el contenido es cargado por un módulo de terceras partes? Por ejemplo tenemos un foro, escrito por algún otro, que carga contenido dinámicamente y quisiéramos añadirle sintaxis de highlighting. A nadie le gusta emparchar scripts de terceras partes.
168168

169-
Luckily, there's another option.
169+
Afortunadamente hay otra opción.
170170

171-
We can use `MutationObserver` to automatically detect when code snippets are inserted in the page and highlight them.
171+
Podemos usar `MutationObserver` para detectar automáticamente cuándo los fragmentos de código son insertados en la página y resaltarlos.
172172

173-
So we'll handle the highlighting functionality in one place, relieving us from the need to integrate it.
173+
Entonces manejaremos la funcionalidad de "highlighting" en un único lugar, liberándonos de la necesidad de integrarlo.
174174

175-
### Dynamic highlight demo
175+
### Demo de highlight dinámico
176176

177-
Here's the working example.
177+
Aquí el ejemplo funcionando.
178178

179-
If you run this code, it starts observing the element below and highlighting any code snippets that appear there:
179+
Si ejecutas el código, este comienza a observar el elemento debajo y resalta cualquier fragmento de código que aparezca allí:
180180

181181
```js run
182182
let observer = new MutationObserver(mutations => {
183183

184184
for(let mutation of mutations) {
185-
// examine new nodes, is there anything to highlight?
185+
// examine nodos nuevos, ¿hay algo para resaltar?
186186

187187
for(let node of mutation.addedNodes) {
188-
// we track only elements, skip other nodes (e.g. text nodes)
188+
// seguimos elementos solamente, saltamos los otros nodos (es decir nodos de texto)
189189
if (!(node instanceof HTMLElement)) continue;
190190

191-
// check the inserted element for being a code snippet
191+
// verificamos que el elemento insertado sea un fragmento de código
192192
if (node.matches('pre[class*="language-"]')) {
193193
Prism.highlightElement(node);
194194
}
195195

196-
// or maybe there's a code snippet somewhere in its subtree?
196+
// ¿o tal vez haya un fragmento de código en su sub-árbol?
197197
for(let elem of node.querySelectorAll('pre[class*="language-"]')) {
198198
Prism.highlightElement(elem);
199199
}
@@ -207,18 +207,18 @@ let demoElem = document.getElementById('highlight-demo');
207207
observer.observe(demoElem, {childList: true, subtree: true});
208208
```
209209

210-
Here, below, there's an HTML-element and JavaScript that dynamically fills it using `innerHTML`.
210+
Aquí, abajo, hay un elemento HTML y JavaScript que lo llena dinámicamente usando `innerHTML`.
211211

212-
Please run the previous code (above, observes that element), and then the code below. You'll see how `MutationObserver` detects and highlights the snippet.
212+
Por favor ejecuta el código anterior (arriba, que observa aquel elemento) y luego el código de abajo. Verás cómo `MutationObserver` detecta y resalta el fragmento.
213213

214214
<p id="highlight-demo" style="border: 1px solid #ddd">A demo-element with <code>id="highlight-demo"</code>, run the code above to observe it.</p>
215215

216-
The following code populates its `innerHTML`, that causes the `MutationObserver` to react and highlight its contents:
216+
El siguiente código llena su `innerHTML`, lo que causa que `MutationObserver` reaccione y resalte su contenido:
217217

218218
```js run
219219
let demoElem = document.getElementById('highlight-demo');
220220

221-
// dynamically insert content with code snippets
221+
// inserta contenido con fragmentos de código
222222
demoElem.innerHTML = `A code snippet is below:
223223
<pre class="language-javascript"><code> let hello = "world!"; </code></pre>
224224
<div>Another one:</div>
@@ -228,39 +228,39 @@ demoElem.innerHTML = `A code snippet is below:
228228
`;
229229
```
230230

231-
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.
231+
Ahora tenemos un `MutationObserver` que puede rastrear todo el "highlighting" en los elementos observados del `document` entero. Podemos agregar o quitar fragmentos de código en el HTML sin siquiera pensar en ello.
232232

233-
## Additional methods
233+
## Métodos adicionales
234234

235-
There's a method to stop observing the node:
235+
Hay un método para detener la observación del nodo:
236236

237-
- `observer.disconnect()` -- stops the observation.
237+
- `observer.disconnect()` -- detiene la observación.
238238

239-
When we stop the observing, it might be possible that some changes were not processed by the observer yet.
239+
Cuando detenemos la observación, algunos cambios todavía podrían quedar sin ser procesados por el observador.
240240

241-
- `observer.takeRecords()` -- gets a list of unprocessed mutation records, those that happened, but the callback did not handle them.
241+
- `observer.takeRecords()` -- obtiene una lista de registros de mutaciones sin procesar, aquellos que ocurrieron pero el callback no manejó.
242242

243-
These methods can be used together, like this:
243+
Estos métodos pueden ser usados juntos, como esto:
244244

245245
```js
246-
// we'd like to stop tracking changes
246+
// quisiéramos detener el rastreo de cambios
247247
observer.disconnect();
248248

249-
// handle unprocessed some mutations
249+
// manejar algunas mutaciones que no fueron procesadas
250250
let mutationRecords = observer.takeRecords();
251251
...
252252
```
253253

254-
```smart header="Garbage collection interaction"
255-
Observers use weak references to nodes internally. That is: if a node is removed from DOM, and becomes unreachable, then it becomes garbage collected.
254+
```smart header="Interacción con la recolección de basura"
255+
Los observadores usan internamente referencias débiles. Esto es: si un nodo es quitado del DOM y se hace inalcanzable, se vuelve basura a ser recolectada.
256256
257-
The mere fact that a DOM node is observed doesn't prevent the garbage collection.
257+
El mero hecho de que un nodo DOM sea observado no evita la recolección de basura.
258258
```
259259

260-
## Summary
260+
## Resumen
261261

262-
`MutationObserver` can react on changes in DOM: attributes, added/removed elements, text content.
262+
`MutationObserver` puede reaccionar a cambios en el DOM: atributos, elementos añadidos y quitados, contenido de texto.
263263

264-
We can use it to track changes introduced by other parts of our code, as well as to integrate with third-party scripts.
264+
Podemos usarlo para rastrear cambios introducidos por otras partes de nuestro código o bien para integrarlo con scripts de terceras partes.
265265

266-
`MutationObserver` can track any changes. The config "what to observe" options are used for optimizations, not to spend resources on unneeded callback invocations.
266+
`MutationObserver` puede rastrear cualquier cambio. Las opciones de `config` permiten establecer qué se va a observar, se usa para optimización y no desperdiciar recursos en llamados al callback innecesarios.

0 commit comments

Comments
 (0)