Skip to content

Commit e4288e4

Browse files
committed
minor
1 parent 899a3ce commit e4288e4

File tree

1 file changed

+21
-20
lines changed

1 file changed

+21
-20
lines changed

10-misc/12-mutation-observer/article.md

Lines changed: 21 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,9 @@ Then after any changes, the `callback` is executed, with a list of [MutationReco
3535
[MutationRecord](https://dom.spec.whatwg.org/#mutationrecord) objects have properties:
3636

3737
- `type` -- mutation type, one of
38-
- `"attributes"` (attribute modified)
39-
- `"characterData"` (data modified)
40-
- `"childList"` (elements added/removed),
38+
- `"attributes"`: attribute modified
39+
- `"characterData"`: data modified
40+
- `"childList"`: elements added/removed,
4141
- `target` -- where the change occured: an element for "attributes", or text node for "characterData", or an element for a "childList" mutation,
4242
- `addedNodes/removedNodes` -- nodes that were added/removed,
4343
- `previousSibling/nextSibling` -- the previous and next sibling to added/removed nodes,
@@ -48,7 +48,7 @@ Then after any changes, the `callback` is executed, with a list of [MutationReco
4848
For example, here's a `<div>` with `contentEditable` attribute. That attribute allows us to focus on it and edit.
4949

5050
```html run
51-
<div contentEditable id="elem">Edit <b>me</b>, please</div>
51+
<div contentEditable id="elem">Click and <b>edit</b>, please</div>
5252

5353
<script>
5454
let observer = new MutationObserver(mutationRecords => {
@@ -98,11 +98,11 @@ mutationRecords = [{
9898

9999
When `MutationObserver` is needed? Is there a scenario when such thing can be useful?
100100

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.
102102

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.
104104

105-
An HTML code snippet looks like this:
105+
An HTML markup of a code snippet looks like this:
106106
```html
107107
...
108108
<pre class="language-javascript"><code>
@@ -112,9 +112,9 @@ An HTML code snippet looks like this:
112112
...
113113
```
114114

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.
116116

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:
118118

119119
```js
120120
// highlight all code snippets on the page
@@ -139,7 +139,7 @@ articleElem.innerHTML = article;
139139

140140
The new `article` HTML may contain code snippets. We need to call `Prism.highlightElem` on them, otherwise they won't get highlighted.
141141

142-
**Who's responsibility is to call `Prism.highlightElem` for a dynamically loaded article?**
142+
**Where and when to call `Prism.highlightElem` for a dynamically loaded article?**
143143

144144
We could append that call to the code that loads an article, like this:
145145

@@ -153,9 +153,9 @@ snippets.forEach(Prism.highlightElem);
153153
*/!*
154154
```
155155

156-
...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.
157157

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.
159159

160160
Luckily, there's another option.
161161

@@ -176,15 +176,15 @@ let observer = new MutationObserver(mutations => {
176176
// examine new nodes
177177

178178
for(let node of mutation.addedNodes) {
179-
// skip newly added text nodes
179+
// we track only elements, skip other nodes (e.g. text nodes)
180180
if (!(node instanceof HTMLElement)) continue;
181181

182182
// check the inserted element for being a code snippet
183183
if (node.matches('pre[class*="language-"]')) {
184184
Prism.highlightElement(node);
185185
}
186186

187-
// search its subtree for code snippets
187+
// maybe there's a code snippet somewhere in its subtree?
188188
for(let elem of node.querySelectorAll('pre[class*="language-"]')) {
189189
Prism.highlightElement(elem);
190190
}
@@ -200,7 +200,7 @@ observer.observe(demoElem, {childList: true, subtree: true});
200200

201201
<p id="highlight-demo" style="border: 1px solid #ddd">Demo element with <code>id="highlight-demo"</code>, obverved by the example above.</p>
202202

203-
The code below populates `innerHTML`. If you've run the code above, snippets will get highlighted:
203+
The code below populates `innerHTML`. Please run the code above first, it will watch and highlight the new content:
204204

205205
```js run
206206
let demoElem = document.getElementById('highlight-demo');
@@ -217,12 +217,9 @@ demoElem.innerHTML = `A code snippet is below:
217217

218218
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.
219219

220+
## Additional methods
220221

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:
226223

227224
- `observer.disconnect()` -- stops the observation.
228225

@@ -240,6 +237,10 @@ let mutationRecords = observer.takeRecords();
240237
observer.disconnect();
241238
```
242239

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+
243244
## Summary
244245

245246
`MutationObserver` can react on changes in DOM: attributes, added/removed elements, text content.

0 commit comments

Comments
 (0)