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 3cf6f5397..6801eb957 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 +# Mutation Observer (спостерігач за мутаціями) -`MutationObserver` is a built-in object that observes a DOM element and fires a callback when it detects a change. +`MutationObserver` -- це вбудований об'єкт, який спостерігає за елементом DOM і викликає функцію зворотного виклику кожного разу, коли він помічає зміну. -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. +Спочатку ми поглянемо на синтаксис, а потім дослідимо реальний приклад, щоб побачити, де така річ може знадобитися. -## Syntax +## Синтаксис -`MutationObserver` is easy to use. +`MutationObserver` -- простий у використанні. -First, we create an observer with a callback-function: +Спершу ми створюємо спостерігача із функцією зворотного виклику: ```js let observer = new MutationObserver(callback); ``` -And then attach it to a DOM node: +А потім прикріплюємо його до вузла 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` -- це об'єкт із булевими опціями, які вказують "на якого роду зміни слід реагувати": +- `childList` -- зміни в безпосередніх нащадках вузла `node`, +- `subtree` -- у всіх нащадках вузла `node`, +- `attributes` -- атрибути вузла `node`, +- `attributeFilter` -- масив назв атрибутів, щоб спостерігати лише за певними з них. +- `characterData` -- чи спостерігати за змінами в `node.data` (текстовий вміст), -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). +Декілька інших опцій: +- `attributeOldValue` -- якщо вказана як `true` -- до функції зворотного виклику буде передано і нове, і старе значення атрибута (дивіться нижче), а інакше передаватиме лише нове значення (потребує вказаної опції `attributes`), +- `characterDataOldValue` -- якщо дорівнює `true` -- до функції зворотного виклику буде передано і нове, і старе значення `node.data` (дивіться нижче), а інакше передаватиме лише нове значення (потребує вказаної опції `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. +Далі після будь-яких змін виконується `callback`: зміни передаються першим аргументом у вигляді списку об'єктів типу [MutationRecord](https://dom.spec.whatwg.org/#mutationrecord), а другим аргументом передається сам спостерігач. -[MutationRecord](https://dom.spec.whatwg.org/#mutationrecord) objects have properties: +Об'єкти [MutationRecord](https://dom.spec.whatwg.org/#mutationrecord) містять такі властивості: -- `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` -- тип мутації, одне з: + - `"attributes"`: змінився атрибут + - `"characterData"`: змінилися дані, використовуються для текстових вузлів, + - `"childList"`: додані/прибрані дочірні елементи, +- `target` -- де саме відбулася зміна: для `"attributes"` це елемент, або текстовий вузол у випадку `"characterData"`, або елемент для мутації типу `"childList"`, +- `addedNodes/removedNodes` -- вузли, які було додано/прибрано, +- `previousSibling/nextSibling` -- відповідно попередній та наступний елемент відносно доданих/прибраних вузлів, +- `attributeName/attributeNamespace` -- ім'я/простір імен (для XML) зміненого атрибута, +- `oldValue` -- попереднє значення, лише для змін в атрибуті або тексті, за умови, що встановлено відповідний параметр `attributeOldValue`/`characterDataOldValue`. -For example, here's a `
- // here's the code
+ // Тут знаходиться код
let hello = "world";
...
```
-For better readability and at the same time, to beautify it, we'll be using a JavaScript syntax highlighting library on our site, like [Prism.js](https://prismjs.com/). To get syntax highlighting for above snippet in Prism, `Prism.highlightElem(pre)` is called, which examines the contents of such `pre` elements and adds special tags and styles for colored syntax highlighting into those elements, similar to what you see in examples here, on this page.
+Для кращої прочитності і, в той же час для естетичності, ми будемо використовувати JavaScript-бібліотеку для підсвітки синтаксису на нашому вебсайті, на кшталт [Prism.js](https://prismjs.com/). Для отримання синтаксичної підсвітки за допомогою Prism для наведеного вище фрагмента, викликається `Prism.highlightElem(pre)`, який перевіряє вміст таких елементів `pre`, та додає в них особливі теги і стилі для кольорової підсвітки синтаксису, подібно до того, що ви можете побачити в прикладах тут, на цій сторінці.
-When exactly should we run that highlighting method? Well, we can do it on `DOMContentLoaded` event, or put the script at the bottom of the page. The moment our DOM is ready, we can search for elements `pre[class*="language"]` and call `Prism.highlightElem` on them:
+Коли саме нам слід запускати такий метод для додавання підсвітки? Що ж, ми можемо це робити на подію `DOMContentLoaded`, або поставити скрипт внизу сторінки. Як тільки наша DOM готова, ми можемо виконати пошук елементів `pre[class*="language"]` та викликати на них `Prism.highlightElem`:
```js
-// highlight all code snippets on the page
+// підсвітити всі фрагменти коду на сторінці
document.querySelectorAll('pre[class*="language"]').forEach(Prism.highlightElem);
```
-Everything's simple so far, right? We find code snippets in HTML and highlight them.
+Досі все просто, правда? Ми шукаємо фрагменти коду всередині HTML і розфарбовуємо їх.
-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:
+Тепер продовжимо. Скажімо, ми збираємося динамічно забирати матеріали зі сервера. Ми вивчимо способи це зробити [далі в посібнику](info:fetch). Що важливо наразі -- це те, що ми забираємо статтю з HTML зі сервера, і показуємо її на вимогу:
```js
-let article = /* fetch new content from server */
+let article = /* отримаємо новий вміст із сервера */
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.
+HTML-вміст нової статті `article` може містити фрагменти коду. Нам потрібно викликати на них `Prism.highlightElem`, інакше підсвітки на них не буде.
-**Where and when to call `Prism.highlightElem` for a dynamically loaded article?**
+**Коли і де нам слід викликати `Prism.highlightElem` для динамічно завантаженої статті ?**
-We could append that call to the code that loads an article, like this:
+Ми могли б прикріпити цей виклик до коду, який завантажує статтю, ось так:
```js
-let article = /* fetch new content from server */
+let article = /* отримаємо новий вміст із сервера */
articleElem.innerHTML = article;
*!*
@@ -162,38 +162,38 @@ snippets.forEach(Prism.highlightElem);
*/!*
```
-...But, imagine if we have many places in the code where we load our content - articles, quizzes, forum posts, etc. Do we need to put the highlighting call everywhere, to highlight the code in content after loading? That's not very convenient.
+...Але, уявімо, що у нас є багато місць в коді, де ми завантажуємо наш вміст: статті, опитники, форумні дописи тощо. Чи повинні ми всюди вставляти виклик підсвітки, аби виконати підсвітку синтаксису коду всередині вмісту після завантаження? Це не надто зручно.
-And what if the content is loaded by a third-party module? For example, we have a forum written by someone else, that loads content dynamically, and we'd like to add syntax highlighting to it. No one likes patching third-party scripts.
+І що, якщо вміст було завантажено стороннім модулем? Наприклад, якщо ми маємо форум, написаний кимось іншим, який динамічно завантажує вміст, і нам би хотілося додати до нього підсвітку синтаксису. Ніхто не любить правити сторонні скрипти.
-Luckily, there's another option.
+На щастя, є інший спосіб.
-We can use `MutationObserver` to automatically detect when code snippets are inserted into the page and highlight them.
+Ми можемо використати `MutationObserver` для автоматичного виявлення моментів, коли фрагменти коду вставляються у сторінку, і виконання підсвітки на них.
-So we'll handle the highlighting functionality in one place, relieving us from the need to integrate it.
+Отже, ми виконаємо функціональність підсвітки в одному місці, позбавивши нас клопоту з її інтеграцією.
-### Dynamic highlight demo
+### Демонстрація динамічної підсвітки
-Here's the working example.
+Ось робочий приклад.
-If you run this code, it starts observing the element below and highlighting any code snippets that appear there:
+Якщо ви запустите цей код, він почне спостерігати за наведеним нижче елементом, і підсвічувати будь який фрагмент коду, який з'являтиметься там:
```js run
let observer = new MutationObserver(mutations => {
for(let mutation of mutations) {
- // examine new nodes, is there anything to highlight?
+ // перевіряємо вузли, чи є тут щось для розфарбування?
for(let node of mutation.addedNodes) {
- // we track only elements, skip other nodes (e.g. text nodes)
+ // ми стежимо лише за елементами, пропустимо інші вузли (наприклад текстові вузли)
if (!(node instanceof HTMLElement)) continue;
- // check the inserted element for being a code snippet
+ // перевіримо, чи вставлений елемент є фрагментом коду
if (node.matches('pre[class*="language-"]')) {
Prism.highlightElement(node);
}
- // or maybe there's a code snippet somewhere in its subtree?
+ // чи можливо фрагмент коду десь в глибині його піддерева?
for(let elem of node.querySelectorAll('pre[class*="language-"]')) {
Prism.highlightElement(elem);
}
@@ -207,67 +207,67 @@ 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`.
+Тут, нижче наведено HTML-елемент і JavaScript, що динамічно заповнюють його за допомогою `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.
+Будь ласка, запускайте попередній код (наведено вище, для спостереження за елементом), а потім код, наведений нижче. Ви помітите, як `MutationObserver` виявляє і виконує підсвітку у фрагменті.
-A demo-element with id="highlight-demo"
, run the code above to observe it.
Демо-елемент із id="highlight-demo"
, запустіть наведений вище код для спостереження за ним.
let hello = "world!";
- .class { margin: 5px; }