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; }
Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.
Alternative Proxies: