You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
`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.
5
5
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.
7
7
8
-
## Syntax
8
+
## Sintaxis
9
9
10
-
`MutationObserver`is easy to use.
10
+
`MutationObserver`es fácil de usar.
11
11
12
-
First, we create an observer with a callback-function:
12
+
Primero creamos un observador con una función callback:
13
13
14
14
```js
15
15
let observer =newMutationObserver(callback);
16
16
```
17
17
18
-
And then attach it to a DOM node:
18
+
Y luego lo vinculamos a un nodo DOM:
19
19
20
20
```js
21
21
observer.observe(node, config);
22
22
```
23
23
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,
30
30
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`).
34
34
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.
36
36
37
-
[MutationRecord](https://dom.spec.whatwg.org/#mutationrecord)objects have properties:
37
+
Los objetos [MutationRecord](https://dom.spec.whatwg.org/#mutationrecord)tienen como propiedades:
38
38
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`.
48
48
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.
50
50
51
51
```html run
52
52
<divcontentEditableid="elem">Click and <b>edit</b>, please</div>
53
53
54
54
<script>
55
55
let observer =newMutationObserver(mutationRecords=> {
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
64
64
});
65
65
</script>
66
66
```
67
67
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:
69
69
70
70
```js
71
71
mutationRecords = [{
72
72
type:"characterData",
73
73
oldValue:"edit",
74
74
target:<text node>,
75
-
//other properties empty
75
+
//otras propiedades vacías
76
76
}];
77
77
```
78
78
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:
80
80
81
81
```js
82
82
mutationRecords = [{
@@ -85,75 +85,75 @@ mutationRecords = [{
85
85
removedNodes: [<b>],
86
86
nextSibling:<text node>,
87
87
previousSibling:<text node>
88
-
//other properties empty
88
+
//otras propiedades vacías
89
89
}, {
90
90
type:"characterData"
91
91
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
95
95
}];
96
96
```
97
97
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.
99
99
100
-
## Usage for integration
100
+
## Uso para integración
101
101
102
-
When such thing may be useful?
102
+
¿Cuándo puede ser práctico esto?
103
103
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>`.
105
105
106
-
Naturally, the third-party script provides no mechanisms to remove it.
106
+
Naturalmente el script de terceras partes no proporciona mecanismos para removerlo.
107
107
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.
109
109
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.
111
111
112
-
`MutationObserver`allows to implement this.
112
+
`MutationObserver`permite implementarlo.
113
113
114
-
## Usage for architecture
114
+
## Uso para arquitectura
115
115
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.
117
117
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.
119
119
120
-
Such snippet in an HTML markup looks like this:
120
+
Tal fragmento en un markup HTML se ve como esto:
121
121
122
122
```html
123
123
...
124
124
<preclass="language-javascript"><code>
125
-
// here's the code
125
+
// aquí el código
126
126
let hello = "world";
127
127
</code></pre>
128
128
...
129
129
```
130
130
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.
132
132
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:
134
134
135
135
```js
136
-
//highlight all code snippets on the page
136
+
//resaltar todos los fragmentos de código en la página
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.
141
141
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:
143
143
144
144
```js
145
-
let article =/*fetch new content from server*/
145
+
let article =/*busca contenido nuevo desde un servidor*/
146
146
articleElem.innerHTML= article;
147
147
```
148
148
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.
150
150
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?**
152
152
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:
154
154
155
155
```js
156
-
let article =/*fetch new content from server*/
156
+
let article =/*busca contenido nuevo desde un servidor*/
...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.
166
166
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.
168
168
169
-
Luckily, there's another option.
169
+
Afortunadamente hay otra opción.
170
170
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.
172
172
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.
174
174
175
-
### Dynamic highlight demo
175
+
### Demo de highlight dinámico
176
176
177
-
Here's the working example.
177
+
Aquí el ejemplo funcionando.
178
178
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í:
180
180
181
181
```js run
182
182
let observer =newMutationObserver(mutations=> {
183
183
184
184
for(let mutation of mutations) {
185
-
// examine new nodes, is there anything to highlight?
185
+
// examine nodos nuevos, ¿hay algo para resaltar?
186
186
187
187
for(let node ofmutation.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)
189
189
if (!(node instanceofHTMLElement)) continue;
190
190
191
-
//check the inserted element for being a code snippet
191
+
//verificamos que el elemento insertado sea un fragmento de código
192
192
if (node.matches('pre[class*="language-"]')) {
193
193
Prism.highlightElement(node);
194
194
}
195
195
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?
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`.
211
211
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.
213
213
214
214
<pid="highlight-demo"style="border: 1pxsolid#ddd">A demo-element with <code>id="highlight-demo"</code>, run the code above to observe it.</p>
215
215
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:
217
217
218
218
```js run
219
219
let demoElem =document.getElementById('highlight-demo');
220
220
221
-
//dynamically insert content with code snippets
221
+
//inserta contenido con fragmentos de código
222
222
demoElem.innerHTML=`A code snippet is below:
223
223
<preclass="language-javascript"><code> let hello = "world!"; </code></pre>
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.
232
232
233
-
## Additional methods
233
+
## Métodos adicionales
234
234
235
-
There's a method to stop observing the node:
235
+
Hay un método para detener la observación del nodo:
236
236
237
-
-`observer.disconnect()` -- stops the observation.
237
+
-`observer.disconnect()` -- detiene la observación.
238
238
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.
240
240
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ó.
242
242
243
-
These methods can be used together, like this:
243
+
Estos métodos pueden ser usados juntos, como esto:
244
244
245
245
```js
246
-
//we'd like to stop tracking changes
246
+
//quisiéramos detener el rastreo de cambios
247
247
observer.disconnect();
248
248
249
-
//handle unprocessed some mutations
249
+
//manejar algunas mutaciones que no fueron procesadas
250
250
let mutationRecords =observer.takeRecords();
251
251
...
252
252
```
253
253
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.
256
256
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.
258
258
```
259
259
260
-
## Summary
260
+
## Resumen
261
261
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.
263
263
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.
265
265
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