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
<divcontentEditableid="elem">Click and <b>edit</b>, please</div>
52
52
53
53
<script>
54
54
let observer =newMutationObserver(mutationRecords=> {
@@ -98,11 +98,11 @@ mutationRecords = [{
98
98
99
99
When `MutationObserver` is needed? Is there a scenario when such thing can be useful?
100
100
101
-
Sure, we can track something like `contentEditable` and create "undo/redo" stack, but here's an example where`MutationObserver` is good from architectural standpoint.
101
+
We can track something like `contentEditable` and implement "undo/redo" functionality (record mutations and rollback/redo them on demand). There are also cases when`MutationObserver` is good from architectural standpoint.
102
102
103
-
Let's say we're making a website about programming, like this one. Naturally, articles and other materials may contain source code snippets.
103
+
Let's say we're making a website about programming. Naturally, articles and other materials may contain source code snippets.
104
104
105
-
An HTML code snippet looks like this:
105
+
An HTML markup of a code snippet looks like this:
106
106
```html
107
107
...
108
108
<preclass="language-javascript"><code>
@@ -112,9 +112,9 @@ An HTML code snippet looks like this:
112
112
...
113
113
```
114
114
115
-
There's also a JavaScript highlighting library, e.g. [Prism.js](https://prismjs.com/). A call to `Prism.highlightElem(pre)` examines the contents of such `pre` elements and adds colored syntax highlighting, similar to what you in examples here, this page.
115
+
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.
116
116
117
-
Generally, when a page loads, e.g. at the bottom of the page, we can search for elements `pre[class*="language"]` and call `Prism.highlightElem` on them:
117
+
When to run that method? We can do it on `DOMContentLoaded` event, or at the bottom of the page. At that moment we have DOM ready, can search for elements `pre[class*="language"]` and call `Prism.highlightElem` on them:
...But imagine, we have many places where we load contents with code: articles, quizzes, forum posts. Do we need to put the highlighting call everywhere? Then we need to be careful, not to forget about it.
156
+
...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.
157
157
158
-
And what if we load the content into a third-party engine? 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.
158
+
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.
159
159
160
160
Luckily, there's another option.
161
161
@@ -176,15 +176,15 @@ let observer = new MutationObserver(mutations => {
176
176
// examine new nodes
177
177
178
178
for(let node ofmutation.addedNodes) {
179
-
// skip newly added text nodes
179
+
//we track only elements, skip other nodes (e.g. text nodes)
180
180
if (!(node instanceofHTMLElement)) continue;
181
181
182
182
// check the inserted element for being a code snippet
183
183
if (node.matches('pre[class*="language-"]')) {
184
184
Prism.highlightElement(node);
185
185
}
186
186
187
-
//search its subtree for code snippets
187
+
//maybe there's a code snippet somewhere in its subtree?
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.
219
219
220
+
## Additional methods
220
221
221
-
## Garbage collection
222
-
223
-
Observers use weak references to nodes internally. That is: if a node is removed from DOM, and becomes unreachable, then it becomes garbage collected, an observer doesn't prevent that.
224
-
225
-
Still, we can release observers any time:
222
+
There's a method to stop observing the node:
226
223
227
224
-`observer.disconnect()` -- stops the observation.
228
225
@@ -240,6 +237,10 @@ let mutationRecords = observer.takeRecords();
240
237
observer.disconnect();
241
238
```
242
239
240
+
## Garbage collection
241
+
242
+
Observers use weak references to nodes internally. That is: if a node is removed from DOM, and becomes unreachable, then it becomes garbage collected, an observer doesn't prevent that.
243
+
243
244
## Summary
244
245
245
246
`MutationObserver` can react on changes in DOM: attributes, added/removed elements, text content.
0 commit comments