# Matreshka.js ```html ``` ## Навіщо Matreshka Для сторінок, у яких HTML уже готовий: серверний рендеринг, віджети, старі проєкти, сторінка з одного HTML-файлу. Підключіть один тег ` ``` Цей самий файл віддає і цей сайт: [/matreshka.min.js](https://matreshka.js.org/matreshka.min.js). ### ES-модуль з CDN Без збирача можна імпортувати `matreshka.min.mjs` — той самий код одним ES-модулем: усі іменовані експорти `matreshka`, а також `initRouter`, `Router` і `parseForm`. Це один запит, і важить він стільки ж, скільки файл для тегу script. ```html ``` ## Модулі Кожна статична функція або клас — іменований експорт головного модуля. ```js import { MatreshkaArray, bindNode, binders } from 'matreshka'; const { prop } = binders; ``` ## Рівні важливості Документація розбита на три рівні важливості. ### Перший рівень — найважливіше Вивчивши найважливіші властивості і методи, ви можете сміливо приступати до роботи. Почніть з [`Matreshka#bindNode`](https://matreshka.js.org/ua/#Matreshka-bindNode), [`Matreshka#calc`](https://matreshka.js.org/ua/#Matreshka-calc), [`Matreshka#on`](https://matreshka.js.org/ua/#Matreshka-on), [`Matreshka.Object`](https://matreshka.js.org/ua/#Matreshka.Object) і [`Matreshka.Array`](https://matreshka.js.org/ua/#Matreshka.Array). ### Другий рівень — рекомендується вивчити Після того, як ви освоїли необхідні для швидкого старту можливості, можете ознайомитися з іншими, менш важливими (але все ще важливими) властивостями і методами фреймворку. ### Третій рівень — інші методи і властивості Для того, щоб не лякати новачків речами, які використовуються відносно рідко, інші методи і властивості за замовчуванням приховані. Якщо ви хочете знати про фреймворк все, без винятку, оберіть на перемикачі зліва, в меню. **Увага**, якщо ви перейдете по посиланню до методу або властивості третього рівня важливості, то третій рівень увімкнеться автоматично. Далі: [Hello World та інші приклади](https://matreshka.js.org/ua/#examples). --- # Як користуватися документацією ## Рівні важливості Документація розбита на три рівні важливості. ### Перший рівень - найважливіше Вивчивши найважливіші властивості і методи, ви можете сміливо приступати до роботи. З класами, методами і властивостями, поміченими значком необхідно розібратися в першу чергу. ### Другий рівень - рекомендується вивчити Після того, як ви освоїли необхідні для швидкого старту можливості, можете ознайомитися з іншими, менш важливими (але все ще важливими) властивостями і методами фреймворку. ### Третій рівень - інші методи і властивості Для того, щоб не лякати новачків речами, які використовуються відносно рідко, інші методи і властивості за замовчуванням приховані. Якщо ви хочете знати про фреймворк все, без винятку, оберіть на перемикачі зліва, в меню. **Увага**, якщо ви перейдете по посиланню до методу або властивості третього рівня важливості, то третій рівень увімкнеться автоматично. ## Помилки в документації У кінці кожної статті документації є посилання на код цієї статті. Виправити помилку можна прямо в редакторі на Github. > Документація розроблена з використанням GitHub Flavored Markdown. ## Модулі Фреймворк - один пакет з трьома точками входу. ```js import Matreshka from 'matreshka'; import { initRouter } from 'matreshka/router'; import { parseForm } from 'matreshka/parse-form'; ``` --- # Приклади ## Hello World Написати перший додаток за допомогою фреймворка Matreshka.js дуже просто. **1\.** Створіть HTML файл з наступним змістом ```html Мій перший додаток на базі Matreshka.js
``` **2\.** Створіть клас у файлі **js/app.js** ```js // присвоюємо html байндер змінній з коротким ім'ям const htmlBinder = Matreshka.binders.html; // створюємо клас, який успадковується від Matreshka class Application extends Matreshka { constructor() { super(); // пов'язуємо властивість x і текстове поле this.bindNode('x', '.my-input'); // пов'язуємо властивість x і блок з класом my-output this.bindNode('x', '.my-output', htmlBinder()); // слухаємо зміни властивості x this.on('change:x', () => console.log(`x змінений на "${this.x}"`)); } } const app = new Application(); ``` **3\.** Це все! Тепер можете відкрити консоль розробника (клавіша F12) і написати: ```js app.x = 'Hello World!'; ``` [Запустити приклад](https://matreshka.js.org/examples/hello-world/). ### Посилання - [Клас `Matreshka`](https://matreshka.js.org/ua/#Matreshka) - [Метод `Matreshka#bindNode`](https://matreshka.js.org/ua/#Matreshka-bindNode) - [Метод `Matreshka#on`](https://matreshka.js.org/ua/#Matreshka-on) ## Живі приклади Кожен приклад працює на цьому сайті; його код лежить у [папці examples](https://github.com/finom/matreshka/tree/main/examples) репозиторію. 1. [TodoMVC](https://matreshka.js.org/examples/todomvc/) – список справ. ([Код з анотаціями](https://matreshka.js.org/examples/todomvc/docs/todomvc/js/app.html), [код](https://github.com/finom/matreshka/tree/main/examples/todomvc)) 2. [TreeView](https://matreshka.js.org/examples/treeview/) – деревовидний список необмеженої вкладеності. ([Код](https://github.com/finom/matreshka/tree/main/examples/treeview)) 3. [Markdown editor](https://matreshka.js.org/examples/markdown-editor/) – найпростіший редактор Markdown. ([Код](https://github.com/finom/matreshka/tree/main/examples/markdown-editor)) 4. [Contact List](https://matreshka.js.org/examples/contact-list/) – дозволяє додавати, видаляти, сортувати, змінювати і шукати контакти. ([Код](https://github.com/finom/matreshka/tree/main/examples/contact-list)) 5. [Форма входу](https://matreshka.js.org/examples/matreshka-object/) на `Matreshka.Object`. ([Посібник](https://github.com/finom/matreshka/tree/main/examples/matreshka-object), англійською) 6. [Таблиця користувачів](https://matreshka.js.org/examples/matreshka-array/) на `Matreshka.Array`. ([Посібник](https://github.com/finom/matreshka/tree/main/examples/matreshka-array), англійською) 7. [Демо matreshka/router](https://matreshka.js.org/examples/router/#!/foo/bar/baz/) – властивості, зв’язані з частинами URL. ([Код](https://github.com/finom/matreshka/tree/main/examples/router)) 8. [Демо matreshka/parse-form](https://matreshka.js.org/examples/parse-form/) – поля форми, зв’язані з властивостями за іменами. ([Код](https://github.com/finom/matreshka/tree/main/examples/parse-form)) 9. [Форма реєстрації](https://matreshka.js.org/examples/signup-form/) – форма, відрендерена на сервері: email перевіряється під час введення, смужка показує надійність пароля. ([Код](https://github.com/finom/matreshka/tree/main/examples/signup-form)) 10. [Таблиця товарів](https://matreshka.js.org/examples/product-table/) – пошук, сортування і фільтр по рядках, які рендерить `Matreshka.Array`. ([Код](https://github.com/finom/matreshka/tree/main/examples/product-table)) 11. [Віджет ціни](https://matreshka.js.org/examples/price-widget/) – віджет на чужій сторінці, який `bindSandbox` тримає всередині його кореня. ([Код](https://github.com/finom/matreshka/tree/main/examples/price-widget)) ## Посібники - [Події](https://github.com/finom/matreshka/tree/main/examples/events) (англійською) – стаття про механізм подій, на якому працюють `calc`, `bindNode`, `instantiate` та інші методи. - [`Matreshka.Object`](https://github.com/finom/matreshka/tree/main/examples/matreshka-object) і [`Matreshka.Array`](https://github.com/finom/matreshka/tree/main/examples/matreshka-array) крок за кроком (англійською), з живими прикладами вище. --- # Matreshka **Клас** **Імпорт:** ```js import Matreshka from 'matreshka'; ``` Клас `` Matreshka`` - це ядро фреймворка Matreshka.js, від якого успадковуються [`Matreshka.Array`](https://matreshka.js.org/ua/#Matreshka.Array), [`Matreshka.Object`](https://matreshka.js.org/ua/#Matreshka.Object) і кожен клас створюваного додатка. Він містить основний функціонал фреймворка: [медіатори](https://matreshka.js.org/ua/#Matreshka-mediate), [залежності](https://matreshka.js.org/ua/#Matreshka-calc), [прив'язки до DOM](https://matreshka.js.org/ua/#Matreshka-bindNode), [механізм подій](https://matreshka.js.org/ua/#Matreshka-on) тощо. Як правило, цей клас, (як і [`Matreshka.Array`](https://matreshka.js.org/ua/#Matreshka.Array) і [`Matreshka.Object`](https://matreshka.js.org/ua/#Matreshka.Object)), не використовуються безпосередньо. Замість цього, від нього успадковуються класи, створювані розробником. ## Посилання - [`Matreshka.Class`](https://matreshka.js.org/ua/#Matreshka.Class) ## Приклади **Створення екземпляру** ```js const matreshka = new Matreshka(); ``` **Спадкування** ```js class MyClass extends Matreshka { constructor() { super().sayHello(); } sayHello() { alert("Hello World!"); } } ``` **Спадкування за допомогою функції [`Matreshka.Class`](https://matreshka.js.org/ua/#Matreshka.Class)** ```js const MyClass = Matreshka.Class({ 'extends': Matreshka, constructor() { this.sayHello(); }, sayHello() { alert("Hello World!"); } }); ``` ## Методи і властивості - [`bindNode`](https://matreshka.js.org/ua/#Matreshka-bindNode) – Пов'язує властивість об'єкта з HTML елементом - [`bindOptionalNode`](https://matreshka.js.org/ua/#Matreshka-bindOptionalNode) – Працює в точності так само, як і [`Matreshka#bindNode`](https://matreshka.js.org/ua/#Matreshka-bindNode) але не кидає виняток, якщо аргумент ``node`` - порожній масив, ``undefined`` або не існує - [`bindSandbox`](https://matreshka.js.org/ua/#Matreshka-bindSandbox) – Прив'язує пісочницю - [`calc`](https://matreshka.js.org/ua/#Matreshka-calc) – Створює залежність значення однієї властивості від значень інших - [`instantiate`](https://matreshka.js.org/ua/#Matreshka-instantiate) – Створює фіксований екземпляр класу - [`isMatreshka`](https://matreshka.js.org/ua/#Matreshka-isMatreshka) – ``isMatreshka`` завжди дорівнює ``true`` для экземплярів [`Matreshka`](https://matreshka.js.org/ua/#Matreshka) - [`mediate`](https://matreshka.js.org/ua/#Matreshka-mediate) – Трансформує значення властивості при його зміні - [`$nodes`](https://matreshka.js.org/ua/#Matreshka-$nodes) – Об'єкт містить масиви прив'язаних елементів для швидкого доступу. - [`nodes`](https://matreshka.js.org/ua/#Matreshka-nodes) – Об'єкт містить прив'язані елементи для швидкого доступу, у вигляді окремих DOM вузлів. - [`off`](https://matreshka.js.org/ua/#Matreshka-off) – Видаляє обробник події - [`on`](https://matreshka.js.org/ua/#Matreshka-on) – Додає обробник події - [`onDebounce`](https://matreshka.js.org/ua/#Matreshka-onDebounce) – Додає обробник події, що викликається лише одного разу за певний проміжок часу - [`once`](https://matreshka.js.org/ua/#Matreshka-once) – Додає обробник подій, який може бути викликаний один раз - [`parseBindings`](https://matreshka.js.org/ua/#Matreshka-parseBindings) – Парсить DOM дерево, оголошуючи прив'язки властивостей, взятих в подвійні фігурні дужки. - [`remove`](https://matreshka.js.org/ua/#Matreshka-remove) – Видаляє властивість - [`select`](https://matreshka.js.org/ua/#Matreshka-select) – Повертає елемент з пісочниці, відповідний селектору - [`selectAll`](https://matreshka.js.org/ua/#Matreshka-selectAll) – Повертає елементи з пісочниці, відповідні селектору - [`set`](https://matreshka.js.org/ua/#Matreshka-set) – Встановлює значення властивості, дозволяючи передати об'єкт події в якості третьої аргументу - [`trigger`](https://matreshka.js.org/ua/#Matreshka-trigger) – Генерує подію - [`unbindNode`](https://matreshka.js.org/ua/#Matreshka-unbindNode) – Розриває зв'язок між властивістю і HTML елементом ## Статичні методи - [`Class`](https://matreshka.js.org/ua/#Matreshka.Class) – Реалізація класів, заснована на прототипному спадкуванні - [`bindNode`](https://matreshka.js.org/ua/#Matreshka.bindNode) – Пов'язує властивість об'єкта з HTML елементом - [`bindOptionalNode`](https://matreshka.js.org/ua/#Matreshka.bindOptionalNode) – Пов'язує елемент із властивістю, але не кидає виняток, якщо аргумент node - порожній масив, ``undefined`` або не існує - [`bindSandbox`](https://matreshka.js.org/ua/#Matreshka.bindSandbox) – Пов'язує властивість ``sandbox`` з елементом і одв'язує попередній елемент, якщо такий існує - [`calc`](https://matreshka.js.org/ua/#Matreshka.calc) – Створює залежність значення одної властивості від значень інших - [`chain`](https://matreshka.js.org/ua/#Matreshka.chain) – Дозволяє викликати універсальні методи ланцюгом - [`defaultBinders`](https://matreshka.js.org/ua/#Matreshka.defaultBinders) – Масив функцій, які повертають відповідний Байндер або ``undefined`` - [`instantiate`](https://matreshka.js.org/ua/#Matreshka.instantiate) – Створює фіксований екземпляр класу - [`initRouter`](https://matreshka.js.org/ua/#Matreshka.initRouter) – Вмикає двостороннє зв'язування даних між властивостями і частинами URL - [`lookForBinder`](https://matreshka.js.org/ua/#Matreshka.lookForBinder) - [`mediate`](https://matreshka.js.org/ua/#Matreshka.mediate) – Трансформує значення властивості при його зміні - [`off`](https://matreshka.js.org/ua/#Matreshka.off) – Видаляє обробник події - [`on`](https://matreshka.js.org/ua/#Matreshka.on) – Додає обробник події - [`onDebounce`](https://matreshka.js.org/ua/#Matreshka.onDebounce) – Додатє обробник події, що викликається лише однин раз за певний проміжок часу - [`once`](https://matreshka.js.org/ua/#Matreshka.once) – Додає обробник події, який може бути викликаний лише один раз - [`parseBindings`](https://matreshka.js.org/ua/#Matreshka.parseBindings) – Парсить DOM дерево, оголошуючи прив'язки властивостей, взятих в подвійні фігурні дужки - [`parseForm`](https://matreshka.js.org/ua/#Matreshka.parseForm) – Прив'язує іменовані поля HTML форми до відповідних властивостей - [`parserBrackets`](https://matreshka.js.org/ua/#Matreshka.parserBrackets) – Містить дужки для [парсера](https://matreshka.js.org/ua/#Matreshka-parseBindings) - [`remove`](https://matreshka.js.org/ua/#Matreshka.remove) – Видаляє властивість - [`select`](https://matreshka.js.org/ua/#Matreshka.select) – Повертає елемент з пісочниці, відповідний селектору - [`selectAll`](https://matreshka.js.org/ua/#Matreshka.selectAll) – Повертає елементи з пісочниці, відповідні селектору - [`set`](https://matreshka.js.org/ua/#Matreshka.set) – Встановлює значення властивості, дозволяючи передати об'єкт події в якості третьої аргументу - [`toMatreshka`](https://matreshka.js.org/ua/#Matreshka.toMatreshka) – Функція, яка конвертує довільну структуру об'єктів і масивів в екземпляри [`Matreshka.Object`](https://matreshka.js.org/ua/#Matreshka.Object) та [`Matreshka.Array`](https://matreshka.js.org/ua/#Matreshka.Array) - [`trigger`](https://matreshka.js.org/ua/#Matreshka.trigger) – Генерує подію - [`unbindNode`](https://matreshka.js.org/ua/#Matreshka.unbindNode) – Розриває зв'язок між властивістю і HTML елементом --- # Matreshka#bindNode **Метод** ```js Matreshka#bindNode(key, node, [binder], [eventOptions]) → object ``` Пов'язує властивість об'єкта з HTML елементом ``bindNode`` - це єдиний метод класу [`Matreshka`](https://matreshka.js.org/ua/#Matreshka), який відповідає за зміни DOM. Він створює міст між значенням властивості і станом HTML елемента на сторінці: від простого інпут до складного віджета (складність елементів не обмежена). Після зв'язування властивості екземпляра і HTML елемента не потрібно більше стежити за синхронізацією даних та виду. > Зверніть увагу, що у метода є [статичний аналог](https://matreshka.js.org/ua/#Matreshka.bindNode), який працює в точності так само, але приймає будь-який об'єкт в якості першого аргументу, зсовуючи інші аргументи вправо. ```js import { bindNode } from 'matreshka'; const object = {}; bindNode(object, key, node, binder, eventOptions); // замість this.bindNode(key, node, binder, eventOptions); ``` Для двостороннього зв'язування елемента і значення властивості, в метод передаються три аргументи: **ім'я властивості**, **HTML елемент** і **правило прив'язки** (байндер, біндер, binder, прівязчік). Байндер, в свою чергу, є звичайним об'єктом і може мати наступні властивості: ``on``, ``getValue``, ``setValue``, ``initialize``, ``destroy`` (докладніше див. [`binder`](https://matreshka.js.org/ua/#type-binder)). Всі п'ять властивостей опційні. Це дозволяє також оголошувати і односторонні прив'язки. > Метод ``bindNode`` підтримує прив'язки "багато до багатьох". З одною властивістю можна зв'язати кілька елементів, а з одним елементом можна зв'язати кілька властивостей, в тому числі і від різних екземплярів різних класів. ```js this.bindNode('myKey', '.my-element', { on: 'click', getValue () {...}, setValue () {...} }); ``` Наприклад, ви хочете зв'язати властивість об'єкта з елементом ``input[type="checkbox"]``: ```js this.bindNode('myKey', '.my-checkbox', { // Коли змінюється стан елемента? // - За подією 'click' on: 'click', // Як витягти стан елемента? // - Повернути значення 'checked' getValue() { return this.checked; }, // Як встановити стан елемента? // - Встановити значення 'checked' setValue(v) { this.checked = !! v; } }); ``` Після оголошення прив'язки можна встановлювати значення властивості об'єкта самим звичним способом, а елемент змінить свій стан автоматично. При кліці на чекбокс, значення властивості теж зміниться на відповідне. ```js // Встановлює checked = true this.myKey = true; ``` Більш складний приклад: зв'язування властивості об'єкта з віджетом jQuery UI ```html
``` ```js this.bindNode('myKey', '.my-slider', { // Коли змінювати стан елемента? // - За подією 'slide' on: 'slide', // Як витягти стан елемента? // - Повернути значення віджета 'value' getValue() { return $(this).slider('option', 'value'); }, // Як встановити стан елемента? // - Встановити значення 'value' setValue(v) { $(this).slider('option', 'value', v); }, // Як ініціалізувати віджет? // Зробити це можна будь-яким способом, // але initialize надає трохи синтаксичного цукру initialize() { $(this).slider({ min: 0, max: 100 }); } }); ``` ```js // Встановить значення слайдера 42 this.myKey = 42; ``` Виглядає просто, але у вас, швидше за все, винекне питанням: "Як зробити так, щоб мені не довелося кожен раз прописувати ці правила?". Дійсно, на сторінці може бути дуже багато однотипних елементів: текстових полів, полів з специфікації HTML5, можуть бути і сторонні віджети (про що говорить приклад вище). Як видно з документації до аргументів методу ``bindNode``, третій аргумент не обов'язковий. Цю проблему вирішує масив [`Matreshka.defaultBinders`](https://matreshka.js.org/ua/#Matreshka.defaultBinders), який містить функції, що перевіряють HTML елемент на відповідність заданим правилам і повертають відповідний Байндер або ``undefined``. З'являється можливість багаторазово скоротити код, виносячи правила прив'язки в окрему частину вашого коду, а для прив'язки використовувати синтаксис без третього аргументу: ```js this.bindNode('myKey', '.my-element'); ``` Як це зробити? Потрібно додати функцію, яка перевіряє ваш елемент на відповідність деяким правилам в початок масиву [`Matreshka.defaultBinders`](https://matreshka.js.org/ua/#Matreshka.defaultBinders). ```js const checkboxBinder = () => { return { on: 'click', getValue () { return this.checked; }, setValue (v) { this.checked = !! v; } } }; // Метод unshift додає функцію // у початок масиву Matreshka.defaultBinders Matreshka.defaultBinders.unshift(node => { // Перевіряємо, чи це чекбокс if (node.tagName === 'INPUT' && node.type === 'checkbox') { // Якщо перевірка пройдена, повертаємо новий байндер return checkboxBinder(); } }); ``` ```js this.bindNode('myKey', '.my-checkbox'); this.myKey = true; ``` Що робити, якщо вам потрібно передати аргументи для ініціалізації якогось плагіна або віджету? Можна вручну викликати функцію, яка повертає Байндер. ```js const uiSlider = (min, max) => { return { on: 'slide', getValue() { return $(this).slider('option', 'value'); }, setValue(v) { $(this).slider('option', 'value', v); }, initialize() { $(this).slider({ min: min, max: max }); } } }; this.bindNode('myKey1', '.my-slider1', uiSlider(0, 100)); this.bindNode('myKey2', '.my-slider2', uiSlider(1, 1000)); this.myKey1 = 42; this.myKey2 = 999; ``` Для глобального доступу до байндера, можна розширити [`Matreshka.binders`](https://matreshka.js.org/ua/#Matreshka.binders). ```js Matreshka.binders.uiSlider = uiSlider; // ... this.bindNode('myKey1', '.my-slider1', Matreshka.binders.uiSlider(0, 100)); this.bindNode('myKey2', '.my-slider2', Matreshka.binders.uiSlider(1, 1000)); ``` [`Matreshka.defaultBinders`](https://matreshka.js.org/ua/#Matreshka.defaultBinders) з коробки містить підтримку **всіх без винятку** HTML елементів форм: ``select`` (включаючи ``multiple``), ``textarea``, ``output``, ``input`` (в тому числі і всі типи із специфікації HTML5: ``text``, ``checkbox``, ``radio``, ``range``, ``number``, ``date``, ``search``, ``time``, ``datetime``, ``datetime-local``, ``color`` та інших). Це означає, що для стандартних елементів вказувати Байндер не обов'язково. ```html ``` ```js this.bindNode('myColor', '.my-color-input'); this.myColor = '#66bb6a'; ``` Після прив'язки, вам доступний новий нестандартний CSS селектор ``:bound(KEY)``. ```js this.bindNode('myKey', '.my-element'); // Знайде елемент .my-inner-element який є в '.my-element' this.bindNode('myAnotherKey', ':bound(myKey) .my-inner-element'); ``` І розширюється синтаксис можливих імен подій: ```js this.bindNode('myKey', '.my-element'); // Відловити клік на елементі .my-element this.on('click::myKey', () => {...}); // Відловити клік на елементі .my-element .my-inner-element this.on('click::myKey(.my-inner-element)', () => {...}); ``` > Якщо елемент не знайдений, кидається виняток ``Binding error: node is missing for key "KEY"``. Для того, щоб уникнути помилки використовуйте метод [`Matreshka#bindOptionalNode`](https://matreshka.js.org/ua/#Matreshka-bindOptionalNode) #### Створення пісочниці [`Matreshka#bindNode`](https://matreshka.js.org/ua/#Matreshka-bindNode) вміє асоціювати екземпляр класу з "головним" HTML елементом, створюючи так звану **пісочницю**. Це потрібно для того, щоб обмежити вплив об'єкта одним HTML елементом. Для прив'язки пісочниці використовується спеціальна властивість ``sandbox``. ```html
``` ```js this.bindNode('sandbox', '.my-sandbox'); ``` Визначення пісочниці додає безліч зручностей програмісту. наприклад: + Дозволяє використовувати методи [`Matreshka#select`](https://matreshka.js.org/ua/#Matreshka-select) і [`Matreshka#$`](https://matreshka.js.org/ua/#Matreshka-selectAll) + Додає можливість використовувати селектор ``:sandbox`` в методах [`Matreshka#bindNode`](https://matreshka.js.org/ua/#Matreshka-bindNode), [`Matreshka#select`](https://matreshka.js.org/ua/#Matreshka-select), [`Matreshka#$`](https://matreshka.js.org/ua/#Matreshka-selectAll) + Додає синтаксичний цукор для делегованих DOM подій в методі [`Matreshka#on`](https://matreshka.js.org/ua/#Matreshka-on) > Слід мати на увазі, що тільки один HTML елемент може бути пов'язаний з властивістю ``sandbox``, інакше кидається помилка. Для оголошення пісочниці можна скористатися методом [`Matreshka#bindSandbox`](https://matreshka.js.org/ua/#Matreshka-bindSandbox). Перед тим, як оголосити байндінг, метод одв'язує попередню пісочницю. ```js // Оголошуємо пісочницю this.bindNode('sandbox', '.my-sandbox'); // .my-element шукається в пісочниці this.bindNode('myKey', ':sandbox .my-element'); // Для делегованих подій всередині пісочниці не потрібно вказувати ключ this.on('click::(.my-button)', () => {...}); // Виведе в консоль елемент .inner-node, // Який знаходиться всередині пісочниці console.log(this.$('.inner-node')); ``` ### Важливі особливості роботи методу і спеціальні прапори Четвертим аргументом ``eventOptions`` в метод ``bindNode`` можна передати об'єкт, що складається з прапорів, описаних нижче, глобальних прапорів (наприклад, ``silent``), або кастомних даних, які потраплять в оброблювачі подій ``bind`` і ``bind:KEY``. ```js this.on('bind:x', evt => { console.log(evt.foo); // bar }); this.bindNode('x', node, binder, { foo: 'bar' }); ``` Для ознайомлення з важливими тонкощами роботи ``bindNode`` інформація нижче обов'язкова до ознайомлення. При цьому, імена прапорів запам'ятовувати не обов'язково. #### Прапор ``exactKey=false`` Якщо в якості ``key`` передати строку, що містить точку, то така строка буде інтерпрітірована як шлях до властивості у вкладеному об'єкті. Matreshka.js буде слухати зміни в усьому дереві, розриваючи зв'язок для старих гілок, і створюючи його для нових. ```js this.a = { b: { c: 'foo' } }; this.bindNode('a.b.c', node); this.a.b.c = 'bar'; // Оновить елемент значенням bar const oldB = this.a.b; this.a.b = { c: 'baz' }; // Оновить елемент значенням baz // Елемент не оновиться, оскільки він більше не пов'язаний з цією гілкою oldB.c = 'fuu'; ``` У разі, якщо ім'я властивості має бути використано як є, скористайтеся прапором ``exactKey`` зі значенням ``true``. ```js this['a.b.c'] = 'foo'; this.bindNode('a.b.c', node, binder, { exactKey: true }); this['a.b.c'] = 'bar'; ``` #### Прапор ``getValueOnBind`` При наявності у байндера ``getValue``, стан елемента буде вилучено та присвоєно властивості відразу після виклику ``bindNode`` за умови, якщо прив'язувана властивість має значення ``undefined``. Для того, щоб форсувати цю поведінку навіть якщо властивість - не ``undefined`` використовуйте прапор ``getValueOnBind`` зі значенням ``true``. Для скасування цієї поведінки, використовуйте той же прапор зі значенням ``false``. #### Прапор ``setValueOnBind`` При наявності у байндері ``setValue``, значення властивості буде встановлено в якості стану елемента відразу після виклику ``bindNode`` за умови, якщо прив'язувати властивість має значення відмінне від ``undefined``. Для того, щоб форсувати цю поведінку навіть якщо властивість - ``undefined`` використовуйте прапор ``setValueOnBind`` зі значенням `` true``. Для скасування цієї поведінки, використовуйте той же прапор зі значенням ``false``. #### Прапори ``debounceGetValue=true`` і ``debounceSetValue=true`` Важливою особливістю методу ``bindNode`` є те, що до зміни властивостей і зміни стану елемента застосовується мікропаттерн debounce. Це означає, що якщо прив'язана властивість буде змінена багаторазово за короткий проміжок часу (наприклад, в циклі), стан елемента буде оновлено лише один раз після затримки в кілька мілісекунд (завдяки ``debounceSetValue=true``). І навпаки: якщо стан елемента змінюється багато разів за короткий проміжок часу (тобто викликається відповідна DOM подія), властивість отримає нове значення тільки один раз після короткої затримки (завдяки ``debounceGetValue=true``). ```js const input = document.querySelector('.my-input'); this.bindNode('x', input); this.x = 'foo'; console.log(input.value === 'foo'); // false setTimeout(() => { console.log(input.value === 'foo'); // true }); ``` Для скасування цієї поведінки, використовуйте прапори ``debounceSetValue`` i/або ``debounceGetValue`` зі значенням ``false``. #### Прапори ``debounceSetValueOnBind=false`` і ``debounceGetValueOnBind=false`` Як говорилося вище, до зміни властивостей і зміни стану елемента застосовується мікропаттерн debounce. Це не стосується самого моменту зв'язування. При виклику ``bindNode`` стан елемента або значення властивості встановлюється синхронно. ``debounceSetValueOnBind`` і ``debounceGetValueOnBind`` встановлені як ``true`` вмикають debounce і для цих процесів. #### Прапори ``debounceSetValueDelay=0`` і ``debounceGetValueDelay=0`` Ці прапори дозволяють вказати затримку debounce. ``debounceSetValueDelay`` задається при використанні ``debounceSetValue`` і ``debounceSetValueOnBind``, ``debounceGetValueDelay`` - при використанні ``debounceGetValue`` і ``debounceGetValueOnBind``. #### Прапор ``useExactBinder=false`` Навіть якщо в метод ``bindNode`` передати конкретний байндер, фреймворк спробує відшукати байндер у [`Matreshka.defaultBinder`](https://matreshka.js.org/ua/#Matreshka.defaultBinders) і розширити його властивостями переданого об'єкта. Така можливість дозволяє використовувати дефолтний частково перевизначений байндер. Наприклад, ми хочемо зв'язати ``input[type="text"]`` з властивістю. За замовчуванням, стандартний байндер для цього елемента містить властивість ``"on"`` зі значенням ``"input"``. Це означає, що значення властивості об'єкта і стан елемента будуть синхронізовані відразу після введення або видалення символу користувачем. У разі, якщо ви хочете, щоб синхронізація відбувалася після DOM події ``"blur"``, вам буде потрібно передати третім аргументом об'єкт, що містить єдину властивість ``"on"``. Цей об'єкт об'єднається зі стандартним байндером, зберігши при цьому значення ``getValue`` і ``setValue``. ```js this.bindNode('x', '.my-input', { on: "blur" }); ``` Для скасування цієї поведінки і використання байндера як він є, в об'єкт події можна передати прапор ``useExactBinder`` зі значенням ``true``. ```js this.bindNode('x', node, binder, { useExactBinder: true }); ``` **Повертає:** [`object`](https://matreshka.js.org/ua/#type-object) – self **Генерує події:** `bind`, `bind:KEY` ## Аргументи | Ім'я | Тип | Опис | | --- | --- | --- | | `key` | [`string`](https://matreshka.js.org/ua/#type-string) | Ім'я властивості | | `node` | [`string`](https://matreshka.js.org/ua/#type-string) \| [`node`](https://matreshka.js.org/ua/#type-node) \| [`$nodes`](https://matreshka.js.org/ua/#type-dollar-nodes) | HTML елемент, який повинен бути пов'язаний з властивістю об'єкта | | `binder` (необов'язковий) | [`binder`](https://matreshka.js.org/ua/#type-binder) | Байндер, що містить властивості ``on``, ``getValue``, ``setValue``, ``initialize``, ``destroy``, див. [`binder`](https://matreshka.js.org/ua/#type-binder). | | `eventOptions` (необов'язковий) | [`eventOptions`](https://matreshka.js.org/ua/#type-event-options) | Об'єкт події, в який можна передати ключ ``"silent"`` (щоб не генерувати події ``"bind"`` і ``"bind:KEY"``), прапори, описані вище або кастомні дані | ## Посилання - [`Matreshka#unbindNode`](https://matreshka.js.org/ua/#Matreshka-unbindNode) - [`Matreshka#bindOptionalNode`](https://matreshka.js.org/ua/#Matreshka-bindOptionalNode) - [`Matreshka#bindSandbox`](https://matreshka.js.org/ua/#Matreshka-bindSandbox) - [`Matreshka#$`](https://matreshka.js.org/ua/#Matreshka-selectAll) - [`Matreshka.binders`](https://matreshka.js.org/ua/#Matreshka.binders) - [`Matreshka.defaultBinders`](https://matreshka.js.org/ua/#Matreshka.defaultBinders) ## Альтернативний синтаксис Matreshka#bindNode: можливість передати об'єкт з байндінгамі ```js Matreshka#bindNode(bindings, [binder], [eventOptions]) → object ``` У метод [`Matreshka#bindNode`](https://matreshka.js.org/ua/#Matreshka-bindNode) можна передати об'єкт щоб уникнути багаторазового виклику методу і скоротити код. Ключі об'єкта - це імена властивостей, а значення можуть бути наступними: - HTML елемент - Об'єкт з властивостями ``node`` (HTML елемент) і ``binder`` - Масив об'єктів з властивостями ``node`` (HTML елемент) і ``binder`` Якщо `` binder`` переданий другим аргументом, то він служить байндером для тих елементів, для яких байднер не вказано явно. **Повертає:** [`object`](https://matreshka.js.org/ua/#type-object) – self ### Аргументи | Ім'я | Тип | Опис | | --- | --- | --- | | `bindings` | [`object`](https://matreshka.js.org/ua/#type-object) | (див. приклад) | | `binder` (необов'язковий) | [`binder`](https://matreshka.js.org/ua/#type-binder) | (див. вище) | | `eventOptions` (необов'язковий) | [`eventOptions`](https://matreshka.js.org/ua/#type-event-options) | (див. вище) | ### Приклади ```js this.bindNode({ foo: '.custom-checkbox', 'bar.length': 'textarea' }); ``` ```js this.bindNode({ foo: { node: ':sandbox .aaa', binder: Matreshka.binders.html() }, bar: '.bbb', baz: [{ node: '.ccc' }, { node: document.querySelector('.ddd'), binder: Matreshka.binders.prop('baz') }] }, { // will be used as a binder for .bbb and .ccc setValue(value) { foo(value); } }); ``` ## Альтернативний синтаксис, що дозволяє оголосити необмежену кількість байндінгов одним викликом методу. ```js Matreshka#bindNode(batch, [commonEventOptions]) → object ``` Варіація методу дозволяє передати масив об'єктів, що містять інформацію про байндінги. Елемент масиву повинен містити наступні властивості: - ``key`` - ім'я властивості - ``node`` - елемент, для якого оголошуємо зв'язування з ``key`` - ``binder`` - байндер (не обов'язково) - ``event`` - об'єкт події (не обов'язково) Другий аргумент - загальний об'єкт події, що розширює ``event`` для кожного байндінга (властивості з ``event`` є більш пріоритетні). **Повертає:** [`object`](https://matreshka.js.org/ua/#type-object) – self ### Аргументи | Ім'я | Тип | Опис | | --- | --- | --- | | `batch` | [`array`](https://matreshka.js.org/ua/#type-array) | Масив байндінгів | | `commonEventOptions` (необов'язковий) | [`eventOptions`](https://matreshka.js.org/ua/#type-event-options) | Загальні для всіх об'єктів властивості події | ### Приклади ```js this.bindNode([{ key: 'a', node: '.my-node', binder: { setValue(v) { doSomething(v); } } }, { key: 'b', node: document.querySelectorAll('.bar'), event: { foo: 'bar' } }, { key: 'c.d.e', node: jQuery('.baz'), binder: Matreshka.binders.html(), event: { silent: true, exactKey: true } }], { getValueOnBind: false }); ``` --- # Matreshka#bindOptionalNode **Метод** ```js Matreshka#bindOptionalNode() ``` Працює в точності так само, як і [`Matreshka#bindNode`](https://matreshka.js.org/ua/#Matreshka-bindNode) але не кидає виняток, якщо аргумент ``node`` - порожній масив, ``undefined`` або не існує > У метода є [статичный аналог](https://matreshka.js.org/ua/#Matreshka.bindOptionalNode). ## Посилання - [`Matreshka#bindNode`](https://matreshka.js.org/ua/#Matreshka-bindNode) ## Приклади ```js this.bindOptionalNode('myKey', '.my-element'); ``` --- # Matreshka#calc **Метод** ```js Matreshka#calc(target, source, [handler=(v)=>v], [eventOptions]) ``` Створює залежність значення однієї властивості від значень інших Метод ``calc`` створює залежність значення властивості (аргумент ``target``) від значень інших властивостей (аргумент ``source``). При зміні ``source``, ``target`` обчислюється автоматично. > Зверніть увагу, що у метода є [статичний аналог](https://matreshka.js.org/ua/#Matreshka.calc), який працює в точності так само, але приймає будь-який об'єкт в якості першого аргументу, зсуваючи інші аргументи вправо. ```js import { calc } from 'matreshka'; const object = {}; calc(object, target, source, handler, eventOptions); // Замість this.calc(target, source, handler, eventOptions); ``` Аргумент ``source`` має кілька варіацій. #### Строка Властивість ``target`` буде залежати від властивості ``source``. ```js this.b = 1; this.calc('a', 'b', b => b * 2); console.log(this.a); // 2 ``` #### Масив строк Властивість ``target`` буде залежати від властивостей, перерахованих в ``source``. ```js this.b = 1; this.c = 2; this.d = 3; this.calc('a', ['b', 'c', 'd'], (b, c, d) => b + c + d); console.log(this.a); // 6 ``` #### Об'єкт з властивостями ``object`` і ``key`` В цьому випадку можна оголосити залежність властивості ``target`` від іншого об'єкта. ```js const someObject = { b: 1 }; this.calc('a', { object: someObject, key: 'b' }, b => b * 2); console.log(this.a); // 2 ``` Значенням властивості ``key`` можна передати масив ключів. ```js const someObject = { b: 1, c: 2, d: 3 }; this.calc ('a', { object: someObject, key: ['b', 'c', 'd'] }, (b, c, d) => b + c + d); console.log(this.a); // 6 ``` #### Масив об'єктів з властивостями ``object`` і ``key`` Так можна оголосити залежність властивості від властивостей різних об'єктів. ```js const someObject = { b: 1, c: 2 }; const someObjectY = { d: 3 }; this.calc('a', [{ object: someObject, key: ['b', 'c'] }, { object: someObjectY, key: 'd' }], (b, c, d) => b + c + d); console.log(this.a); // 6 ``` #### Масив, що комбінує строки (власні властивості) і об'єкти ```js this.b = 1; this.c = 2; const someObject = { d: 3, e: 4 }; this.calc('a', ['b', 'c', { object: someObject, key: ['d', 'e'] }], (b, c, d, e) => b + c + d + e); console.log(this.a); // 10 ``` З міркувань чистоти коду, комбінувати строки і об'єкти в масиві ``source`` не рекомендується. Замість строк краще передати об'єкт, у якого властивість ``object`` має значення цільового об'єкту. Приклад нижче робить те ж саме, що і попередній. ```js this.b = 1; this.c = 2; const someObject = { d: 3, e: 4 }; this.calc('a', [{ object: this, // цільовий об'єкт - це this key: ['b', 'c'] }, { object: someObject, key: ['d', 'e'] }], (b, c, d, e) => b + c + d + e); console.log(this.a); // 10 ``` #### Точка в імені властивості-джерела Якщо ім'я ключа містить точку, метод ініціює залежність від властивості у вкладеному об'єкті. ```js this.b = { c: { d: 1 } }; this.e = { f: { g: 2 } }; this.calc('a', ['b.c.d', 'e.f.g'], (d, g) => d + g); console.log(this.a); // 3 ``` Те ж саме стосується і зовнішніх об'єктів ```js this.b = { c: { d: 1 } }; const someObject = { e: { f: { g: 2 } } }; this.calc('a', [{ object: this, key: 'b.c.d' }, { object: someObject, key: 'e.f.g' }], (d, g) => d + g); console.log(this.a); // 3 ``` > Метод захищений від циклічних залежностей (наприклад a залежить від b, b залежить від c, а c залежить від a) і при помилці обчислень не блокує сторінку і не кидає виняток про переповнення стека. Як ви могли помітити, аргументи функції ``handler`` завжди розташовані в тому ж порядку, що і властивості з ``source``. У разі, якщо потрібно змінити значення властивості-джерела і зробити це так, щоб цільова властивість не була обчислена заново, використовуйте метод [`Matreshka#set`](https://matreshka.js.org/ua/#Matreshka-set) з прапором ``skipCalc`` рівним ``true``. ```js this.calc('a', 'b', handler); this.set('b', newValue, {     skipCalc: true }); ``` ### Важливі особливості роботи методу і спеціальні прапори Четвертим аргументом в метод ``calc`` можна передати об'єкт події ``eventOptions``, що містить спеціальні прапори, які описані нижче, прапори для методу ``set`` (наприклад, ``silent``), або кастомні дані, які передаються в обробники події ``change:KEY``. ```js this.on('change:a', evt => { console.log(evt.foo); // 'bar' }); this.calc('a', source, handler, { foo: 'bar' }); ``` Якщо джерело змінюється з прапором ``silent``, ціль теж змінюється «тихо». Кастомні дані зміни джерела також потрапляють в обробники цілі. Прапори ``force``, ``forceHTML``, ``silentHTML`` і ``skipMediator`` зміни джерела на ціль не діють. #### Прапор ``debounceCalc=true`` При виклику методу `` calc`` цільова властивість обчислюється без затримок, але при зміні властивості-джерела застосовується патерн debounce. Це означає, що цільова властивість зміниться через кілька мілісекунд і тільки один раз, навіть якщо властивості-джерела змінилися багаторазово за короткий проміжок часу. ```js this.b = 1; this.c = 2; this.d = 3; this.calc('a', ['b', 'c', 'd'], (b, c, d) => b + c + d); this.on('change:a', () => { // Обробник буде викликаний один раз незважаючи на те, // що властивості-джерела змінилися тричі console.log(`a is changed to ${this.a}`); // a is changed to 60 }); this.b = 10; this.c = 20; this.d = 30; console.log(this.a); // 6 замість 60 ``` Для скасування debounce при зміні властивостей, тобто для включення моментального оновлення цільового властивості (як було в попередніх версіях методу), четвертим аргументом методу ``calc`` можна передати прапор ``debounceCalc`` рівний ``false``. ```js this.b = 1; this.c = 2; this.d = 3; this.calc ('a', ['b', 'c', 'd'], (b, c, d) => b + c + d, { debounceCalc: false }); this.on('change: a', () => { // Обробник буде викликаний тричі, // кожен раз коли властивості b, c чи d змінюються     // a is changed to ... 15, 33, 60 console.log(`a is changed to ${this.a}`); }); this.b = 10; this.c = 20; this.d = 30; console.log(this.a); // 60 ``` #### Прапор ``debounceCalcOnInit=false`` Як говорилося вище, при виклику методу ``calc`` цільова властивість обчислюється відразу, а при зміні властивостей-джерел - ні. Увімкнути debounce і при першому обчисленні властивості можна передавши в якості властивості об'єкта події прапор ``debounceCalcOnInit=true``. ```js this.on('change:a', () => { // Обробник буде викликаний один раз через невеликий проміжок часу console.log(`a is changed to ${this.a}`); // a is changed to 6 }); this.b = 1; this.c = 2; this.d = 3; this.calc ('a', ['b', 'c', 'd'], (b, c, d) => b + c + d, {     debounceCalcOnInit: true }); console.log(this.a); // undefined ``` На практиці ``debounceCalcOnInit`` навряд чи стане в нагоді. Потрібно лише пам'ятати, що є прапор який включає "повний debounce". #### Прапор ``debounceCalcDelay=0`` Прапор дозволяє вказати затримку debounce при використанні ``debounceCalc`` і ``debounceCalcOnInit``. #### Прапор ``setOnInit=true`` Відомо, що при виклику методу ``calc`` властивість відразу отримує нове значення. Для того, щоб скасувати цю поведінку і обчислити властивість ``target`` тільки тоді, коли властивість-джерело вперше змінено, використовуйте прапор ``setOnInit`` рівний ``false``. ```js this.calc('a', 'b', b => b * 2, {     setOnInit: false }); console.log(this.a); // undefined // Але якщо оновити this.b, для властивості a буде обчислено нове значення this.b = 1; ``` #### Прапор ``exactKey=false`` Як говорилося вище, в якості імені властивості-джерела можна передати строку, що містить точки. Таке ім'я буде витлумачено як шлях до властивості у вкладеному об'єкті. У разі, якщо ім'я має бути використано як є, скористайтеся прапором ``exactKey`` зі значенням ``true``. ```js this['foo.bar.baz'] = 1; this.calc('a', 'foo.bar.baz', fooBarBaz => fooBarBaz * 2, {     exactKey: true }); console.log(this.a); // 2 ``` #### Прапор ``promiseCalc=false`` Цей прапор дозволяє використовувати екземпляри ``Promise`` всередині функції, що обчислює значення. Значенням шуканої властивості стає результат успішного виконання промісу. > Увага! ``Promise`` неможливо скасувати. Використовуйте можливість ``promiseCalc`` акуратно та не допускайте багаторазового виклику складних функцій. Якщо джерела змінюються знову до того, як проміс виконається, ціль встановлює тільки останнє обчислення: результати попередніх відкидаються. ```js this.calc('a', ['b', 'c'], (b, c) => { return new Promise(resolve => { setTimeout(() => { resolve(b + c) }, 1000); }); }, { promiseCalc: true }); this.b = 1; this.c = 2; // "a" буде змінений через секунду ``` ```js this.calc('response', 'data', async (data) => { const resp = await fetch(url, { method: 'post', body: data }); return resp.json(); }, { promiseCalc: true }); ``` ## Аргументи | Ім'я | За замовчуванням | Тип | Опис | | --- | --- | --- | --- | | `target` | | [`string`](https://matreshka.js.org/ua/#type-string) | Ім'я властивості яка залежить від інших властивостей | | `source` | | [`string`](https://matreshka.js.org/ua/#type-string) \| [`array`](https://matreshka.js.org/ua/#type-array) | Від яких властивостей залежить шукана властивість (див. опис вище) | | `handler` (необов'язковий) | `(v)=>v` | [`function`](https://matreshka.js.org/ua/#type-function) | Функція, що повертає нове значення | | `eventOptions` (необов'язковий) | | [`eventOptions`](https://matreshka.js.org/ua/#type-event-options) | Об'єкт, в який можна передати якісь дані для обробника події, який слухає зміни ``target`` або спеціальні прапори (див. опис методу) | ## Приклади ```js this.calc('greeting', 'name', name => `Hello, ${name}!`); this.name = 'World'; // ... in a moment alert(this.greeting); // 'Hello, World!' ``` **Обчислення периметра прямокутника по двох сторонах (і сторін по периметру)** ```js this.a = 3; this.b = 4; this     .calc('p', ['a', 'b'], (a, b) => (a + b) * 2)     .calc('a', ['p', 'b'], (p, b) => p / 2 - b)     .calc('b', ['p', 'a'], (p, a) => p / 2 - a); alert(this.p); // 14 this.on('change: p', () => {     // "периметр змінений і дорівнює 18"     console.log(`периметр змінений і дорівнює ${this.p}`); }); this.a = 5; ``` ## Додаткова можливість методу Matreshka#calc, що дозволяє оголосити кілька обчислюваних властивостей одним викликом ```js Matreshka#calc(batch, [commonEventOptions]) ``` Перший аргумент - об'єкт, ключі якого - імена властивостей, які потрібно обчислювати, а значення - об'єкти, що містять: - ``source`` - властивості, від яких залежить цільова властивість; - ``handler`` - як саме буде обчислена властивість (за замовчуванням дорівнює ``(value) => value``); - ``event`` - об'єкт події (не обов'язково). Другий аргумент - загальний об'єкт події, що розширює ``event`` для кожної шуканої властивості (властивості з ``event`` мають більший приоритет). ``source`` може приймати будь-який вид [опис вище](https://matreshka.js.org/ua/#Matreshka-calc) (рядок, масив рядків, об'єкт з властивостями ``key`` і ``object``, масив таких об'єктів). ### Аргументи | Ім'я | Тип | Опис | | --- | --- | --- | | `batch` | [`array`](https://matreshka.js.org/ua/#type-array) | Об'єкт містить інформацію про обчислюваних властивості | | `commonEventOptions` (необов'язковий) | [`eventOptions`](https://matreshka.js.org/ua/#type-event-options) | Загальні властивості для об'єктів події | ### Приклади ```js this.calc({ x: { source: ['a', 'b'], handler: (a, b) => a + b }, y: { source: { object: someObject, key: 'c' }, event: { setOnInit: false } }, z: { source: [{ object: this, key: 'x' }, { object: someObject, key: 'd' }], handler: (x, d) => x + d } }, { debounceCalc: false }); ``` --- # Matreshka#instantiate **Метод** ```js Matreshka#instantiate(key, class, [updateCallback]) → object ``` Створює фіксований екземпляр класу > Зверніть увагу, що у метода є [статичний аналог](https://matreshka.js.org/ua/#Matreshka.instantiate). Метод створює і фіксує екземпляр класу в якості значення заданогї властивості. При спробі перевизначити властивість, замість самого перевизначення, екземпляр оновлюється. Таким чином досягається цілісність програми, зробленої на базі Matreshka.js. > Метод є надбудовою над [`Matreshka#mediate`](https://matreshka.js.org/ua/#Matreshka-mediate) і перевизначає медіатор. Екземпляр класу створюється під час запуску методу ``instantiate``. Першим аргументом конструктора класу стає поточне значення властивості. У конструкторі класу необхідно передбачити те, що в нього потрапить або ``undefined`` (якщо властивість не містила до цього ніяких даних), або об'єкт, з яким треба щось зробити (наприклад, розширити екземпляр класу властивостями об'єкта). > На ділі це виглядає просто: ви створюєте звичайний клас, який майже завжди приймає якісь дані, які потрібно обробити (наприклад, використовувати їх в методі [`Matreshka.Object#setData`](https://matreshka.js.org/ua/#Matreshka.Object-setData)). При спробі привласнити властивості інше значення, внутрішній механізм методу ``instantiate``, замість присвоювання, робить наступне: - Якщо вказана функція ``updateCallback``, метод запускає його з двома аргументами: поточним значенням властивості і даними, які код намагається привласнити. - Якщо заданий клас успадкований від [`Matreshka.Object`](https://matreshka.js.org/ua/#Matreshka.Object), екземпляр оновлюється новими даними, використовуючи метод [`Matreshka.Object#setData`](https://matreshka.js.org/ua/#Matreshka.Object-setData) з прапором ``replaceData=true``. - Якщо заданий клас успадкований від [`Matreshka.Array`](https://matreshka.js.org/ua/#Matreshka.Array), екземпляр оновлюється новими даними, використовуючи метод [`Matreshka.Array#recreate`](https://matreshka.js.org/ua/#Matreshka.Array-recreate). - Якщо не вказана функція ``updateCallback`` і якщо класі не успадкований від [`Matreshka.Object`](https://matreshka.js.org/ua/#Matreshka.Object) або [`Matreshka.Array`](https://matreshka.js.org/ua/#Matreshka.Array), екземпляр розширюється властивостями об'єкта, який код намагається привласнити. > Особливістю методу є відсутність обмежень на джерело класу. Класом може виступати будь-яка функція-конструктор. яка ініціалізується за допомогою оператора `` new``, а не тільки спадкоємці [`Matreshka`](https://matreshka.js.org/ua/#Matreshka). **Повертає:** [`object`](https://matreshka.js.org/ua/#type-object) – self ## Аргументи | Ім'я | Тип | Опис | | --- | --- | --- | | `key` | [`string`](https://matreshka.js.org/ua/#type-string) \| [`array`](https://matreshka.js.org/ua/#type-array) | Ім'я властивості або масив імен властивостей | | `class` | [`function`](https://matreshka.js.org/ua/#type-function) | Клас, чий екземпляр стає значенням властивості | | `updateCallback` (необов'язковий) | [`function`](https://matreshka.js.org/ua/#type-function) | Функція, викликається при кожній спробі присвоїти чергові дані властивості, що дозволяє кастомізувати логіку поновлення екземпляра класу новими даними. Функція приймає два аргументи: поточне значення властивості (екземпляр класу) і дані, які намагаються привласнити. | ## Приклади ```js class MyClass { // ... } // ... this.instantiate('x', MyClass); // намагаємося привласнити властивості інше значення this.x = { a: 42 }; // this.x як і раніше екземпляр класу MyClass alert(this.x instanceof MyClass); // true alert(this.x.a); // 42 ``` **Використання ``updateCallback``.** ```js this.instantiate('x', MyClass, (instance, data) => { updateSomeHow(instance, data); }); ``` **Отримання батьківского об'єкту та імені властивості. Крім даних (перший аргумент), в конструктор створюваного класу, передається посилання на об'єкт, що викликав ``instantiate`` та ім'я створеної властивості** ```js class MyClass extends Matreshka { constructor(data, parent, key) { super(); // parent - це екземпляр MyParentClass, // який створив властивість // key - им'я властивості ("х") } } class MyParentClass extends Matreshka { constructor() { super().instantiate('x', MyClass); } } ``` **Нестандартний спосіб використання ``updateCallback`` для ігнорування будь-яких змін властивості** ```js this.instantiate('x', SubClass, () => {}); ``` **У разі, якщо ваш клас не підтримує використання оператора ``new``, замість ``instantiate`` скористайтеся методом [`Matreshka#mediate`](https://matreshka.js.org/ua/#Matreshka-mediate).** ```js this.mediate('x', (data, currentValue) => { return currentValue instanceof SomeClass ? Object.assign(currentValue, data) : SomeLib.initInstance(SomeClass, data); }); ``` **Абстрактний приклад з даними великий вкладеності (для лаконічності використовується синтаксис class instance fields)** ```js // app.js class App extends Matreshka { constructor(appData) { super(); this.appData = appData; this.instantiate('appData', AppData); } } // app-data.js class AppData extends Matreshka.Object { constructor(data) { super(data) .instantiate({ friends: Friends, settins: Settings }); } } // friend.js class Friend extends Matreshka.Object { constructor(data) { super(data); } } // friends.js class Friends extends Matreshka.Array { get Model() { return Friend; } trackBy = 'id'; constructor(data) { super(...data); } } // settings.js class Settings extends Matreshka.Object { constructor(data) { super(data) .instantiate('credentials', Credentials); } } // credentials.js class Credentials extends Matreshka.Object { constructor(data) { super(data); } } // app-init.js var app = new App({ settings: { name: 'Vasiliy Vasiliev', credentials: { email: 'vasia.vasia@gmail.com' } }, friends: [{ name: 'Yulia Zuyeva', id: 1 }, { name: 'Konstantin Konstantinopolsky', id: 2 }, { name: 'nagibator3000', id: 3 }] }); // дані можна серіалізувати та передати на сервер JSON.stringify(app.appData); // потім просто присвоїти чергові дані властивості appData // при цьому, структура класів не зміниться app.appData = { settings: { name: 'Petr Petrov', credentials: { email: 'petr.petrov@gmail.com' } }, friends: [{ name: 'Yulechka Zuyeva', id: 1 }, { name: 'Konstantin Konstantinopolsky', id: 2 }] }; ``` ## Альтернативный синтаксис методу Matreshka#instantiate, який дозволяє приймати об'єкт ключ-клас в якості аргументу ```js Matreshka#instantiate(keyClassPairs, [updateCallback]) → object ``` **Повертає:** [`object`](https://matreshka.js.org/ua/#type-object) – self ### Аргументи | Ім'я | Тип | Опис | | --- | --- | --- | | `keyClassPairs` | [`object`](https://matreshka.js.org/ua/#type-object) | Об'єкт з властивостями ключ-клас | | `updateCallback` (необов'язковий) | [`function`](https://matreshka.js.org/ua/#type-function) | Функція, яка викликається при кожній спробі присвоїти нові данні властивості. | ### Приклади ```js this.instantiate({ x: Class1, y: Class2, z: Class3 }, (instance, data) => { instance.doSomethingWith(data); }); ``` --- # Matreshka#mediate **Метод** ```js Matreshka#mediate(key, mediator) ``` Трансформує значення властивості при його зміні Цей метод використовується для перетворення значення властивості при його зміні. Наприклад, вам потрібно, щоб значення властивості завжди було або певного типу, або цілим числом, або бути не менше нуля і не більше ста тощо. > Зверніть увагу, що у метода є [статичний аналог](https://matreshka.js.org/ua/#Matreshka.mediate), який працює в точності так само, але приймає будь-який об'єкт в якості першого аргументу, зсуваючи інші аргументи вправо. ```js import { mediate } from 'matreshka'; const object = {}; mediate(object, key, mediator); // Замість this.mediate(key, mediator); ``` ## Аргументи | Ім'я | Тип | Опис | | --- | --- | --- | | `key` | [`string`](https://matreshka.js.org/ua/#type-string) \| [`array`](https://matreshka.js.org/ua/#type-array) | Ім'я властивості або масив імен | | `mediator` | [`function`](https://matreshka.js.org/ua/#type-function) | Функція-посередник (медіатор, mediator), яка повертає нове значення. У неї передаються такі аргументи: нове значення, попереднє значення, ім'я властивості, сам об'єкт | ## Приклади ```js this.mediate('x', value => String(value)); this.x = 1; alert(typeof this.x); // "string" ``` **Масив ключів** ```js this.mediate(['x', 'y'], value => String(value)); ``` ## Альтернативный синтаксис методу Matreshka#mediate, приймаючий в якості аргументу об'єкт "ключ-медіатор" ```js Matreshka#mediate(keyMediatorPairs) ``` ### Аргументи | Ім'я | Тип | Опис | | --- | --- | --- | | `keyMediatorPairs` | [`object`](https://matreshka.js.org/ua/#type-object) | Об'ект із властивостями ключ-медіатор | ### Приклади ```js this.mediate({ x: String, y: Number, z: Boolean }); this.x = 1; this.y = 2; this.z = 3; alert(typeof this.x); // "string" alert(typeof this.y); // "number" alert(typeof this.z); // "boolean" ``` --- # Matreshka#off **Метод** ```js Matreshka#off([names], [callback], [context]) → matreshka ``` Видаляє обробник події Видаляє створений раніше обробник. Всі три аргументи опційні. Ви можете видалити як всі події (не передаючи жодного аргументу), так і окремі (передавши тільки ім'я події, передавши ім'я події і обробник, передавши і ім'я події, і обробник, і контекст) Без аргументів ``off`` видаляє всі обробники, додані через ``on``, ``once`` і ``onDebounce``, і генерує ``removeevent`` для кожного з них. Прив'язки, залежності ``calc`` і внутрішні події ``Matreshka.Object`` та ``Matreshka.Array`` залишаються. **Повертає:** [`matreshka`](https://matreshka.js.org/ua/#type-matreshka) – self **Генерує події:** `removeevent`, `removeevent:NAME` ## Аргументи | Ім'я | Тип | Опис | | --- | --- | --- | | `names` (необов'язковий) | [`eventNames`](https://matreshka.js.org/ua/#type-event-names) | Розділений пробілами список імен подій (наприклад, ``"change:x ajaxcomplete change:y"``) | | `callback` (необов'язковий) | [`eventHandler`](https://matreshka.js.org/ua/#type-event-handler) | Функція-обробник | | `context` (необов'язковий) | [`object`](https://matreshka.js.org/ua/#type-object) | Контекст | ## Посилання - [`Matreshka#on`](https://matreshka.js.org/ua/#Matreshka-on) - [`Matreshka#once`](https://matreshka.js.org/ua/#Matreshka-once) - [`Matreshka#onDebounce`](https://matreshka.js.org/ua/#Matreshka-onDebounce) - [`Matreshka#trigger`](https://matreshka.js.org/ua/#Matreshka-trigger) ## Приклади ```js this.off('change:x bind'); ``` **Видалення всіх подій** ```js this.off(); ``` **Видалення події з певним обробником** ```js const handler = function () { // ... } this.on('change:x', handler); this.off('change:x', handler); ``` **Видалення події з певним контекстом** ```js const object = {}; this.on('change:x', handler, object); this.off('change:x', handler, object); ``` --- # Matreshka#on **Метод** ```js Matreshka#on(names, callback, [triggerOnInit=false], [context]) → object ``` Додає обробник події Метод [`Matreshka#on`](https://matreshka.js.org/ua/#Matreshka-on) додає обробник події для екземпляра класу ``Matreshka``. Повний список можливих подій з описом см. Тут: [`eventNames`](https://matreshka.js.org/ua/#type-event-names). > Зверніть увагу, що у методва є [статичний аналог](https://matreshka.js.org/ua/#Matreshka.on), який працює в точності так само, але приймає будь-який об'єкт в якості першого аргументу, зсуваючи інші аргументи вправо. ```js import { on } from 'matreshka'; const object = {}; on(object, names, callback, triggerOnInit, context); // Замість this.on(names, callback, triggerOnInit, context); ``` Повторне додавання того самого обробника з тим самим контекстом для тієї самої події нічого не змінює. Для DOM подій (``click::x``) діє те саме правило. **Повертає:** [`object`](https://matreshka.js.org/ua/#type-object) – self **Генерує події:** `addevent`, `addevent:NAME` ## Аргументи | Ім'я | За замовчуванням | Тип | Опис | | --- | --- | --- | --- | | `names` | | [`eventNames`](https://matreshka.js.org/ua/#type-event-names) | Ім'я події або кілька імен, розділених пробілом (наприклад, ``"change:x ajaxcomplete change:y"``) | | `callback` | | [`eventHandler`](https://matreshka.js.org/ua/#type-event-handler) | Функція, яка викликається за подією | | `triggerOnInit` (необов'язковий) | `false` | [`boolean`](https://matreshka.js.org/ua/#type-boolean) | Якщо аргумент ``triggerOnInit`` дорівнює ``true``, то обробник буде викликаний негайно після ініціалізації. | | `context` (необов'язковий) | | [`object`](https://matreshka.js.org/ua/#type-object) | Контекст обробника. Іншими словами, ``this`` при виклику ``callback`` | ## Посилання - [`Matreshka#onDebounce`](https://matreshka.js.org/ua/#Matreshka-onDebounce) - [`Matreshka#once`](https://matreshka.js.org/ua/#Matreshka-once) - [`Matreshka#off`](https://matreshka.js.org/ua/#Matreshka-off) - [`Matreshka#trigger`](https://matreshka.js.org/ua/#Matreshka-trigger) ## Приклади ```js this.on('foo', () => { alert('Custom Event is fired'); }); this.trigger('foo'); ``` **Передача контексту** ```js this.on('foo', function() { alert(this.a); // 5 }, { a: 5 }); this.trigger('foo', 'Hello world'); ``` **Виклик обробника відразу після ініціалізації** ```js // Виводить на екран "bar" моментально і чекає на подію "foo" this.on('foo', () => { alert('bar'); }, true); ``` ## Альтернативний синтаксис: пари "подія-обробник" ```js Matreshka#on(evtnameHandlerObject, [triggerOnInit=false], [context]) → object ``` У метод [`Matreshka#on`](https://matreshka.js.org/ua/#Matreshka-on) можна передати об'єкт з парами подія-обробник, щоб уникнути багаторазового виклику методу і скоротити код. **Повертає:** [`object`](https://matreshka.js.org/ua/#type-object) – self ### Аргументи | Ім'я | За замовчуванням | Тип | Опис | | --- | --- | --- | --- | | `evtnameHandlerObject` | | [`object`](https://matreshka.js.org/ua/#type-object) | Об'єкт з подіями | | `triggerOnInit` (необов'язковий) | `false` | [`boolean`](https://matreshka.js.org/ua/#type-boolean) | Якщо аргумент ``triggerOnInit`` дорівнює ``true``, то обробники будуть викликані негайно після ініціалізації | | `context` (необов'язковий) | | [`object`](https://matreshka.js.org/ua/#type-object) | Контекст обробника | ### Приклади ```js this.on({ 'custom': evt => ..., 'click::x': evt => ..., 'change:y': evt => ..., }); ``` --- # Matreshka#once **Метод** ```js Matreshka#once(names, callback, [context]) → object ``` Додає обробник подій, який може бути викликаний один раз Метод працює так само, як і [`Matreshka#on`](https://matreshka.js.org/ua/#Matreshka-on) але переданий обробник може бути викликаний тільки один раз. > Зверніть увагу, що у метода є [статичний аналог](https://matreshka.js.org/ua/#Matreshka.once) **Повертає:** [`object`](https://matreshka.js.org/ua/#type-object) – self **Генерує події:** `addevent`, `addevent:NAME` ## Аргументи | Ім'я | Тип | Опис | | --- | --- | --- | | `names` | [`eventNames`](https://matreshka.js.org/ua/#type-event-names) | Ім'я події або кілька імен, розділених пробілом (наприклад, \"change:x ajaxcomplete change:y" \) | | `callback` | [`eventHandler`](https://matreshka.js.org/ua/#type-event-handler) | Функція, яка викликається за подією | | `context` (необов'язковий) | [`object`](https://matreshka.js.org/ua/#type-object) | Контекст обробника | ## Посилання - [`Matreshka#on`](https://matreshka.js.org/ua/#Matreshka-on) - [`Matreshka#off`](https://matreshka.js.org/ua/#Matreshka-off) - [`Matreshka#onDebounce`](https://matreshka.js.org/ua/#Matreshka-onDebounce) - [`Matreshka#trigger`](https://matreshka.js.org/ua/#Matreshka-trigger) ## Приклади ```js this.x = 1; this.once('change:x', () => { alert('x is changed'); }); this.x = 2; // виводить 'x is changed' this.x = 3; // нічого не робить ``` ## Альтернативний синтаксис: пари "подія-обробник" ```js Matreshka#once(evtnameHandlerObject, [context]) → object ``` У метод [`Matreshka#once`](https://matreshka.js.org/ua/#Matreshka-once) можна передати об'єкт з парами подія-обробник, щоб уникнути багаторазового виклику методу і скоротити код. **Повертає:** [`object`](https://matreshka.js.org/ua/#type-object) – self ### Аргументи | Ім'я | Тип | Опис | | --- | --- | --- | | `evtnameHandlerObject` | [`object`](https://matreshka.js.org/ua/#type-object) | Об'єкт з подіями | | `context` (необов'язковий) | [`object`](https://matreshka.js.org/ua/#type-object) | Контекст обробників | ### Посилання - [`Matreshka#on(2)`](https://matreshka.js.org/ua/#Matreshka-on--variation-2) ### Приклади ```js this.once({ 'custom': evt => { ... }, 'click::x': evt => { ... }, 'change:y': evt => { ... } }); ``` --- # Matreshka#onDebounce **Метод** ```js Matreshka#onDebounce(names, callback, [debounceDelay=0], [triggerOnInit=false], [context]) → object ``` Додає обробник події, що викликається лише одного разу за певний проміжок часу Метод дозволяє додати обробник події на екземпляр класу [`Matreshka`](https://matreshka.js.org/ua/#Matreshka), усуваючи "деренчання" обробника. Функція може бути викликана лише один раз за певний проміжок часу. В іншому, метод працює так само, як і [`Matreshka#on`](https://matreshka.js.org/ua/#Matreshka-on). > У метода є [статичний аналог](https://matreshka.js.org/ua/#Matreshka.onDebounce). **Повертає:** [`object`](https://matreshka.js.org/ua/#type-object) – self **Генерує події:** `addevent`, `addevent:NAME` ## Аргументи | Ім'я | За замовчуванням | Тип | Опис | | --- | --- | --- | --- | | `names` | | [`eventNames`](https://matreshka.js.org/ua/#type-event-names) | Ім'я події або кілька імен, розділених пробілом (наприклад, \"change:x ajaxcomplete change:y" \) | | `callback` | | [`eventHandler`](https://matreshka.js.org/ua/#type-event-handler) | Функція, яка викликається за подією | | `debounceDelay` (необов'язковий) | `0` | [`number`](https://matreshka.js.org/ua/#type-number) | Затримка | | `triggerOnInit` (необов'язковий) | `false` | [`boolean`](https://matreshka.js.org/ua/#type-boolean) | Якщо аргумент ``triggerOnInit`` дорівнює ``true``, то обробник буде викликаний негайно після ініціалізації | | `context` (необов'язковий) | | [`object`](https://matreshka.js.org/ua/#type-object) | Контекст обробника | ## Посилання - [`Matreshka#on`](https://matreshka.js.org/ua/#Matreshka-on) - [`Matreshka#once`](https://matreshka.js.org/ua/#Matreshka-once) - [`Matreshka#off`](https://matreshka.js.org/ua/#Matreshka-off) - [`Matreshka#trigger`](https://matreshka.js.org/ua/#Matreshka-trigger) ## Приклади ```js this.onDebounce('change:x', () => { alert(`x = ${this.x}`); // x = 101 }, 300); this.x = 1; for(let i = 0; i < 100; i++) { this.x++; } ``` ## Альтернативний синтаксис: пари "подія-обробник" ```js Matreshka#onDebounce(evtnameHandlerObject, [debounceDelay=0], [triggerOnInit=false], [context]) → object ``` У метод [`Matreshka#onDebounce`](https://matreshka.js.org/ua/#Matreshka-onDebounce) можна передати об'єкт з парами подія-обробник, щоб уникнути багаторазового виклику методу і скоротити код. **Повертає:** [`object`](https://matreshka.js.org/ua/#type-object) – self ### Аргументи | Ім'я | За замовчуванням | Тип | Опис | | --- | --- | --- | --- | | `evtnameHandlerObject` | | [`object`](https://matreshka.js.org/ua/#type-object) | Об'єкт з обробниками подій | | `debounceDelay` (необов'язковий) | `0` | [`number`](https://matreshka.js.org/ua/#type-number) | Затримка | | `triggerOnInit` (необов'язковий) | `false` | [`boolean`](https://matreshka.js.org/ua/#type-boolean) | Якщо аргумент ``triggerOnInit`` дорівнює ``true``, то обробники будуть викликаний негайно після ініціалізації | | `context` (необов'язковий) | | [`object`](https://matreshka.js.org/ua/#type-object) | Контекст обробників | ### Посилання - [`Matreshka#on(2)`](https://matreshka.js.org/ua/#Matreshka-on--variation-2) ### Приклади ```js this.onDebounce({ 'custom': evt => { ... }, 'click::x': evt => { ... }, 'change:y': evt => { ... } }); ``` --- # Matreshka#parseBindings **Метод** ```js Matreshka#parseBindings(node, [eventOptions]) → $nodes ``` Парсить DOM дерево, оголошуючи прив'язки властивостей, взятих в подвійні фігурні дужки. Matreshka.js включає в себе простий DOM парсер, що обробляє синтаксичні конструкції, укладені в подвійні фігурні дужки. Метод ``parseBindings`` першим аргументом приймає HTML строку, DOM вузол або селектор, відповідний DOM вузлу. Так як метод є DOM шаблонізатором (а не строковим HTML шаблонізатором), всі дочірні DOM вузли переданого елемента залишаються в своєму колишньому стані (наприклад, DOM події не затираються). #### Підтримуваний синтаксис. 1. HTML прив'язка ```html Hello, {{user.name}} ``` 2. Прив'язка елементів форм. ```html ``` ```html ``` ```html ``` 3. Прив'язка атрибутів. ```html A link ``` > Якщо фігурні дужки не влаштовують, поміняйте їх на щось інше, використовуючи [`Matreshka.parserBrackets`](https://matreshka.js.org/ua/#Matreshka.parserBrackets) #### Навіщо потрібен такий метод? У разі, якщо ви розробляєте велику форму зі стандартними HTML5 полями, метод допоможе зберегти час на оголошення численних прив'язок. Крім цього, ``parseBindings`` корисний у разі створення дуже простих колекцій, які не потребують реалізації складної [моделі](https://matreshka.js.org/ua/#Matreshka.Array-Model). **Повертає:** [`$nodes`](https://matreshka.js.org/ua/#type-dollar-nodes) – Колекція DOM вузлів, передана в функцію як аргумент ## Аргументи | Ім'я | Тип | Опис | | --- | --- | --- | | `node` | [`string`](https://matreshka.js.org/ua/#type-string) \| [`node`](https://matreshka.js.org/ua/#type-node) \| [`$nodes`](https://matreshka.js.org/ua/#type-dollar-nodes) | HTML строка, селектор, DOM вузол або колекція DOM вузлів HTML | | `eventOptions` (необов'язковий) | [`eventOptions`](https://matreshka.js.org/ua/#type-event-options) | Об'єкт події, який буде переданий у всі внутрішні виклики методу [`Matreshka#bindNode`](https://matreshka.js.org/ua/#Matreshka-bindNode) | ## Приклади **Парсинг заданого вузла** ```js this.parseBindings(node); ``` **Парсинг вузла по селектору** ```js this.parseBindings('.my-node'); ``` **Парсинг HTML строки** ```js const $node = this.parseBindings('

Hello, {{name}}

'); this.name = 'Arthur Philip Dent'; ``` --- # Matreshka#select **Метод** ```js Matreshka#select(selector) → node|null ``` Повертає елемент з пісочниці, відповідний селектору Метод дуже схожий на [`Matreshka#selectAll`](https://matreshka.js.org/ua/#Matreshka-selectAll), але повертає лише один елемент або ``null`` > У метода є [статичний аналог](https://matreshka.js.org/ua/#Matreshka.select). **Повертає:** [`node`](https://matreshka.js.org/ua/#type-node) \| [`null`](https://matreshka.js.org/ua/#type-null) ## Аргументи | Ім'я | Тип | Опис | | --- | --- | --- | | `selector` | [`string`](https://matreshka.js.org/ua/#type-string) | Селектор | ## Приклади ```js this.bindNode('sandbox', '.app'); this.select('.my-element'); // те ж саме, що і this.nodes.sandbox.querySelector('.my-element'); // те ж саме, що і $('.app').find('.my-element')[0]; ``` --- # Matreshka#selectAll **Метод** ```js Matreshka#selectAll(selector) → $nodes ``` Повертає елементи з пісочниці, відповідні селектору Синонім: `Matreshka#$` Після створення пісочниці методом [`Matreshka#bindNode`](https://matreshka.js.org/ua/#Matreshka-bindNode), можна отримувати і використовувати елементи, що знаходяться в ній. Крім цього, метод підтримує кастомний селектор ``:bound(KEY)``. > У метода є [статичний аналог](https://matreshka.js.org/ua/#Matreshka.selectAll). **Повертає:** [`$nodes`](https://matreshka.js.org/ua/#type-dollar-nodes) ## Аргументи | Ім'я | Тип | Опис | | --- | --- | --- | | `selector` | [`string`](https://matreshka.js.org/ua/#type-string) | Селектор | ## Приклади ```js this.bindNode('sandbox', '.app'); nodes = this.selectAll('.my-element'); // те ж саме, що і nodes = this.$('.my-element'); // $ - посилання на метод selectAll // те ж саме, що і nodes = $('.app').find('.my-element'); ``` **Селектор ``:bound(KEY)``** ```js this.bindNode('myKey', '.my-element'); nodes = this.selectAll(':bound(myKey) .my-another-element'); // те ж саме, що і nodes = $('.my-element').find('.my-another-element'); ``` --- # Matreshka#set **Метод** ```js Matreshka#set(key, value, [eventOptions]) ``` Встановлює значення властивості, дозволяючи передати об'єкт події в якості третьої аргументу Список підтримуваних прапорів: + ``silent`` - не викликати події ``change`` і ``change:KEY`` + ``silentHTML`` - не змінювати стан прив'язаних елементів + ``force`` - викликати події ``change`` і ``change:KEY`` навіть якщо значення властивості не змінилося + ``forceHTML`` - змінити стан прив'язаного елемента, навіть якщо значення властивості не змінилося. Ця опція потрібна, якщо прив'язаний елемент був відмальований після прив'язки (наприклад, в ``select`` були додані теги ``option``) + ``skipMediator`` - запобігає трансформацію властивості медіатором (див. [`Matreshka#mediate`](https://matreshka.js.org/ua/#Matreshka-mediate)) + ``skipCalc`` - запобігає роботу залежностей, створених за допомогою [`Matreshka#calc`](https://matreshka.js.org/ua/#Matreshka-calc) > У метода є [статичний аналог](https://matreshka.js.org/ua/#Matreshka.set). **Генерує події:** `change`, `change:KEY`, `beforechange`, `beforechange:KEY` ## Аргументи | Ім'я | Тип | Опис | | --- | --- | --- | | `key` | [`string`](https://matreshka.js.org/ua/#type-string) | Ключ | | `value` | [`*`](https://matreshka.js.org/ua/#type-any) | Значення | | `eventOptions` (необов'язковий) | [`eventOptions`](https://matreshka.js.org/ua/#type-event-options) | Об'єкт події | ## Приклади ```js this.on('change: myKey', evt => { alert(evt.value); }); // Те ж саме, що і this['myKey'] = 3 // або this.myKey = 3 // виводить на екран 3 this.set('myKey', 3); ``` **Використання ``eventOptions``** ```js this.on('change:myKey', evt => { alert(evt.value); }); // alert не спрацює this.set('myKey', 4, { silent: true }); ``` **Передача даних в обробник** ```js this.on('change:myKey', evt => { alert(evt.myCustomFlag); }); // Виводить на екран 42 this.set('myKey', 4, { myCustomFlag: 42 }); ``` ## Альтернативний синтаксис методу Matreshka#set "ключ-значення" ```js Matreshka#set(keyValuePairs, [eventOptions]) ``` ### Аргументи | Ім'я | Тип | Опис | | --- | --- | --- | | `keyValuePairs` | [`object`](https://matreshka.js.org/ua/#type-object) | Об'єкт, що містить пари ключ-значення | | `eventOptions` (необов'язковий) | [`eventOptions`](https://matreshka.js.org/ua/#type-event-options) | Об'єкт події | ### Приклади ```js this.set({ myKey1: 1, myKey2: 2 }); ``` **Передача ``eventOptions`` в якості второго аргумента** ```js this.set({ myKey: 3 }, { myFlag: 'foo' }); ``` --- # Matreshka#trigger **Метод** ```js Matreshka#trigger(names, [arg]) → object ``` Генерує подію Після додавання обробників подій за допомогою методу [`Matreshka#on`](https://matreshka.js.org/ua/#Matreshka-on), [`Matreshka#onDebounce`](https://matreshka.js.org/ua/#Matreshka-onDebounce) або [`Matreshka#once`](https://matreshka.js.org/ua/#Matreshka-once), подія може бути сгенерована вручну за допомогою цього методу. > Зверніть увагу, що у метода є [статичний аналог](https://matreshka.js.org/ua/#Matreshka.trigger). **Повертає:** [`object`](https://matreshka.js.org/ua/#type-object) – self ## Аргументи | Ім'я | Тип | Опис | | --- | --- | --- | | `names` | [`eventNames`](https://matreshka.js.org/ua/#type-event-names) | Ім'я події або кілька імен, розділених пробілом | | `arg` (необов'язковий) | `...*` | Аргументи, які будуть передані обробникам | ## Посилання - [`Matreshka#on`](https://matreshka.js.org/ua/#Matreshka-on) - [`Matreshka#once`](https://matreshka.js.org/ua/#Matreshka-once) - [`Matreshka#onDebounce`](https://matreshka.js.org/ua/#Matreshka-onDebounce) - [`Matreshka#off`](https://matreshka.js.org/ua/#Matreshka-off) ## Приклади ```js this.on('foo bar', (a, b, c) => { alert(a + b + c); }); this.trigger('bar', 1, 2, 3); // alerts 6 ``` --- # Matreshka#unbindNode **Метод** ```js Matreshka#unbindNode(key, [node], [eventOptions]) → matreshka ``` Розриває зв'язок між властивістю і HTML елементом Використовуючи цей метод, можна видалити доданий раніше, але вже не потрібний зв'язок між властивістю і елементом. Ключ з крапками — це шлях до вкладеної властивості, як і в [`Matreshka#bindNode`](https://matreshka.js.org/ua/#Matreshka-bindNode); з опцією події ``exactKey: true`` він використовується як є. ``null`` замість ключа видаляє також прив'язки вкладених властивостей (``"a.b"``). **Повертає:** [`matreshka`](https://matreshka.js.org/ua/#type-matreshka) – self **Генерує події:** `unbind`, `unbind:KEY` ## Аргументи | Ім'я | Тип | Опис | | --- | --- | --- | | `key` | [`string`](https://matreshka.js.org/ua/#type-string) \| [`null`](https://matreshka.js.org/ua/#type-null) | Ключ або список ключів, розділених пробілами. Якщо замість ключа передати null, будуть видалені всі прив'язки для даного об'єкта. | | `node` (необов'язковий) | [`string`](https://matreshka.js.org/ua/#type-string) \| [`node`](https://matreshka.js.org/ua/#type-node) \| [`$nodes`](https://matreshka.js.org/ua/#type-dollar-nodes) | HTML елемент, з яким властивість більше не хоче мати справи | | `eventOptions` (необов'язковий) | [`eventOptions`](https://matreshka.js.org/ua/#type-event-options) | Об'єкт події, в який можна передати якісь дані для обробника або ключ ``"silent"``, який відключає генерацію подій ``"unbind"`` і ``"unbind:KEY"`` | ## Приклади ```js this.bindNode('myKey', '.my-element'); // Змінює значення властивості і стан HTML елемента this.myKey = true; this.unbindNode('myKey', '.my-element'); // Тепер змінюється лише значення властивості this.myKey = false; ``` ## Альтернативний синтаксис unbindNode, що дозволяє передати об'єкт з байндінгамі. Див. Matreshka#bindNode(2) ```js Matreshka#unbindNode(bindings, [eventOptions]) → matreshka ``` **Повертає:** [`matreshka`](https://matreshka.js.org/ua/#type-matreshka) – self ### Аргументи | Ім'я | Тип | Опис | | --- | --- | --- | | `bindings` | [`object`](https://matreshka.js.org/ua/#type-object) | (див. приклад) | | `eventOptions` (необов'язковий) | [`eventOptions`](https://matreshka.js.org/ua/#type-event-options) | (див. вище) | ### Приклади ```js this.unbindNode({ foo: '.aaa', bar: { node: '.bbb' }, baz: [{ node: '.ccc' }, { node: '.ddd' }] }); ``` ## Альтернативний синтаксис, що дозволяє видалити необмежену кількість байндінгів одним викликом методу. ```js Matreshka#unbindNode(batch, [eventOptions]) ``` Варіація методу дозволяє передати масссів об'єктів, що містять інформацію про байндінги. Елемент масиву повинен містити наступні властивості: - ``key`` - ім'я властивості - ``node`` - елемент, для якого був об'явлений байндінг з ``key`` (не обов'язково) Ця варіація методу зручна тим, що її синтаксис збігається з однією з варіацій методу [`Matreshka#bindNode`](https://matreshka.js.org/ua/#Matreshka-bindNode), дозволяючи привласнити байндінгі змінної для швидкого видалення. ### Аргументи | Ім'я | Тип | Опис | | --- | --- | --- | | `batch` | [`array`](https://matreshka.js.org/ua/#type-array) | Массив байндингів | | `eventOptions` (необов'язковий) | [`eventOptions`](https://matreshka.js.org/ua/#type-event-options) | (див. вище) | ### Приклади ```js const temporaryBindings = [{ key: 'a', node: '.my-node', binder: { setValue(v) { doSomething(v); } } }, { key: 'b', node: document.querySelectorAll('.bar'), event: { foo: 'bar' } }, { key: 'c.d.e', node: jQuery('.baz'), binder: Matreshka.binders.html(), event: { silent: true, exactKey: true } }] this.bindNode(temporaryBindings); // більше не потрібні ці прив'язки this.unbindNode(temporaryBindings); ``` --- # Matreshka#bindSandbox **Метод** ```js Matreshka#bindSandbox(node, [eventOptions]) ``` Прив'язує пісочницю При цьому, "одв'язує" попередню, якщо така існує. > У метода є [статичний аналог](https://matreshka.js.org/ua/#Matreshka.bindSandbox). Ключ ``sandbox`` зарезервований для прив'язки: він не потрапляє в ``Object.keys`` і ``JSON.stringify``, а читання або присвоєння ``this.sandbox`` кидає помилку. Прив'язаний вузол доступний як ``this.nodes.sandbox``. **Генерує події:** `bind`, `bind:sandbox` ## Аргументи | Ім'я | Тип | Опис | | --- | --- | --- | | `node` | [`string`](https://matreshka.js.org/ua/#type-string) \| [`node`](https://matreshka.js.org/ua/#type-node) \| [`$nodes`](https://matreshka.js.org/ua/#type-dollar-nodes) | Елемент, який повинен стати пісочницею | | `eventOptions` (необов'язковий) | [`eventOptions`](https://matreshka.js.org/ua/#type-event-options) | Об'єкт події | ## Посилання - [`Matreshka#bindNode`](https://matreshka.js.org/ua/#Matreshka-bindNode) ## Приклади ```js this.bindSandbox('.my-element'); ``` --- # Matreshka#remove **Метод** ```js Matreshka#remove(key, [eventOptions]) → matreshka ``` Видаляє властивість > У метода є [статичний аналог](https://matreshka.js.org/ua/#Matreshka.remove). **Повертає:** [`matreshka`](https://matreshka.js.org/ua/#type-matreshka) – self **Генерує події:** `delete`, `delete:KEY` ## Аргументи | Ім'я | Тип | Опис | | --- | --- | --- | | `key` | [`string`](https://matreshka.js.org/ua/#type-string) | Им'я властивості або масив имен властивостей, які треба видалити | | `eventOptions` (необов'язковий) | [`eventOptions`](https://matreshka.js.org/ua/#type-event-options) | Об'ект події | ## Приклади ```js this.remove('myKey'); this.remove(['myKey1', 'myKey2']); ``` **Використання ``eventOptions``** ```js this.remove('myKey', { silent: true }); ``` --- # Matreshka#$nodes **Властивість** ```js Matreshka#$nodes: $nodes ``` Об'єкт містить масиви прив'язаних елементів для швидкого доступу. ## Посилання - [`Matreshka#bindNode`](https://matreshka.js.org/ua/#Matreshka-bindNode) ## Приклади ```js this.bindNode('myKey', '.my-node'); this.$nodes.myKey; // масив вузлів, як Array.from(document.querySelectorAll('.my-node')) ``` --- # Matreshka#isMatreshka **Властивість** ```js Matreshka#isMatreshka: boolean ``` ``isMatreshka`` завжди дорівнює ``true`` для экземплярів [`Matreshka`](https://matreshka.js.org/ua/#Matreshka) ## Приклади ```js alert(object.isMatreshka); ``` --- # Matreshka#nodes **Властивість** ```js Matreshka#nodes: node ``` Об'єкт містить прив'язані елементи для швидкого доступу, у вигляді окремих DOM вузлів. Зверніть увагу, кожна властивість об'єкта містить перший вузол з пов'язаних з соотвутствующий властивістю. Для отримання всіх вузлів, пов'язаних з певною властивістю, використовуйте [`Matreshka#$nodes`](https://matreshka.js.org/ua/#Matreshka-$nodes). ## Посилання - [`Matreshka#bindNode`](https://matreshka.js.org/ua/#Matreshka-bindNode) ## Приклади ```js this.bindNode('myKey', '.my-node'); this.nodes.myKey; // Те ж саме, що і $('.my-node')[0] ``` --- # Matreshka.bindNode **Метод** **Імпорт:** ```js import { bindNode } from 'matreshka'; ``` ```js Matreshka.bindNode() → object ``` Пов'язує властивість об'єкта з HTML елементом Цей статичний метод працює так само, як і [`Matreshka#bindNode`](https://matreshka.js.org/ua/#Matreshka-bindNode) та всі його варіації, але приймає в якості першого аргументу будь-який JavaScript об'єкт. **Повертає:** [`object`](https://matreshka.js.org/ua/#type-object) – Перший аргумент ## Посилання - [`Matreshka#bindNode`](https://matreshka.js.org/ua/#Matreshka-bindNode) ## Приклади ```js const object = {}; Matreshka.bindNode(object, 'x', '.my-node'); ``` --- # Matreshka.calc **Метод** **Імпорт:** ```js import { calc } from 'matreshka'; ``` ```js Matreshka.calc() → object ``` Створює залежність значення одної властивості від значень інших Цей статичний метод працює так само, як і [`Matreshka#calc`](https://matreshka.js.org/ua/#Matreshka-calc) та всі його варіації, але приймає в якості першого аргументу будь JavaScript об'єкт. **Повертає:** [`object`](https://matreshka.js.org/ua/#type-object) – Перший аргумент ## Посилання - [`Matreshka#calc`](https://matreshka.js.org/ua/#Matreshka-calc) ## Приклади ```js const object = {}; object.a = 40; object.b = 2; Matreshka.calc(object, 'sum', ['a', 'b'], (a, b) => a + b); alert(object.sum); // 42 ``` --- # Matreshka.chain **Метод** **Імпорт:** ```js import { chain } from 'matreshka'; ``` ```js Matreshka.chain(object) → object ``` Дозволяє викликати універсальні методи ланцюгом Функція приймає будь-який об'єкт і повертає екземпляр недоступного ззовні класу, який переймає універсальні методи, дозволяючи їх ланцюговий виклик для роботи з переданим об'єктом. > Універсальні методи - це такі методи, які одночасно є в прототипі [`Matreshka`](https://matreshka.js.org/ua/#Matreshka) і мають статичний аналог (наприклад, [`Matreshka#bindNode`](https://matreshka.js.org/ua/#Matreshka-bindNode) і [`Matreshka.bindNode`](https://matreshka.js.org/ua/#Matreshka.bindNode)). **Повертає:** [`object`](https://matreshka.js.org/ua/#type-object) – Екземпляр недоступного ззовні класу ## Аргументи | Ім'я | Тип | Опис | | --- | --- | --- | | `object` | [`object`](https://matreshka.js.org/ua/#type-object) \| [`function`](https://matreshka.js.org/ua/#type-function) | Об'єкт | ## Приклади ```js const object = {}; Matreshka.chain(object) .calc('a', 'b', b => b * 2) .set('b', 3) .bindNode('c', '.node'); // те ж саме, що і // Matreshka.calc(object, 'a', 'b', b => b * 2) // Matreshka.set(object, 'b', 3) // Matreshka.bindNode(object, 'c', '.node'); ``` --- # Matreshka.Class **Метод** **Імпорт:** ```js import { Class } from 'matreshka'; ``` ```js Matreshka.Class(prototype, [statics]) → class ``` Реалізація класів, заснована на прототипному спадкуванні Функція ``Class`` дозволяє використовувати класичне ООП в тих випадках, коли немає можливості скористатися синтаксисом ECMAScript 2015 classes. Якщо ``prototype`` не має власної властивості ``constructor``, клас викликає батьківський конструктор з тими самими аргументами, як клас ECMAScript 2015 без конструктора. Як ``constructor`` можна передати клас ECMAScript 2015: він викликається при створенні екземпляра, але методи, оголошені в його тілі, не успадковуються; додайте їх у ``prototype``. **Повертає:** [`class`](https://matreshka.js.org/ua/#type-class) – клас (точніше, конструктор класу) ## Аргументи | Ім'я | Тип | Опис | | --- | --- | --- | | `prototype` | [`object`](https://matreshka.js.org/ua/#type-object) | Методи та властивості | | `statics` (необов'язковий) | [`object`](https://matreshka.js.org/ua/#type-object) | Статичні методи та властивості | ## Приклади ```js const A = Matreshka.Class({ method1() { ... } }); const B = Matreshka.Class({ // B успадковується від A extends: A, method2() { ... } }); const C = Matreshka.Class({ // С успадковується від B extends: B, method2() { // виклик батьківського методу B.prototype.method2.apply(this, arguments); }, method3(a, b) { ... } }); const D = Matreshka.Class({ // D успадковується від C extends: C, method3(a, b) { // виклик батьківського методу C.prototype.method3.apply(this, arguments); } }); ``` **Передача об'єкта зі статичними методами і властивостями** ```js const MyClass = Matreshka.Class({ method() { ... } }, { staticProp: 'foo', staticMethod() { return 'bar'; } }); alert(MyClass.staticProp); // foo alert(MyClass.staticMethod()); // bar ``` --- # Matreshka.mediate **Метод** **Імпорт:** ```js import { mediate } from 'matreshka'; ``` ```js Matreshka.mediate() → object ``` Трансформує значення властивості при його зміні Цей статичний метод працює так само, як і [`Matreshka#mediate`](https://matreshka.js.org/ua/#Matreshka-mediate) та всі його варіації, але приймає в якості першого аргументу будь-який JavaScript об'єкт. **Повертає:** [`object`](https://matreshka.js.org/ua/#type-object) – Перший аргумент ## Посилання - [`Matreshka#mediate`](https://matreshka.js.org/ua/#Matreshka-mediate) ## Приклади ```js const object = {}; Matreshka.mediate(object, 'x', String); object.x = 42; alert(typeof object.x); // string ``` --- # Matreshka.on **Метод** **Імпорт:** ```js import { on } from 'matreshka'; ``` ```js Matreshka.on() → object ``` Додає обробник події Цей статичний метод працює так само, як і [`Matreshka#on`](https://matreshka.js.org/ua/#Matreshka-on) та всі його варіації, але приймає в якості першого аргументу будь-який JavaScript об'єкт. **Повертає:** [`object`](https://matreshka.js.org/ua/#type-object) – Перший аргумент ## Посилання - [`Matreshka#on`](https://matreshka.js.org/ua/#Matreshka-on) ## Приклади ```js const object = {}; Matreshka.on(object, 'foo', evt => { alert(evt.hello); }); Matreshka.trigger(object, 'foo', { hello: 'World' }); ``` --- # Matreshka.bindOptionalNode **Метод** **Імпорт:** ```js import { bindOptionalNode } from 'matreshka'; ``` ```js Matreshka.bindOptionalNode() → object ``` Пов'язує елемент із властивістю, але не кидає виняток, якщо аргумент node - порожній масив, ``undefined`` або не існує Цей статичний метод працює так само, як і [`Matreshka#bindOptionalNode`](https://matreshka.js.org/ua/#Matreshka-bindOptionalNode) та всі його варіації, але приймає в якості першого аргументу будь-який JavaScript об'єкт. **Повертає:** [`object`](https://matreshka.js.org/ua/#type-object) – Перший аргумент ## Посилання - [`Matreshka#bindOptionalNode`](https://matreshka.js.org/ua/#Matreshka-bindOptionalNode) ## Приклади ```js const object = {}; Matreshka.bindOptionalNode(object, 'x', '.my-node'); ``` --- # Matreshka.bindSandbox **Метод** **Імпорт:** ```js import { bindSandbox } from 'matreshka'; ``` ```js Matreshka.bindSandbox() → object ``` Пов'язує властивість ``sandbox`` з елементом і одв'язує попередній елемент, якщо такий існує Цей статичний метод працює так само, як і [`Matreshka#bindSandbox`](https://matreshka.js.org/ua/#Matreshka-bindSandbox) та всі його варіації, але приймає в якості першого аргументу будь-який JavaScript об'єкт. **Повертає:** [`object`](https://matreshka.js.org/ua/#type-object) – Перший аргумент ## Посилання - [`Matreshka#bindSandbox`](https://matreshka.js.org/ua/#Matreshka-bindSandbox) ## Приклади ```js const object = {}; Matreshka.bindSandbox(object, '.my-node'); ``` --- # Matreshka.instantiate **Метод** **Імпорт:** ```js import { instantiate } from 'matreshka'; ``` ```js Matreshka.instantiate() → object ``` Створює фіксований екземпляр класу Цей статичний метод працює так само, як і [`Matreshka#instantiate`](https://matreshka.js.org/ua/#Matreshka-instantiate) та всі його варіації, але приймає в якості першого аргументу будь-який JavaScript об'єкт. **Повертає:** [`object`](https://matreshka.js.org/ua/#type-object) – Перший аргумент ## Посилання - [`Matreshka#instantiate`](https://matreshka.js.org/ua/#Matreshka-instantiate) ## Приклади ```js const object = {}; Matreshka.instantiate(object, 'x', SomeClass); object.x = { a: 42 }; alert(object.x instanceof SomeClass); // true alert(object.x.a); // 42 ``` --- # Matreshka.initRouter **Метод** **Імпорт:** ```js import { initRouter } from 'matreshka/router'; ``` ```js Matreshka.initRouter(object, route, [type="hash"]) → object ``` Вмикає двостороннє зв'язування даних між властивостями і частинами URL За замовчуванням роутер працює з хешем: він використовує ``location.hash`` з hashbang (``#!/a/b/``). Щоб натомість використовувати шлях (``/a/b/``) через History API, передайте ``"history"`` третім аргументом. ```js // використовується location.hash initRouter(object, '/a/b/c/'); object.a = 'foo'; object.b = 'bar'; object.c = 'baz'; // location.hash стає #!/foo/bar/baz/ ``` Якщо потрібно використовувати History API замість хешу, передайте ``"history"`` третім аргументом. ```js initRouter(object, '/a/b/c/', 'history'); ``` Як працює «традиційний» роутинг? Розробник задає правило (маршрут) і функцію, яка викликається, коли поточний шлях відповідає правилу. ```js route("books/:id", id => { // щось робимо }); ``` Принцип ``initRouter`` інший. Ви вказуєте, яка частина URL (підтримуються і [хеш](https://developer.mozilla.org/uk/docs/Web/API/Location/hash), і [HTML5 History](https://developer.mozilla.org/uk/docs/Web/API/History_API)) синхронізується з якою властивістю. Скажімо, потрібно синхронізувати ``"x"`` з першою частиною ``location.hash``, а ``"y"`` з другою. ```js initRouter(object, '/x/y/'); ``` Тепер, коли ви пишете... ```js object.x = 'foo'; object.y = 'bar'; ``` ...``location.hash`` автоматично змінюється на ``#!/foo/bar/`` І навпаки. Коли URL змінюється вручну або кнопками «назад» і «вперед», властивості змінюються автоматично. ```js location.hash = '#!/baz/qux/'; // ... за мить console.log(object.x, object.y); // 'baz', 'qux' ``` Як завжди, зміни властивостей можна слухати методом [`Matreshka#on`](https://matreshka.js.org/ua/#Matreshka-on). ```js Matreshka.on(object, 'change:x', handler); // для екземплярів Matreshka: this.on('change:x', handler); ``` Значення кодуються в URL і декодуються назад: ``object.x = 'a b/c'`` дає ``#!/a%20b%2Fc/``, а ``object.x`` залишається ``'a b/c'``. Хеш, який не починається з ``#!`` (якір на кшталт ``#top``), не є маршрутом. #### Синтаксис зірочки Якщо якусь частину шляху не потрібно синхронізувати з властивістю, поставте на її місце зірочку. ```js initRouter(object, '/x/*/y'); ``` Якщо хеш має вигляд ``#!/foo/bar/baz/``, то ``object.x = "foo"``, а ``object.y = "baz"``. Це зручно, коли різні класи керують різними частинами шляху. **class1.js** ```js initRouter(this, '/x/*/'); ``` **class2.js** ```js initRouter(this, '/*/y/'); ``` #### Дві речі, які треба запам'ятати **1.** Якщо властивість має значення (не ``undefined``, ``null`` і не ``''``), URL змінюється одразу після виклику ``initRouter``. Властивість без значення отримує значення з URL. ```js object.x = 'foo'; initRouter(object, '/x/y/'); ``` **2.** Якщо властивість отримує ``null``, ``undefined`` або ``''``, усі наступні за нею властивості отримують ``null``. ```js initRouter(object, '/x/y/z/u/'); object.y = null; // object.z і object.u теж стають null ``` Ідея в тому, щоб властивості відображали актуальний стан URL. Було б дивно отримати ``"z"`` зі значенням ``"foo"``, коли відповідної частини URL немає. #### HTML5 History API Роутер підтримує і HTML5 History. Для цього передайте функції ``initRouter`` необов'язковий аргумент ``type`` зі значенням ``"history"`` (за замовчуванням ``type`` дорівнює ``"hash"``). ```js initRouter(object, '/x/y/z/', 'history'); ``` Роутер читає і пише ``location.pathname``; рядок запиту і хеш залишаються як є. > На сторінці з бандлом, підключеним тегом script, функція доступна як ``Matreshka.initRouter``. **Повертає:** [`object`](https://matreshka.js.org/ua/#type-object) – Перший аргумент ## Аргументи | Ім'я | За замовчуванням | Тип | Опис | | --- | --- | --- | --- | | `object` | | [`object`](https://matreshka.js.org/ua/#type-object) | Об'єкт | | `route` | | [`string`](https://matreshka.js.org/ua/#type-string) | Маршрут: імена властивостей через скісну риску, ``*`` для частини, яка не синхронізується | | `type` (необов'язковий) | `"hash"` | [`string`](https://matreshka.js.org/ua/#type-string) | ``"hash"`` або ``"history"`` | ## Посилання - [`Matreshka.Router`](https://matreshka.js.org/ua/#Matreshka.Router) - [Приклад роутера](https://matreshka.js.org/examples/router/) --- # Matreshka.lookForBinder **Метод** **Імпорт:** ```js import { lookForBinder } from 'matreshka'; ``` ```js Matreshka.lookForBinder(node) → binder ``` Повертає байндер, відповідний елементу. Якщо байндер не знайдений, повертає ``undefined``. Функція перебирає [`Matreshka.defaultBinders`](https://matreshka.js.org/ua/#Matreshka.defaultBinders) для пошуку байндера. **Повертає:** [`binder`](https://matreshka.js.org/ua/#type-binder) – binder ## Аргументи | Ім'я | Тип | Опис | | --- | --- | --- | | `node` | [`node`](https://matreshka.js.org/ua/#type-node) | | ## Посилання - [`Matreshka#bindNode`](https://matreshka.js.org/ua/#Matreshka-bindNode) - [`Matreshka.defaultBinders`](https://matreshka.js.org/ua/#Matreshka.defaultBinders) ## Приклади ```js const element = document.createElement('input'); element.type = 'text'; console.log(Matreshka.lookForBinder(element)); // поверне приблизно такий об'єкт { on: 'input', getValue() { return this.value; }, setValue(v) { this.value = v; } } ``` --- # Matreshka.off **Метод** **Імпорт:** ```js import { off } from 'matreshka'; ``` ```js Matreshka.off() → object ``` Видаляє обробник події Цей статичний метод працює так само, як і [`Matreshka#off`](https://matreshka.js.org/ua/#Matreshka-off) та всі його варіації, але приймає в якості першого аргументу будь-який JavaScript об'єкт. Якщо передати тільки об'єкт, метод видаляє всі обробники, додані через ``on``, ``once`` і ``onDebounce``; прив'язки й залежності ``calc`` залишаються. **Повертає:** [`object`](https://matreshka.js.org/ua/#type-object) – Перший аргумент ## Посилання - [`Matreshka#off`](https://matreshka.js.org/ua/#Matreshka-off) ## Приклади ```js const object = {}; Matreshka.on(object, 'foo', evt => { //... }); Matreshka.off(object, 'foo'); ``` --- # Matreshka.once **Метод** **Імпорт:** ```js import { once } from 'matreshka'; ``` ```js Matreshka.once() → object ``` Додає обробник події, який може бути викликаний лише один раз Цей статичний метод працює так само, як і [`Matreshka#once`](https://matreshka.js.org/ua/#Matreshka-once) та всі його варіації, але приймає в якості першого аргументу будь-який JavaScript об'єкт. **Повертає:** [`object`](https://matreshka.js.org/ua/#type-object) – Перший аргумент ## Посилання - [`Matreshka#once`](https://matreshka.js.org/ua/#Matreshka-once) ## Приклади ```js const object = {}; Matreshka.once(object, 'foo', evt => { //... }); ``` --- # Matreshka.onDebounce **Метод** **Імпорт:** ```js import { onDebounce } from 'matreshka'; ``` ```js Matreshka.onDebounce() → object ``` Додатє обробник події, що викликається лише однин раз за певний проміжок часу Цей статичний метод працює так само, як і [`Matreshka#onDebounce`](https://matreshka.js.org/ua/#Matreshka-onDebounce) та всі його варіації, але приймає в якості першого аргументу будь-який JavaScript об'єкт. **Повертає:** [`object`](https://matreshka.js.org/ua/#type-object) – Перший аргумент ## Посилання - [`Matreshka#onDebounce`](https://matreshka.js.org/ua/#Matreshka-onDebounce) ## Приклади ```js const object = {}; Matreshka.onDebounce(object, 'foo', evt => { //... }); ``` --- # Matreshka.parseBindings **Метод** **Імпорт:** ```js import { parseBindings } from 'matreshka'; ``` ```js Matreshka.parseBindings() → $nodes ``` Парсить DOM дерево, оголошуючи прив'язки властивостей, взятих в подвійні фігурні дужки Цей статичний метод працює так само, як і [`Matreshka#parseBindings`](https://matreshka.js.org/ua/#Matreshka-parseBindings) та всі його варіації, але приймає в якості першого аргументу будь-який JavaScript об'єкт. **Повертає:** [`$nodes`](https://matreshka.js.org/ua/#type-dollar-nodes) – Колекція оброблених DOM вузлів, передана в функцію як аргумент ## Посилання - [`Matreshka#parseBindings`](https://matreshka.js.org/ua/#Matreshka-parseBindings) ## Приклади ```js const object = {}; const $node = Matreshka.parseBindings(object, `

Hello, {{name}}

`); object.name = 'World'; ``` --- # Matreshka.parseForm **Метод** **Імпорт:** ```js import { parseForm } from 'matreshka/parse-form'; ``` ```js Matreshka.parseForm(object, form, [callback], [eventOptions]) → node|null ``` Функція прив'язує іменовані поля HTML форми (input, select, textarea тощо) до відповідних властивостей. ```html
``` ```js const object = {}; parseForm(object, '.my-form'); // ... console.log(object.x); // 'foo' object.x = 'bar'; // змінює значення поля на 'bar' ``` Третій аргумент корисний, коли ``parseForm`` використовується з [`Matreshka.Object`](https://matreshka.js.org/ua/#Matreshka.Object): у ньому можна викликати метод [`Matreshka.Object#addDataKeys`](https://matreshka.js.org/ua/#Matreshka.Object-addDataKeys). ```js const form = parseForm(this, ':sandbox .foo', key => this.addDataKeys(key), { getValueOnBind: false }); ``` > На сторінці з бандлом, підключеним тегом script, функція доступна як ``Matreshka.parseForm``. **Повертає:** [`node`](https://matreshka.js.org/ua/#type-node) \| [`null`](https://matreshka.js.org/ua/#type-null) – Елемент форми або ``null``, якщо форму не знайдено ## Аргументи | Ім'я | Тип | Опис | | --- | --- | --- | | `object` | [`object`](https://matreshka.js.org/ua/#type-object) | Об'єкт | | `form` | [`string`](https://matreshka.js.org/ua/#type-string) \| [`node`](https://matreshka.js.org/ua/#type-node) \| [`$nodes`](https://matreshka.js.org/ua/#type-dollar-nodes) | Селектор, DOM вузол тощо форми (кастомні селектори ``:sandbox`` і ``:bound(KEY)`` теж підходять) | | `callback` (необов'язковий) | [`function`](https://matreshka.js.org/ua/#type-function) | Функція, яка викликається для кожного знайденого поля; отримує ім'я поля і сам елемент | | `eventOptions` (необов'язковий) | [`eventOptions`](https://matreshka.js.org/ua/#type-event-options) | Опції події, які передаються в кожен внутрішній виклик [`Matreshka#bindNode`](https://matreshka.js.org/ua/#Matreshka-bindNode) | ## Посилання - [`Matreshka#bindNode`](https://matreshka.js.org/ua/#Matreshka-bindNode) - [Приклад парсера форм](https://matreshka.js.org/examples/parse-form/) --- # Matreshka.remove **Метод** **Імпорт:** ```js import { remove } from 'matreshka'; ``` ```js Matreshka.remove() → object ``` Видаляє властивість Цей статичний метод працює так само, як і [`Matreshka#remove`](https://matreshka.js.org/ua/#Matreshka-remove) та всі його варіації, але приймає в якості першого аргументу будь-який JavaScript об'єкт. **Повертає:** [`object`](https://matreshka.js.org/ua/#type-object) – Перший аргумент ## Посилання - [`Matreshka#remove`](https://matreshka.js.org/ua/#Matreshka-remove) ## Приклади ```js Matreshka.remove(object, 'x'); ``` --- # Matreshka.select **Метод** **Імпорт:** ```js import { select } from 'matreshka'; ``` ```js Matreshka.select() → node|null ``` Повертає елемент з пісочниці, відповідний селектору Цей статичний метод працює так само, як і [`Matreshka#select`](https://matreshka.js.org/ua/#Matreshka-select) та всі його варіації, але приймає в якості першого аргументу будь-який JavaScript об'єкт. **Повертає:** [`node`](https://matreshka.js.org/ua/#type-node) \| [`null`](https://matreshka.js.org/ua/#type-null) – знайдений елемент ## Посилання - [`Matreshka#select`](https://matreshka.js.org/ua/#Matreshka-select) ## Приклади ```js const object = {}; Matreshka.bindNode(object, 'sandbox', '.app'); Matreshka.select(object, '.my-element'); ``` --- # Matreshka.selectAll **Метод** **Імпорт:** ```js import { selectAll } from 'matreshka'; ``` ```js Matreshka.selectAll() → $nodes ``` Повертає елементи з пісочниці, відповідні селектору Цей статичний метод працює так само, як і [`Matreshka#selectAll`](https://matreshka.js.org/ua/#Matreshka-selectAll) та всі його варіації, але приймає в якості першого аргументу будь-який JavaScript об'єкт. **Повертає:** [`$nodes`](https://matreshka.js.org/ua/#type-dollar-nodes) – найденные элементы ## Посилання - [`Matreshka#selectAll`](https://matreshka.js.org/ua/#Matreshka-selectAll) ## Приклади ```js const object = {}; Matreshka.bindNode(object, 'sandbox', '.app'); Matreshka.selectAll(object, '.my-element'); ``` --- # Matreshka.set **Метод** **Імпорт:** ```js import { set } from 'matreshka'; ``` ```js Matreshka.set() → object ``` Встановлює значення властивості, дозволяючи передати об'єкт події в якості третьої аргументу Цей статичний метод працює так само, як і [`Matreshka#set`](https://matreshka.js.org/ua/#Matreshka-set) та всі його варіації, але приймає в якості першого аргументу будь-який JavaScript об'єкт. **Повертає:** [`object`](https://matreshka.js.org/ua/#type-object) – Перший аргумент ## Посилання - [`Matreshka#set`](https://matreshka.js.org/ua/#Matreshka-set) ## Приклади ```js const object = {}; Matreshka.set(object, 'x', 42, { someOption: true }); ``` --- # Matreshka.toMatreshka **Метод** **Імпорт:** ```js import { toMatreshka } from 'matreshka'; ``` ```js Matreshka.toMatreshka() → matreshka ``` Функція, яка конвертує довільну структуру об'єктів і масивів в екземпляри [`Matreshka.Object`](https://matreshka.js.org/ua/#Matreshka.Object) та [`Matreshka.Array`](https://matreshka.js.org/ua/#Matreshka.Array) Тільки масиви та екземпляри ``Matreshka.Array`` стають ``Matreshka.Array``; будь-який інший об'єкт, навіть з властивістю ``length``, стає ``Matreshka.Object``. З переданого ``Matreshka.Object`` беруться тільки ключі, що відповідають за дані. **Повертає:** [`matreshka`](https://matreshka.js.org/ua/#type-matreshka) – новостворений екземпляр ``Matreshka`` ## Приклади ```js const matreshka = Matreshka.toMatreshka({ a: 1, b: { c: 2 }, d: [{e: 1}, {e: 2}, {e: 3}] }); ``` --- # Matreshka.trigger **Метод** **Імпорт:** ```js import { trigger } from 'matreshka'; ``` ```js Matreshka.trigger() → object ``` Генерує подію Цей статичний метод працює так само, як і [`Matreshka#trigger`](https://matreshka.js.org/ua/#Matreshka-trigger) та всі його варіації, але приймає в якості першого аргументу будь-який JavaScript об'єкт. **Повертає:** [`object`](https://matreshka.js.org/ua/#type-object) – Перший аргумент ## Посилання - [`Matreshka#trigger`](https://matreshka.js.org/ua/#Matreshka-trigger) ## Приклади ```js const object = {}; Matreshka.on(object, 'foo', evt => { alert(evt.hello); }); Matreshka.trigger(object, 'foo', { hello: 'World' }); ``` --- # Matreshka.unbindNode **Метод** **Імпорт:** ```js import { unbindNode } from 'matreshka'; ``` ```js Matreshka.unbindNode() → object ``` Розриває зв'язок між властивістю і HTML елементом Цей статичний метод працює так само, як і [`Matreshka#unbindNode`](https://matreshka.js.org/ua/#Matreshka-unbindNode) та всі його варіації, але приймає в якості першого аргументу будь-який JavaScript об'єкт. **Повертає:** [`object`](https://matreshka.js.org/ua/#type-object) – Перший аргумент ## Посилання - [`Matreshka#unbindNode`](https://matreshka.js.org/ua/#Matreshka-unbindNode) ## Приклади ```js const object = {}; Matreshka.unbindNode(object, 'x', '.my-node'); ``` --- # Matreshka.defaultBinders **Властивість** **Імпорт:** ```js import { defaultBinders } from 'matreshka'; ``` ```js Matreshka.defaultBinders: array ``` Масив функцій, які повертають відповідний Байндер або ``undefined`` ``defaultBinders`` - масив функцій, які по черзі перевіряють елемент на відповідність заданим в цих функціях правилам і повертають байндер (див. [`binder`](https://matreshka.js.org/ua/#type-binder)). Цей масив використовується тоді, коли в метод [`Matreshka#bindNode`](https://matreshka.js.org/ua/#Matreshka-bindNode) не був переданий третій аргумент. Детальну інформацію про байндінги дивіться в документації до [`Matreshka#bindNode`](https://matreshka.js.org/ua/#Matreshka-bindNode). ## Посилання - [`Matreshka#bindNode`](https://matreshka.js.org/ua/#Matreshka-bindNode) - [`Matreshka.lookForBinder`](https://matreshka.js.org/ua/#Matreshka.lookForBinder) ## Приклади ```js Matreshka.defaultBinders.unshift(element => { // перевіряємо, чи є у елемента клас "foo" if(element.classList.contains('foo')) { // якщо перевірка пройдена, повертаємо новий байндер return { on: ..., getValue: ..., setValue: ... }; } }); // ... this.bindNode('myKey', '.foo.bar'); ``` --- # Matreshka.parserBrackets **Властивість** **Імпорт:** ```js import { parserBrackets } from 'matreshka'; ``` ```js Matreshka.parserBrackets: object ``` Містить дужки для [парсера](https://matreshka.js.org/ua/#Matreshka-parseBindings) Об'єкт ``parserBrackets`` дозволяє змінити стандартний синтаксис парсеру прив'язок. Він містить дві властивості: ``left`` (ліва дужка, за замовчуванням "\{\{") і ``right`` (права дужка, за замовчуванням "\}\}") Дужками можуть бути будь-які символи. ## Приклади **Замінює поведінку парсеру, використовуючи синтаксис ``[[=property]]`` замість ``{{property}}``** ```js Matreshka.parserBrackets.left = '[[='; Matreshka.parserBrackets.right = ']]'; ``` --- # Matreshka.Object **Клас** · extends `Matreshka` **Імпорт:** ```js import { MatreshkaObject } from 'matreshka'; ``` ``Matreshka.Object`` - клас, який відповідає за дані вида ключ-значення. Його завданням є відділення службових властивостей від даних, які можна передати на сервер або зберегти в локальному сховищі. Клас успадковується від класу [`Matreshka`](https://matreshka.js.org/ua/#Matreshka) і включає всі його властивості та методи. Уявіть собі, що ви створюєте клас, що включає властивості ``"a"``, ``"b"`` і ``"c"``. Припустимо ``"a"`` і ``"b"`` - це властивості які повинні бути відправлені на сервер, а властивість ``"c"`` лише відповідає за деякий стан програми (наприклад, містить суму ``"a"`` і ``"b"``). Властивість ``"c"`` не повинна бути відправлена на сервер. Тому нам потрібно відокремити **властивості, які відповідають за дані**. Для того, щоб відокремити такі властивості від інших, можна скористатися методом [`Matreshka.Object#addDataKeys`](https://matreshka.js.org/ua/#Matreshka.Object-addDataKeys). ```js this.addDataKeys(['a', 'b']); this.a = 1; this.b = 2; this.c = 3; ``` Якщо ви заздалегідь не знаєте, які властивості є даними, можна завжди використовувати метод [`Matreshka.Object#setData`](https://matreshka.js.org/ua/#Matreshka.Object-setData), який не тільки оголошує властивості, що відповідають за дані, але і відразу встановлює значення. ```js this.setData({ a: 1, b: 2 }); this.c = 3; ``` Після того, як додаток отримав інформацію про те, що є даними, екземпляр [`Matreshka.Object`](https://matreshka.js.org/ua/#Matreshka.Object) можна конвертувати в звичайний об'єкт методом [`Matreshka.Object#toJSON`](https://matreshka.js.org/ua/#Matreshka.Object-toJSON) і передати на сервер або зберегти в локальній БД (наприклад, в ``localStorage``). ```js // поверне об'єкт { a: 1, b: 2 } this.toJSON(); ``` #### Події При додаванні і зміні властивостей, що відповідають за дані генеруються події ``set`` і ``modify``, при видаленні - ``remove`` і ``modify``. Тобто будь-які зміни даних можна слухати за допомогою ``modify``. ```js this.on('modify', () => { alert('Object is modified'); }); ``` ## Аргументи | Ім'я | Тип | Опис | | --- | --- | --- | | `data` (необов'язковий) | [`object`](https://matreshka.js.org/ua/#type-object) | Дані, що входять в новий екземпляр | ## Приклади **Створення екземпляра з двома властивостями-даними** ```js // те ж саме, що і new Matreshka.Object().setData({ a: 1, b: 2 }); new Matreshka.Object({ a: 1, b: 2 }); ``` **Спадкування** ```js class MyClass extends Matreshka.Object { constructor(data) { super(data).sayHello(); } sayHello() { alert("Hello World!"); } } ``` **Спадкування за допомогою функції [`Matreshka.Class`](https://matreshka.js.org/ua/#Matreshka.Class)** ```js const MyClass = Matreshka.Class({ extends: Matreshka.Object, constructor(data) { this.setData(data).sayHello(); }, sayHello() { alert("Hello World!"); } }); ``` **Перебір даних, використовуючи цикл for..of** ```js const matreshkaObject = new Matreshka.Object({ a: 1, b: 2 }); for(let item of matreshkaObject) { console.log(item); // 1 .. 2 } ``` ## Методи і властивості - [`addDataKeys`](https://matreshka.js.org/ua/#Matreshka.Object-addDataKeys) – Додає задані імена властивостей в список імен властивостей, що відповідають за дані - [`each`](https://matreshka.js.org/ua/#Matreshka.Object-each) – Перебирає властивості, що відповідають за дані - [`entries`](https://matreshka.js.org/ua/#Matreshka.Object-entries) – Повертає масив пар імен і значень властивостей, що відповідають за дані - [`isDataKey`](https://matreshka.js.org/ua/#Matreshka.Object-isDataKey) – Перевіряє, чи входить строка до списку імен властивостей, що відповідають за дані - [`isMatreshkaObject`](https://matreshka.js.org/ua/#Matreshka.Object-isMatreshkaObject) – Властивість ``isMatreshkaObject`` завжди дорівнює ``true`` для екземплярів [`Matreshka.Object`](https://matreshka.js.org/ua/#Matreshka.Object). - [`keyOf`](https://matreshka.js.org/ua/#Matreshka.Object-keyOf) – Шукає задане значення властивості серед властивостей, що відповідають за дані, і повертає ім'я властивості, якщо таке значення знайдено - [`keys`](https://matreshka.js.org/ua/#Matreshka.Object-keys) – Повертає масив імен властивостей, що відповідають за дані - [`removeDataKeys`](https://matreshka.js.org/ua/#Matreshka.Object-removeDataKeys) – Видаляє задані імена властивостей зі списку імен властивостей, що відповідають за дані (але не видаляє властивість) - [`setData`](https://matreshka.js.org/ua/#Matreshka.Object-setData) – Встановлює значення властивості і додає його ім'я в список імен властивостей, що відповідають за дані - [`toJSON`](https://matreshka.js.org/ua/#Matreshka.Object-toJSON) – Конвертує екземпляр [`Matreshka.Object`](https://matreshka.js.org/ua/#Matreshka.Object) в звичайний об'єкт - [`values`](https://matreshka.js.org/ua/#Matreshka.Object-values) – Повертає масив значень властивостей, що відповідають за дані --- # Matreshka.Object#addDataKeys **Метод** ```js Matreshka.Object#addDataKeys(keys) → matreshkaObject ``` Додає задані імена властивостей в список імен властивостей, що відповідають за дані Цей метод застосовується тоді, коли потрібно оголосити властивості, що відповідають за дані, але значення цих властивостей ще не відомі. **Повертає:** [`matreshkaObject`](https://matreshka.js.org/ua/#type-matreshka-object) – self **Генерує події:** `set`, `modify` ## Аргументи | Ім'я | Тип | Опис | | --- | --- | --- | | `keys` | [`string`](https://matreshka.js.org/ua/#type-string) \| [`array`](https://matreshka.js.org/ua/#type-array) | Масив імен властивостей або список аргументів з іменами властивостей | ## Приклади ```js this.addDataKeys(['a', 'b']); ``` ```js this.addDataKeys('a', 'b'); ``` --- # Matreshka.Object#each **Метод** ```js Matreshka.Object#each(callback, [thisArg]) → matreshkaObject ``` Перебирає властивості, що відповідають за дані Метод дуже схожий на ``Array.prototype.forEach`` і є альтернативою циклу for..of. **Повертає:** [`matreshkaObject`](https://matreshka.js.org/ua/#type-matreshka-object) – self ## Аргументи | Ім'я | Тип | Опис | | --- | --- | --- | | `callback` | [`function`](https://matreshka.js.org/ua/#type-function) | Функція, яка викликається на кожній ітерації | | `thisArg` (необов'язковий) | [`*`](https://matreshka.js.org/ua/#type-any) | Контекст функції | ## Приклади ```js this .setData({ a: 1, b: 2 }) .addDataKeys('c') .each((value, key) => { console.log(key, value); }); ; // >>> a 1, b 2, c undefined ``` --- # Matreshka.Object#isDataKey **Метод** ```js Matreshka.Object#isDataKey(key) → boolean ``` Перевіряє, чи входить строка до списку імен властивостей, що відповідають за дані **Повертає:** [`boolean`](https://matreshka.js.org/ua/#type-boolean) – результат перевірки ## Аргументи | Ім'я | Тип | Опис | | --- | --- | --- | | `key` | [`string`](https://matreshka.js.org/ua/#type-string) | | ## Приклади ```js console.log(this.isDataKey('a')); ``` --- # Matreshka.Object#keyOf **Метод** ```js Matreshka.Object#keyOf() → string|null ``` Шукає задане значення властивості серед властивостей, що відповідають за дані, і повертає ім'я властивості, якщо таке значення знайдено **Повертає:** [`string`](https://matreshka.js.org/ua/#type-string) \| [`null`](https://matreshka.js.org/ua/#type-null) – перше знайдене ім'я властивості ## Властивості | Ім'я | Тип | Опис | | --- | --- | --- | | `value` | [`*`](https://matreshka.js.org/ua/#type-any) | значення будь-якого типу, яке слід знайти серед даних | ## Приклади ```js const matreshkaObject = new Matreshka.Object({ a: 1, b: 2 }); matreshkaObject.c = 3; matreshkaObject.keyOf(1); // 'a' matreshkaObject.keyOf(2); // 'b' matreshkaObject.keyOf(3); // null ``` --- # Matreshka.Object#keys **Метод** ```js Matreshka.Object#keys() → array ``` Повертає масив імен властивостей, що відповідають за дані **Повертає:** [`array`](https://matreshka.js.org/ua/#type-array) – keys ## Приклади ```js const keys = this.keys(); ``` --- # Matreshka.Object#removeDataKeys **Метод** ```js Matreshka.Object#removeDataKeys(keys) → matreshkaObject ``` Видаляє задані імена властивостей зі списку імен властивостей, що відповідають за дані (але не видаляє властивість) Подія ``remove`` генерується раніше за ``modify``, як і в [`Matreshka#remove`](https://matreshka.js.org/ua/#Matreshka-remove). **Повертає:** [`matreshkaObject`](https://matreshka.js.org/ua/#type-matreshka-object) – self **Генерує події:** `remove`, `modify` ## Аргументи | Ім'я | Тип | Опис | | --- | --- | --- | | `keys` | [`string`](https://matreshka.js.org/ua/#type-string) \| [`array`](https://matreshka.js.org/ua/#type-array) | Масив імен властивостей або список аргументів з іменами властивостей | ## Приклади ```js this.removeDataKeys(['a', 'b']); ``` ```js this.removeDataKeys('a', 'b'); ``` --- # Matreshka.Object#setData **Метод** ```js Matreshka.Object#setData(key, value, [eventOptions]) → matreshkaObject ``` Встановлює значення властивості і додає його ім'я в список імен властивостей, що відповідають за дані Синонім: `Matreshka.Object#jset` Цей метод робить дві речі: 1. Встановлює значення заданої властивості. 2. Додає ключ властивості в список даних, що робить властивість доступною для використання в методах [`Matreshka.Object#each`](https://matreshka.js.org/ua/#Matreshka.Object-each), [`Matreshka.Object#keys`](https://matreshka.js.org/ua/#Matreshka.Object-keys), [`Matreshka.Object#toJSON`](https://matreshka.js.org/ua/#Matreshka.Object-toJSON)) та інших. > Якщо передати прапор ``replaceData``, встановлений як ``true``, в об'єкт події, то інші властивості будуть вилучені зі списку властивостей, що відповідають за дані. В іншому, метод працює так само, як і [`Matreshka#set`](https://matreshka.js.org/ua/#Matreshka-set). **Повертає:** [`matreshkaObject`](https://matreshka.js.org/ua/#type-matreshka-object) – self **Генерує події:** `change`, `change:KEY`, `modify`, `set` ## Аргументи | Ім'я | Тип | Опис | | --- | --- | --- | | `key` | [`string`](https://matreshka.js.org/ua/#type-string) | Ключ | | `value` | [`*`](https://matreshka.js.org/ua/#type-any) | Значення | | `eventOptions` (необов'язковий) | [`eventOptions`](https://matreshka.js.org/ua/#type-event-options) | Об'єкт події | ## Посилання - [`Matreshka#set`](https://matreshka.js.org/ua/#Matreshka-set) ## Приклади ```js this.setData('a', 1).setData('b', 2); // Присвоювання властивості 'c' трійку, // але не додаємо ключ 'c' в список ключів, що відповідають за дані this.set('c', 3); this.each((value, key) => { console.log(key, value); }); // виводить 'a' 1 і 'b' 2 console.log(this.keys()); // виводить ['a', 'b'] console.log(this.toJSON()); // виводить { a: 1, b: 2 } ``` **Після використання методу ``setData`` з властивістю можна працювати, як із звичайною властивістю** ```js this.setData('a', 1).setData('b', 2); this.set('a', 3); this.b = 4; ``` **Використання альтернативного імені методу: ``jset``** ```js this.jset('a', 1); ``` ## Альтернативний синтаксис методу Matreshka.Object#setData, який приймає об'єкт ключ-значення для встановлення декількох властивостей одночасно ```js Matreshka.Object#setData(keyValuePairs, evtOpts) → matreshkaObject ``` **Повертає:** [`matreshkaObject`](https://matreshka.js.org/ua/#type-matreshka-object) – self ### Аргументи | Ім'я | Тип | Опис | | --- | --- | --- | | `keyValuePairs` | [`object`](https://matreshka.js.org/ua/#type-object) | Об'єкт ключ-значення | | `evtOpts` | [`eventOptions`](https://matreshka.js.org/ua/#type-event-options) | Об'єкт події | ### Приклади ```js this.setData({ a: 1, b: 2 }); ``` **Якщо передати прапор ``replaceData``, встановлений як ``true`` в об'єкт події, то властивості, які не входять до переданого об'єкту, будуть вилучені зі списку властивостей, що відповідають за дані** ```js this .addDataKeys(['a', 'b', 'c']) .setData({ a: 1, b: 2 }, { replaceData: true }); console.log(this.keys()); // ['a', 'b'] ``` --- # Matreshka.Object#toJSON **Метод** ```js Matreshka.Object#toJSON([recursive=true]) → object ``` Конвертує екземпляр [`Matreshka.Object`](https://matreshka.js.org/ua/#Matreshka.Object) в звичайний об'єкт Метод працює рекурсивно, викликаючи ``toJSON`` для всіх властивостей, у яких є метод з таким ім'ям. Для скасування рекурсії передайте ``false`` першим аргументом. **Повертає:** [`object`](https://matreshka.js.org/ua/#type-object) ## Аргументи | Ім'я | За замовчуванням | Тип | Опис | | --- | --- | --- | --- | | `recursive` (необов'язковий) | `true` | [`boolean`](https://matreshka.js.org/ua/#type-boolean) | | ## Приклади ```js const matreshkaObject = new Matreshka.Object({ a: 1, b: 2, c: new Matreshka.Object({ d: 3, e: 4 }) }); // повертає {a: 1, b: 2, c: { d: 3, e: 4 }} console.log(matreshkaObject.toJSON()); // повертає {a: 1, b: 2, c: MatreshkaObject} console.log(matreshkaObject.toJSON(false)); ``` --- # Matreshka.Object#entries **Метод** ```js Matreshka.Object#entries() → array ``` Повертає масив пар імен і значень властивостей, що відповідають за дані **Повертає:** [`array`](https://matreshka.js.org/ua/#type-array) – entries ## Приклади ```js for(const [key, value] of this.entries()) { console.log(key, value); } ``` --- # Matreshka.Object#values **Метод** ```js Matreshka.Object#values() → array ``` Повертає масив значень властивостей, що відповідають за дані **Повертає:** [`array`](https://matreshka.js.org/ua/#type-array) – values ## Приклади ```js const values = this.values(); ``` --- # Matreshka.Object#isMatreshkaObject **Властивість** ```js Matreshka.Object#isMatreshkaObject: boolean ``` Властивість ``isMatreshkaObject`` завжди дорівнює ``true`` для екземплярів [`Matreshka.Object`](https://matreshka.js.org/ua/#Matreshka.Object). ## Приклади ```js console.log(object.isMatreshkaObject); ``` --- # Matreshka.Array **Клас** · extends `Matreshka` **Імпорт:** ```js import { MatreshkaArray } from 'matreshka'; ``` Клас ``Matreshka.Array`` служить колекцією в Matreshka.js. Він успадковується від класу [`Matreshka`](https://matreshka.js.org/ua/#Matreshka) і включає всі його властивості та методи. Крім цього, ``Matreshka.Array`` має всі методи, які є у звичайного масиву, тим самим спрощуючи вивчення його можливостей. #### Всі методи, запозичені у вбудованого Array працюють аналогічно їх оригіналам Програміст, знайомий з методами нативного `` Array`` відразу може зрозуміти, яким методом можна додати елемент (``push``, ``unshift``, ``splice``), яким видалити (``pop``, ``shift``, ``splice``), яким впорядкувати (``sort``, ``reverse``) тощо. У зв'язку з тим, що методи працюють так само, як і оригінальні (з невеликими винятками), вони не приведені в цій документації окремо, а виведені в розділ [`Matreshka.Array#METHOD`](https://matreshka.js.org/ua/#Matreshka.Array-METHOD). ```js this.push(1, 2, 3); this.pop(); ``` #### Всі методи, запозичені у вбудованого Array, які модифікують масив можуть бути викликані з передачею об'єкта події Для цього використовується синтаксис ``метод_``, де нижнє підкреслення в кінці імені методу означає, що останнім аргументом є об'єкт події. Такі методи не наведено в цій документації, так як потрібно запам'ятати тільки їх синтаксис. Див. [`Matreshka.Array#METHOD_`](https://matreshka.js.org/ua/#Matreshka.Array-METHOD_). ```js this.push_(1, 2, 3, { silent: true }); this.pop_({ foo: 'bar' }); ``` #### Розробник має можливість відловлювати будь-які модифікації даних __При використанні методів, запозичених у вбудованого ``Array`` генеруються події з відповідним ім'ям.__ Викликаючи метод ``push``, генерується подія ``push``, викликаючи метод ``shift`` генерується подія ``shift``, викликаючи метод ``sort``, генерується подія ``sort`` і так далі. ```js this.on('push', evt => { console.log('push is called'); }); this.push(1, 2, 3); ``` __При додаванні елементів генеруються події ``add`` і ``addone``.__ Перше генерується один раз на додавання (наприклад, ви додали кілька елементів за допомогою ``push``, подія викликана лише один раз), друге генерується один раз на кожен доданий елемент. При спрацьовуванні події ``add``, значенням властивості ``added`` об'єкта події передається масив доданих елементів, а при спрацьовуванні ``addone``, значенням властивості ``addedItem`` - кожен окремий доданий елемент. ```js this.on('add', evt => { console.log(evt.added); // [1,2,3] }); this.push(1, 2, 3); ``` ```js // Обробник запуститься тричі, // так як в масив додали три нові елементи this.on('addone', evt => { console.log(evt.addedItem); // 1 ... 2 ... 3 }); this.push(1, 2, 3); ``` __При видаленні елементів діє та ж логіка__: ``remove`` спрацьовує один раз, навіть якщо видалено кілька елементів, а подія ``removeone`` спрацьовує для кожного віддаленого елемента індивідуально. При генерації події ``remove`` вилучені елементи містяться у властивості ``removed`` об'єкта події, а при генерації події ``removeone`` - кожен віддалений елемент міститься у властивості ``removedItem``. ```js this.push(1, 2, 3, 4, 5); this.on('remove', evt => { console.log(evt.removed); // [2, 3, 4] }); this.splice(1, 3); ``` ```js this.push(1, 2, 3, 4, 5); // Обробник запуститься тричі, // так як з масиву видалили три елементи this.on('removeone', evt => { console.log(evt.removedItem); // 2 ... 3 ... 4 }); this.splice(1, 3); ``` __Приі кожної модифікації масиву генерується подія ``modify``__, дозволяючи відловити всі без винятку зміни в масиві (додавання, видалення, пересортовування). ```js this.on('modify', evt => { console.log(evt.added); console.log(evt.removed); }); ``` __``length`` - це звичайне свойство__ яке можна пов'язувати з HTML елементом або відловлювати зміни за допомогою події ``change:length``. > Наприклад, при додаванні трьох елементів за допомогою методу ``push``, генеруються наступні події: ``push``, ``add``, ``addone`` (тричі), ``modify``, ``change:length``. #### Model Властивість [`Matreshka.Array#Model`](https://matreshka.js.org/ua/#Matreshka.Array-Model) визначає клас елементів, які буде містити колекція. Рекомендується наслідувати ``Model`` від класу [`Matreshka.Object`](https://matreshka.js.org/ua/#Matreshka.Object) або [`Matreshka.Array`](https://matreshka.js.org/ua/#Matreshka.Array) (на випадок, якщо потрібно отримати колекцію колекцій), щоб отримати можливість конвертації масиву в звичайний масив рекурсивно методом [`Matreshka.Array#toJSON`](https://matreshka.js.org/ua/#Matreshka.Array-toJSON). #### Автоматичний рендеринг ``Matreshka.Array`` вміє автоматично відмальовувати елементи на сторінці при будь-яких модифікаціях масиву. За подробицями зверніться до документації [`Matreshka.Array#itemRenderer`](https://matreshka.js.org/ua/#Matreshka.Array-itemRenderer). ## Посилання - [`Matreshka.Array#itemRenderer`](https://matreshka.js.org/ua/#Matreshka.Array-itemRenderer) - [`Matreshka.Array#Model`](https://matreshka.js.org/ua/#Matreshka.Array-Model) ## Приклади **Створення екземпляра з нульовою довжиною** ```js new Matreshka.Array(); ``` **Створення екземпляра із зазначенням довжини** ```js new Matreshka.Array(42); ``` Як і нативний ``Array``, одне число, яке не є допустимою довжиною (від'ємне, дробове або ``NaN``), кидає ``RangeError``. **Передача елементів при створенні** ```js new Matreshka.Array('Hi', { a: 'b' }); ``` **Спадкування** ```js class MyClass extends Matreshka.Array { constructor(items) { super(...items).sayHello(); } sayHello() { alert("Hello World!"); } } ``` **Спадкування, використовуючи функцію [`Matreshka.Class`](https://matreshka.js.org/ua/#Matreshka.Class)** ```js const MyClass = Matreshka.Class({ extends: Matreshka.Array, constructor(items) { this.recreate(items).sayHello(); }, sayHello() { alert("Hello World!"); } }); ``` ## Методи і властивості - [`METHOD`](https://matreshka.js.org/ua/#Matreshka.Array-METHOD) – Будь-який метод із ``Array.prototype`` - [`METHOD_`](https://matreshka.js.org/ua/#Matreshka.Array-METHOD_) – Будь-який метод із ``Array.prototype`` з можливістю передати об'єкт події - [`Model`](https://matreshka.js.org/ua/#Matreshka.Array-Model) – Властивість визначає клас елементів, які буде містити колекція - [`isMatreshkaArray`](https://matreshka.js.org/ua/#Matreshka.Array-isMatreshkaArray) – ``isMatreshkaArray`` завжди дорівнює ``true`` для экземплярів [`Matreshka.Array`](https://matreshka.js.org/ua/#Matreshka.Array) - [`itemRenderer`](https://matreshka.js.org/ua/#Matreshka.Array-itemRenderer) – HTML строка, селектор або функція, яка відповідає за рендерінг элементів масива на сторінці - [`mediateItem`](https://matreshka.js.org/ua/#Matreshka.Array-mediateItem) – Трансформує значення елементів масиву - [`onItemRender`](https://matreshka.js.org/ua/#Matreshka.Array-onItemRender) – Функція, яка запускається перед подією ``render``. - [`orderBy`](https://matreshka.js.org/ua/#Matreshka.Array-orderBy) – Сортує масив за значеннями властивостей об'єктів, які в нього входять - [`pull`](https://matreshka.js.org/ua/#Matreshka.Array-pull) – Видаляє елемент за індексом або за значенням - [`recreate`](https://matreshka.js.org/ua/#Matreshka.Array-recreate) – Перестворює екземпляр [`Matreshka.Array`](https://matreshka.js.org/ua/#Matreshka.Array) - [`renderIfPossible`](https://matreshka.js.org/ua/#Matreshka.Array-renderIfPossible) – Властивість ``renderIfPossible`` скасовує рендеринг масиву якщо має значення `` false`` - [`rerender`](https://matreshka.js.org/ua/#Matreshka.Array-rerender) – Перемальовує DOM вузли об'єктів, що входять в масив - [`restore`](https://matreshka.js.org/ua/#Matreshka.Array-restore) – Відтворює [`Matreshka.Array`](https://matreshka.js.org/ua/#Matreshka.Array) з HTML вузлів на сторінці. - [`toJSON`](https://matreshka.js.org/ua/#Matreshka.Array-toJSON) – Конвертує екземпляр [`Matreshka.Array`](https://matreshka.js.org/ua/#Matreshka.Array) в звичайний масив - [`trackBy`](https://matreshka.js.org/ua/#Matreshka.Array-trackBy) – Властивість ``trackBy`` вказує на ім'я властивості ідентифікатора об'єктів, що входять в масив - [`from`](https://matreshka.js.org/ua/#Matreshka.Array.from) – Метод створює новий екземпляр [`Matreshka.Array`](https://matreshka.js.org/ua/#Matreshka.Array) з масивоподібного або ітеруємого об'єкта - [`of`](https://matreshka.js.org/ua/#Matreshka.Array.of) – Метод створює новий екземпляр [`Matreshka.Array`](https://matreshka.js.org/ua/#Matreshka.Array) з довільного числа агрумент, незалежно від числа або типу аргументів --- # Matreshka.Array#mediateItem **Метод** ```js Matreshka.Array#mediateItem(mediator) ``` Трансформує значення елементів масиву Цей метод служить для того, щоб перехопити і трансформувати додані в масив елементи. Зверніть увагу, метод перевизначає властивість [`Matreshka.Array#Model`](https://matreshka.js.org/ua/#Matreshka.Array-Model). Виклик методу конвертує елементи, які вже є в масиві, і замінює їх відрендерені вузли; події при цьому не генеруються. ## Аргументи | Ім'я | Тип | Опис | | --- | --- | --- | | `mediator` | [`function`](https://matreshka.js.org/ua/#type-function) | Функція, що повертає трансформований елемент масиву | ## Посилання - [`Matreshka.Array#Model`](https://matreshka.js.org/ua/#Matreshka.Array-Model) - [`Matreshka#mediate`](https://matreshka.js.org/ua/#Matreshka-mediate) ## Приклади ```js // всі елементи масиву - цілі числа this.mediateItem(item => parseInt(item) || 0); ``` ```js this.push(1, 2, 3, 4, 5); // всі елементи масиву - строки this.mediateItem(String); this.push(6, 7); this.unshift(true, {}); // ["true", "[object Object]", "1", "2", "3", "4", "5", "6", "7"] console.log(matreshkaArray.toJSON()); ``` ```js this.mediateItem(item => { if(item.something) { return new FirstModel(item); } else { return new SecondModel(item); } }); ``` --- # Matreshka.Array#METHOD **Метод** ```js Matreshka.Array#METHOD() ``` Будь-який метод із ``Array.prototype`` [`Matreshka.Array`](https://matreshka.js.org/ua/#Matreshka.Array) включає в себе всі методи, що входять в нативний JavaScript масив: - [join](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/join) - [pop](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/pop) - [push](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/push) - [reverse](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/reverse) - [shift](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/shift) - [unshift](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/unshift) - [slice](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/slice) - [splice](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/splice) - [sort](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort) - [filter](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter) - [forEach](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach) - [some](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/some) - [every](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/every) - [map](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map) - [indexOf](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/indexOf) - [lastIndexOf](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/lastIndexOf) - [reduce](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/reduce) - [reduceRight](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/reduceRight) - [copyWithin](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/copyWithin) - [find](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/find) - [findIndex](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/findIndex) - [fill](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/fill) - [includes](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/includes) - [entries](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/entries) - [keys](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/keys) - [concat](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/concat) При цьому, вони працюють точно так же, як і методи `` Array.prototype``. Є лише кілька застережень: - Метод `` forEach`` повертає себе замість ``undefined`` - Методи, які в оригінальному вигляді повертають новий масив (``splice``, ``slice``, ``filter``, ``map`` ...), повертають новий екземпляр ``Matreshka.Array``. - Методи ``keys``, ``values`` та ``entries`` повертають масив замість ітератора. - ``fill`` передає замінені елементи як ``removed`` у події ``remove`` і ``modify``, а ``added`` містить по одному елементу на кожен заповнений індекс. - ``fill`` і ``copyWithin`` кидають помилку на відрендереному масиві (у якого є ``container`` або ``sandbox``). Крім усього, методи генерують події пов'язані з будь-якою модифікацією масиву. Детальніше див. [`Matreshka.Array`](https://matreshka.js.org/ua/#Matreshka.Array). ## Посилання - [`Matreshka.Array#METHOD_`](https://matreshka.js.org/ua/#Matreshka.Array-METHOD_) ## Приклади ```js this.push(1, 2, 3); ``` ```js const matreshkaArray = this .forEach((value, index) => { //... }) .map((value, index) => { //... }); console.log(matreshkaArray.isMatreshkaArray); // true ``` ```js this.reverse(); ``` --- # Matreshka.Array#METHOD_ **Метод** ```js Matreshka.Array#METHOD_() ``` Будь-який метод із ``Array.prototype`` з можливістю передати об'єкт події Ознайомившись з [`Matreshka.Array#METHOD`](https://matreshka.js.org/ua/#Matreshka.Array-METHOD) стає зрозуміло, що методи не підтримують передачу об'єкта події, так як в точності повторюють синтаксис і кількість аргументів методів вбудованого ``Array``. Синтаксис ``МЕТОД_`` дозволяє передати в обробник події якісь дані або встановити службові прапори, що відповідають за поведінку масиву після виклику методу. Службові прапори: - ``silent`` - відключає генерацію подій - ``dontRender`` - відключає [рендеринг](https://matreshka.js.org/ua/#Matreshka.Array-itemRenderer) - ``skipItemMediator`` - відключає [медіатори](https://matreshka.js.org/ua/#Matreshka.Array-mediateItem) ## Посилання - [`Matreshka.Array#METHOD`](https://matreshka.js.org/ua/#Matreshka.Array-METHOD) ## Приклади ```js this.push_(1, 2, 3, { silent: true }); this.pop_({ silent: true }); ``` ```js this.on('modify', evt => { alert(evt.flag); // 42 }); this.push_(1, 2, 3, { flag: 42 }); ``` --- # Matreshka.Array#Model **Метод** · Визначається вами ```js Matreshka.Array#Model(data, matreshkaArray, index) ``` Властивість визначає клас елементів, які буде містити колекція При кожному додаванні елементів в масив, вбудований обробник перевіряє, чи є доданий елемент екземпляром ``Model`` і конвертує його в такий, якщо перевірка не пройдена. Рекомендується наслідувати ``Model`` від класу [`Matreshka.Object`](https://matreshka.js.org/ua/#Matreshka.Object) або [`Matreshka.Array`](https://matreshka.js.org/ua/#Matreshka.Array) (на випадок, якщо потрібно отримати колекцію колекцій), щоб отримати можливість конвертації масиву в звичайний масив методом [`Matreshka.Array#toJSON`](https://matreshka.js.org/ua/#Matreshka.Array-toJSON). Для більш гнучкого контролю класу елементів (наприклад, якщо для одних елементів потрібно використовувати одну "модель", а для інших - іншу), використовуйте [`Matreshka.Array#mediateItem`](https://matreshka.js.org/ua/#Matreshka.Array-mediateItem). ``Model`` можна оголосити як поле класу (``Model = MyModel;``), а не лише як геттер. Поля класу встановлюються після повернення з ``super(...)``, тому елементи, передані в ``super(...)``, конвертуються, коли масив наступного разу змінює якийсь метод; геттер ``get Model()`` конвертує їх одразу. Якщо змінити ``Model`` пізніше, елементи, які вже є в масиві, конвертуються, а їх відрендерені вузли замінюються. ## Аргументи | Ім'я | Тип | Опис | | --- | --- | --- | | `data` | [`object`](https://matreshka.js.org/ua/#type-object) | Дані, передані в конструктор | | `matreshkaArray` | [`matreshkaArray`](https://matreshka.js.org/ua/#type-matreshka-array) | Масив, в який додали елемент | | `index` | [`number`](https://matreshka.js.org/ua/#type-number) | Поточний індекс об'єкта в батьківському масиві | ## Посилання - [`Matreshka.Array#mediateItem`](https://matreshka.js.org/ua/#Matreshka.Array-mediateItem) - [`Matreshka.Array#itemRenderer`](https://matreshka.js.org/ua/#Matreshka.Array-itemRenderer) ## Приклади ```js // визначаємо "модель" class MyModel extends Matreshka.Object { constructor(data, parentArray, index) { super(data); this.doSomething(); } doSomething() { ... } } // визначаємо клас для колекції class MyArray extends Matreshka.Array { get Model() { return MyModel; } } // створюємо екземпляр класу const myArray = new MyArray(); // додаємо два елементи myArray.push({ a: 1, b: 2 }, { a: 3, b: 4 }); console.log(myArray[0] instanceof MyModel); // true console.log(myArray[1] instanceof MyModel); // true // поверне [{ a: 1, b: 2 }, { a: 3, b: 4 }] myArray.toJSON(); ``` --- # Matreshka.Array#onItemRender **Метод** · Визначається вами ```js Matreshka.Array#onItemRender(item, renderEvent) ``` Функція, яка запускається перед подією ``render``. Віртуальний метод ``onItemRender`` можна використовувати в якості заміни події ``render``. При цьому, у вставленого айтема викликається віртуальний метод ``onRender`` з єдиним аргументом - об'єктом події. ## Аргументи | Ім'я | Тип | Опис | | --- | --- | --- | | `item` | [`object`](https://matreshka.js.org/ua/#type-object) | Елемент колекції | | `renderEvent` | [`object`](https://matreshka.js.org/ua/#type-object) | Об'єкт події ``render`` | ## Приклади ```js class MyModel extends Matreshka.Object { constructor(data) { super(data); } onRender(renderEvt) { this.bindNode('isChecked', ':sandbox .my-checkbox'); this.bindNode('text', ':sandbox .text', Matreshka.binders.html()); } } class MyArray extends Matreshka.Array { get Model() { return MyModel; } itemRenderer() { return '
  • ' } constructor() { super().bindNode('sandbox', '.my-form'); } onItemRender(item, renderEvt) { // ... } } const app = new MyArray(); ``` --- # Matreshka.Array#orderBy **Метод** ```js Matreshka.Array#orderBy(keys, [orders=asc]) → matreshkaArray ``` Сортує масив за значеннями властивостей об'єктів, які в нього входять Цей метод працює майже так само, як і метод [orderBy з lodash](https://lodash.com/docs#orderBy). Він приймає ключ або масив ключів першим аргументом, порядок (asc/desc) або масив порядків - другим. **Повертає:** [`matreshkaArray`](https://matreshka.js.org/ua/#type-matreshka-array) – self **Генерує події:** `sort` ## Аргументи | Ім'я | За замовчуванням | Тип | Опис | | --- | --- | --- | --- | | `keys` | | [`string`](https://matreshka.js.org/ua/#type-string) \| [`array`](https://matreshka.js.org/ua/#type-array) | Ключ властивості або масив декількох ключів, за якими колекція буде відсортована | | `orders` (необов'язковий) | `asc` | [`string`](https://matreshka.js.org/ua/#type-string) \| [`array`](https://matreshka.js.org/ua/#type-array) | Порядок або масив порядків, відповідних до масиву ключів | ## Приклади ```js this.recreate([ { 'user': 'fred', 'age': 48 }, { 'user': 'barney', 'age': 34 }, { 'user': 'fred', 'age': 42 }, { 'user': 'barney', 'age': 36 } ]); // сортує за значенням властивості 'user' по зростанню і значенням властивості 'age' по спаданню this.orderBy(['user', 'age'], ['asc', 'desc']); // → [{"user":"barney","age":36},{"user":"barney","age":34},{"user":"fred","age":48},{"user":"fred","age":42}] ``` --- # Matreshka.Array#pull **Метод** ```js Matreshka.Array#pull(indexOrValue, [eventOptions]) → *|null ``` Видаляє елемент за індексом або за значенням **Повертає:** [`*`](https://matreshka.js.org/ua/#type-any) \| [`null`](https://matreshka.js.org/ua/#type-null) – Видалений елемент або ``null`` **Генерує події:** `pull`, `remove`, `removeone`, `modify` ## Аргументи | Ім'я | Тип | Опис | | --- | --- | --- | | `indexOrValue` | [`object`](https://matreshka.js.org/ua/#type-object) \| [`number`](https://matreshka.js.org/ua/#type-number) | Індекс елемента, який потрібно видалити або видаляємий об'єкт | | `eventOptions` (необов'язковий) | [`eventOptions`](https://matreshka.js.org/ua/#type-event-options) | Об'єкт події на випадок, якщо потрібно передати в обробник події якісь дані або встановити службові прапори (наприклад, ``silent``) | ## Приклади **Передача індексу масиву** ```js let removed; this.recreate(['a', 'b', 'c']); removed = this.pull(1); console.log(removed); // 'b' console.log(this.join(',')); // 'a,c' ``` **Передача видаляємого об'єкту** ```js const object1 = {}; const object2 = {}; const object3 = {}; let removed; this.push(object1, object2, object3); removed = this.pull(object2); console.log(removed === object2); // true console.log(this.length); // 2 ``` --- # Matreshka.Array#recreate **Метод** ```js Matreshka.Array#recreate([array], [eventOptions]) → matreshkaArray ``` Перестворює екземпляр [`Matreshka.Array`](https://matreshka.js.org/ua/#Matreshka.Array) Метод дозволяє конвертувати будь-який масив (або об'єкт, подібний масиву) в екземпляр [`Matreshka.Array`](https://matreshka.js.org/ua/#Matreshka.Array). Якщо нічого не передано в якості першого аргументу, екземпляр очищується. **Повертає:** [`matreshkaArray`](https://matreshka.js.org/ua/#type-matreshka-array) – self **Генерує події:** `recreate`, `modify`, `add`, `addone`, `remove`, `removeone` ## Аргументи | Ім'я | Тип | Опис | | --- | --- | --- | | `array` (необов'язковий) | [`array`](https://matreshka.js.org/ua/#type-array) | Масив або масивоподібний об'єкт | | `eventOptions` (необов'язковий) | [`eventOptions`](https://matreshka.js.org/ua/#type-event-options) | Об'єкт події | ## Посилання - [`Matreshka.Array#trackBy`](https://matreshka.js.org/ua/#Matreshka.Array-trackBy) ## Приклади ```js // очищаємо масив і додаємо 5 нових айтемів this.recreate([1, 2, 3, 4, 5]); // очищаємо масив this.recreate(); ``` --- # Matreshka.Array#restore **Метод** ```js Matreshka.Array#restore([selector], [eventOptions]) → matreshkaArray ``` Відтворює [`Matreshka.Array`](https://matreshka.js.org/ua/#Matreshka.Array) з HTML вузлів на сторінці. У разі, якщо колекція заздалегідь відмальована на сторінці (наприклад, за допомогою сервера), метод може відтворити колекцію з HTML вузлів. ```html ``` ```js class MyModel extends Matreshka.Object { constructor(data) { super(data); this.addDataKeys('value'); } onRender() { this.bindNode('value', ':sandbox', Matreshka.binders.html()) } } class MyCollection extends Matreshka.Array { get itemRenderer() { return ':sandbox .renderer'; } constructor() { super() .bindNode('sandbox', '.collection-node') .restore(':sandbox li'); } } const myCollection = new MyCollection(); myCollection.push({ value: 'Four' }); console.log(myCollection.toJSON()); // [{value: 'One'}, {value: 'Two'}, {value: 'Three'}, {value: 'Four'}] ``` Якщо аргумент ``selector`` не заданий, то колекція буде відтворена з елементів, що входять в контейнер (``"container"`` або ``"sandbox"``). При відтворенні, на кожному елементі масиву генерується подія ``render`` і викликаються методи ``onRender`` і ``onItemRender`` (див [документацію](https://matreshka.js.org/ua/#Matreshka.Array-onItemRender)), як і при [звичайному рендерингу](https://matreshka.js.org/ua/#Matreshka.Array-itemRenderer). **Повертає:** [`matreshkaArray`](https://matreshka.js.org/ua/#type-matreshka-array) – self **Генерує події:** `recreate`, `modify`, `add`, `addone` ## Аргументи | Ім'я | Тип | Опис | | --- | --- | --- | | `selector` (необов'язковий) | `selector` | Селектор | | `eventOptions` (необов'язковий) | [`eventOptions`](https://matreshka.js.org/ua/#type-event-options) | Об'єкт події | --- # Matreshka.Array#toJSON **Метод** ```js Matreshka.Array#toJSON([recursive=true]) → array ``` Конвертує екземпляр [`Matreshka.Array`](https://matreshka.js.org/ua/#Matreshka.Array) в звичайний масив Метод працює рекурсивно, викликаючи ``toJSON`` для внутрішніх об'єктів, у яких є метод з таким ім'ям. Для скасування рекурсії передайте ``false`` першим аргументом. **Повертає:** [`array`](https://matreshka.js.org/ua/#type-array) ## Аргументи | Ім'я | За замовчуванням | Тип | Опис | | --- | --- | --- | --- | | `recursive` (необов'язковий) | `true` | [`boolean`](https://matreshka.js.org/ua/#type-boolean) | | ## Приклади ```js const matreshkaArray = new Matreshka.Array(1, 2, new MatreshkaArray(3, 4)); // повертає [1, 2, [3, 4]] console.log(matreshkaArray.toJSON()); // повертає [1, 2, MatreshkaArray] console.log(matreshkaArray.toJSON(false)); ``` --- # Matreshka.Array#rerender **Метод** ```js Matreshka.Array#rerender([eventOptions]) → matreshkaArray ``` Перемальовує DOM вузли об'єктів, що входять в масив Цей метод заново рендерить елементи масиву в контейнері масиву. Якщо вузол, який асоційований з айтемом вже створений, метод, замість перемальовування з нуля, "перевставляє" його в контейнер масиву. Метод може бути корисним на випадок, коли елементи додані в масив перед оголошенням контейнера. Щоб змусити масив перемалюватися, незалежно від наявності відрендерених вузлів (наприклад, ви використовуєте кастомний шаблонізатор в ``itemRenderer``), передайте в метод об'єкт з властивістю ``forceRerender`` рівною ``true``. **Повертає:** [`matreshkaArray`](https://matreshka.js.org/ua/#type-matreshka-array) – self ## Аргументи | Ім'я | Тип | Опис | | --- | --- | --- | | `eventOptions` (необов'язковий) | [`eventOptions`](https://matreshka.js.org/ua/#type-event-options) | Об'єкт події | ## Приклади ```js this.rerender({ forceRerender: true }); ``` --- # Matreshka.Array#itemRenderer **Властивість** · Визначається вами ```js Matreshka.Array#itemRenderer: string|function ``` HTML строка, селектор або функція, яка відповідає за рендерінг элементів масива на сторінці Властивість ``itemRenderer`` - це перевизначаєма (віртуальна) властивість, яка дозволяє рендерити айтеми масиву без додаткового коду. При вставці нового об'єкта в масив, автоматично створюється HTML елемент. Цей елемент стає пісочницею (див. [`Matreshka#bindNode`](https://matreshka.js.org/ua/#Matreshka-bindNode)) (цю поведінку можна скасувати, див. нижче) для вставленого об'єкта і вставляється в HTML контейнер, визначений у масиві. > Для скорочення, в прикладах до цієї статті буде використовуватися синтаксис class fields. > ``itemRenderer`` і ``Model`` працюють і як поля класу, і як геттери; нове значення поля ``itemRenderer`` перерендерює елементи. Про елементи, передані в ``super(...)``, див. [`Matreshka.Array#Model`](https://matreshka.js.org/ua/#Matreshka.Array-Model). #### Куди вставляється створений елемент? Для того, щоб визначити місце, в яке будуть вставлятися відмальовані HTML вузли, потрібно визначити **контейнер **. Для цього слід оголосити HTML пісочницю для масиву або зв'язати спеціальний ключ ``container`` з HTML контейнером. Детальніше про привязки і пісочницю див. [`Matreshka#bindNode`](https://matreshka.js.org/ua/#Matreshka-bindNode). Приклад використання пісочниці як контейнера: ```html ``` ```js class MyArray extends Matreshka.Array { itemRenderer = '
  • '; get Model() { return MyModel; } constructor() { super(); // визначаємо пісочницю this.bindNode('sandbox', '.my-list'); } } ``` Тепер всі новостворені елементи ``
  • `` попадуть у елемент ``.my-list``. Якщо ви не хочете вставляти HTML елементи безпосередньо в пісочницю, можете пов'язати ключ ``container`` з необхідним контейнером. Така логіка потрібна в тому випадку, якщо пісочниця не обмежена одними лише елементами колекції і включає в себе інші HTML елементи. ```html

    This is my awesome list

    ``` ```js class MyArray extends Matreshka.Array { itemRenderer = '
  • '; get Model() { return MyModel; } constructor() { super(); // визначаємо пісочницю this.bindNode('sandbox', '.my-widget'); // визначаємо контейнер для HTML элементів this.bindNode('container', '.my-list'); } } ``` В наведеному вище прикладі HTML вузли попадуть в ``.my-list`` замість ``.my-widget``. Властивість ``itemRenderer`` підтримує кілька варіантів визначення, але всі вони повинні містити або повертати єдиний HTML вузол. #### HTML строка в якості значення властивості Як видно з прикладу вище, ``itemRenderer`` може бути визначений, як HTML строка. ```js class MyArray extends Matreshka.Array { get Model() { return MyModel; } itemRenderer = '
    foo
    '; constructor() { ... } } ``` #### Селектор в якості значення властивості На випадок, якщо ви виносите шаблони для елементів на HTML сторінку, ``itemRenderer`` підтримує селектор в якості значення. У цьому випадку, [`Matreshka.Array`](https://matreshka.js.org/ua/#Matreshka.Array) буде шукати HTML елемент в DOM дереві і витягне ``innerHTML`` знайденого елемента. У разі, якщо елемент не знайдений, кидається виняток. > HTML текст від селектора відрізняється наявністю символу ``<``. ```html ``` ```js class MyArray extends Matreshka.Array { get Model() { return MyModel; } itemRenderer = '#my-template'; constructor() { ... } } ``` #### Функція як значення властивості Використання функції в якості значення властивості ``itemRenderer`` може стати в нагоді, коли є потреба динамічно генерувати елемент для рендеринга. Функція може повертати: __HTML строку__ ```js class MyArray extends Matreshka.Array { itemRenderer() { return '
    foo
    '; } } ``` __Селектор__ ```js class MyArray extends Matreshka.Array { itemRenderer() { return '#my-template'; } } ``` __DOM вузол__ ```js class MyArray extends Matreshka.Array { itemRenderer() { return document.createElement('div'); } } ``` #### Перекриття батьківського рендерера властивістю ``render`` Іноді зручно оголошувати рендерер в класі [`Matreshka.Array#Model`](https://matreshka.js.org/ua/#Matreshka.Array-Model), а не на рівні колекції. Властивість ``renderer`` перекриває значення ``itemRenderer``, якщо вона задана для елемента колекції. ```js class MyModel extends Matreshka.Object { renderer = '
    foo
    '; } class MyArray extends Matreshka.Array { Model = MyModel; itemRenderer = 'bar'; constructor() { ... } } ``` В цьому випадку, можна зовсім не вказувати ``itemRenderer``, так як ``render`` дочірнього елемента переймає всі його можливості. Синтаксис залишається таким же: можна використовувати HTML, селектор або функцію. #### Події ``render`` та ``afterrender`` Після того, як об'єкт вставлений в масив, а його HTML елемент вже створений, але ще не вставлений в контейнер, генерується подія ``render`` на вставленому об'єкті. Після його генерації можна оголосити прив'язки властивостей до HTML вузлів, що містяться всередині цього елемента. ``afterrender``, в свою чергу, генерирується після вставки HTML элемента в контейнер масива. ```html
    ``` ```js class MyModel extends Matreshka.Object { constructor(data) { super(data); // чекаємо на генерацію події this.on('render', () => { // оголошуємо біндінги this.bindNode('isChecked', ':sandbox .my-checkbox'); this.bindNode('text', ':sandbox .text', Matreshka.binders.html()); }); } } class MyArray extends Matreshka.Array { get Model() { return MyModel; } itemRenderer = ``; constructor() { super(); this.bindNode('sandbox', '.my-form'); this.push({ isChecked: true, text: 'Buy a raccoon' }, { isChecked: false, text: 'Sell the raccoon' }); } } const app = new MyArray(); ``` Код вище створить таке HTML дерево: ```html
    ``` І зв'яже чекбокси з відповідними властивостями ``isChecked`` і ``text``. Не забувайте, що в Matreshka.js реалізована можливість вилову делегованих подій. Тобто сам масив може відловити подію рендеринга айтема, використовуючи ім'я події ``*@render`` (див. документацію до [`eventNames`](https://matreshka.js.org/ua/#type-event-names)). ```js this.on('*@render', () => { alert('Child element is rendered'); }); ``` > HTML елемент стає пісочницею для вставленого об'єкту дозволяючи використовувати селектор ``:sandbox`` і інші можливості після рендеринга. Якщо об'єкт входить відразу в кілька колекцій, встановіть йому властивість ``bindRenderedAsSandbox: false``, щоб скасувати цю поведінку. ```js class MyModel extends Matreshka.Object { bindRenderedAsSandbox = false; // ... } ``` #### ``onItemRender`` та ``onRender`` Для поліпшення коду в одній з попередніх версій з'явився віртуальний метод [`Matreshka.Array#onItemRender`](https://matreshka.js.org/ua/#Matreshka.Array-onItemRender), який можна використовувати замість події ``render``. В якості альтернативи, у "моделей" викликається метод ``onRender``, що так само дозволяє зробити код більш "плоским" і позбутися вкладених функцій. ```js class MyModel extends Matreshka.Object { constructor(data) { super(data); } onRender(evt) { this.bindNode('isChecked', ':sandbox .my-checkbox'); this.bindNode('text', ':sandbox .text', Matreshka.binders.html()); } } class MyArray extends Matreshka.Array { get Model() { return MyModel; } itemRenderer = '...'; constructor() { super(); //... } onItemRender(item, evt) { //... } } const app = new MyArray(); ``` #### Шаблонізатор Поглянувши на приклади використання [`Matreshka.Array`](https://matreshka.js.org/ua/#Matreshka.Array) і [`Matreshka.Array#itemRenderer`](https://matreshka.js.org/ua/#Matreshka.Array-itemRenderer) можна звернути увагу на те, що вся логіка, що відповідає за двосторонню і односторонню прив'язку даних укладена в JavaScript коді. Але коли розробляєш дуже просту колекцію, яка не включає в себе складну логіку, масу прив'язок та ін. хотілося б мати більш короткий варіант оголошення прив'язок. Для цього, в ``itemRenderer`` може бути переданий шаблон, що включає прив'язки, укладені у фігурні дужки (див. [`Matreshka#parseBindings`](https://matreshka.js.org/ua/#Matreshka-parseBindings)). ```js class MyArray extends Matreshka.Array { itemRenderer = ``; // ... } const app = new MyArray(); ``` #### Скасування рендеринга Як видно вище, якщо у дочірнього елемента задано властивість ``render``, ``Matreshka.Array`` спробує його змалювати. Для того, щоб повністю скасувати рендеринг для масиву, надайте властивості масиву ``renderIfPossible`` значення ``false``. ```js class MyArray extends Matreshka.Array { renderIfPossible = false; // ... } ``` #### Переміщення об'єкта з одного масиву в інший За замовчуванням, при вставці об'єкта в масив Matreshka.js спробує його змалювати, використовуючи ``itemRenderer``. Це дає перевагу у випадках, коли у вас на сторінці є два або більше контейнерів, що включають в себе елементи прив'язані до одного і того же об'єкту. При зміні об'єкта, всі елементи реагують на зміну, оновлюючи DOM. Але іноді стоїть завдання переміщення об'єкта між колекціями, не перемальовуючи його заново. Для переміщення об'єкта з одного масиву в інший, включаючи його пісочницю, використовуйте прапор ``moveSandbox``. ```js this.push_(item, { moveSandbox: true }); ``` #### Перевизначення ``itemRenderer`` При перевизначенні властивості ``itemRenderer``, колекція автоматично перемальовується. ```js this.itemRenderer = '
    '; ``` Ця можливість корисна в тому випадку, коли розробник бажає завантажити шаблон з сервера. ```js fetch('templates/template.html') .then(resp => resp.text()) .then(data => { this.itemRenderer = data; }); ``` Для рендеринга тільки тих об'єктів, які ще не були намальовані, скористайтеся методом [`Matreshka#set`](https://matreshka.js.org/ua/#Matreshka-set) з прапором ``forceRerender`` зі значенням ``false`` ```js this.set('itemRenderer', renderer, { forceRerender: false }); ``` Така необхідність може виникнути тоді, коли ви використовуєте серверний пререндерінг (див. [`Matreshka.Array#restore`](https://matreshka.js.org/ua/#Matreshka.Array-restore)), а шаблон завантажується динамічно. ```js class MyArray extends Matreshka.Array { constructor() { super() .bindNode('sandbox', '.some-node') .restore(); fetch('templates/template.html') .then(resp => resp.text()) .then(data => { this.set('itemRenderer', data, { forceRerender: false }); }); } } ``` #### Рендерінг колекції, що складається зі звичайних об'єктів Об'єкт, що входить в колекцію, не обов'язково повинен бути екземпляром ``Matreshka``, можна рендерити будь-який об'єкт. Байндінги для таких об'єктів можна оголосити використовуючи статичний метод [`Matreshka.bindNode`](https://matreshka.js.org/ua/#Matreshka.bindNode). ```js class MyArray extends Matreshka.Array { // Model не визначена itemRenderer = ...; onItemRender(item) { Matreshka.bindNode(item, 'x', ':sandbox .some-node'); } } ``` Ще невеликий приклад: рендеринг простого списку. ```js class MyArray extends Matreshka.Array { itemRenderer = '
  • {{value}}
  • '; constructor() { super().bindNode('sandbox', '.my-list'); } } const arr = new MyArray(); arr.push({ value: 'Item 1' }, { value: 'Item 2' }); ``` ## Аргументи | Ім'я | Тип | Опис | | --- | --- | --- | | `item` | [`object`](https://matreshka.js.org/ua/#type-object) | об'єкт, який буде рендериться (на випадок необхідності визначення умов для рендеринга різних елементів в різних випадках) | ## Посилання - [`Matreshka#bindNode`](https://matreshka.js.org/ua/#Matreshka-bindNode) - [`Matreshka.Array#Model`](https://matreshka.js.org/ua/#Matreshka.Array-Model) --- # Matreshka.Array#trackBy **Властивість** · Визначається вами ```js Matreshka.Array#trackBy: string ``` Властивість ``trackBy`` вказує на ім'я властивості ідентифікатора об'єктів, що входять в масив У разі, якщо клієнт і сервер активно обмінюються даними (наприклад, списком користувачів), а об'єкти, що входять в масив мають унікальний ID (наприклад, ідентифікатор користувача), то перерисовка всієї колекції з нуля не має сенсу. Після того, як сервер повернув нову колекцію, набагато раціональніше перевірити, чи є в колекції об'єкт з таким само ID і, якщо об'єкт знайдений, оновити його. Таким чином, не створюється новий об'єкт (екземпляр [`Matreshka.Array#Model`](https://matreshka.js.org/ua/#Matreshka.Array-Model)) і не створюється новий DOM вузол. ``trackBy`` працює тільки при використанні методу [`Matreshka.Array#recreate`](https://matreshka.js.org/ua/#Matreshka.Array-recreate), так як це єдиний метод який "перестворює" колекцію заново. У прикладі нижче використовується ``_id`` як ключ ідентифікатора. ```js class MyArray extends Matreshka.Array { get trackBy() { return '_id'; } constructor() { super(); //... } } const arr = new MyArray(); // додає два об'єкти в масив arr.recreate([ {_id: 0, name: 'Foo'}, {_id: 1, name: 'Bar'}, {_id: 2, name: 'Baz'} ]); // Видалить об'єкт з ідентифікатором 0 // Додасть об'єкт з ідентифікатором 3 // Оновить об'єкт з ідентифікатором 1, перезаписавши name: Bar -> BarNew // Оновить об'єкт з ідентифікатором 2, перезаписавши name: Baz -> BazNew // Пересорує колекцію у відповідності з переданим даними arr.recreate([ {_id: 1, name: 'BarNew'}, {_id: 3, name: 'Qux'}, {_id: 2, name: 'BazNew'} ]); ``` Властивість може містити спеціальне значення ``"$index"``, яке дозволяє оновлювати об'єкт за індексом в колекції. ```js class MyArray extends Matreshka.Array { get trackBy() { return '$index'; } constructor() { super(); //... } } const arr = new MyArray(); // додасть два об'єкти в масив arr.recreate([ {name: 'Foo'}, {name: 'Bar'}, {name: 'Baz'} ]); // оновить всі три об'єкти новими даними // і додасть новий об'єкт з ім'ям Qux arr.recreate([ {name: 'NewFoo'}, {name: 'NewBar'}, {name: 'NewBaz'}, {name: 'Qux'} ]); ``` ## Посилання - [`Matreshka.Array#recreate`](https://matreshka.js.org/ua/#Matreshka.Array-recreate) --- # Matreshka.Array#isMatreshkaArray **Властивість** ```js Matreshka.Array#isMatreshkaArray: boolean ``` ``isMatreshkaArray`` завжди дорівнює ``true`` для экземплярів [`Matreshka.Array`](https://matreshka.js.org/ua/#Matreshka.Array) ## Приклади ```js console.log(object.isMatreshkaArray); ``` --- # Matreshka.Array#renderIfPossible **Властивість** ```js Matreshka.Array#renderIfPossible: boolean ``` Властивість ``renderIfPossible`` скасовує рендеринг масиву якщо має значення `` false`` ## Посилання - [`Matreshka.Array#itemRenderer`](https://matreshka.js.org/ua/#Matreshka.Array-itemRenderer) ## Приклади ```js class MyArray extends Matreshka.Array { get renderIfPossible() { return false; } // ... } ``` --- # Matreshka.Array.from **Метод** ```js Matreshka.Array.from(arrayLike, [mapFn], [thisArg]) → matreshkaArray ``` Метод створює новий екземпляр [`Matreshka.Array`](https://matreshka.js.org/ua/#Matreshka.Array) з масивоподібного або ітеруємого об'єкта **Повертає:** [`matreshkaArray`](https://matreshka.js.org/ua/#type-matreshka-array) ## Аргументи | Ім'я | Тип | Опис | | --- | --- | --- | | `arrayLike` | [`object`](https://matreshka.js.org/ua/#type-object) | Массивоподібний або ітеруємий об'єкт | | `mapFn` (необов'язковий) | [`function`](https://matreshka.js.org/ua/#type-function) | Відображаюча функція, що викликається для кожного елемента масиву | | `thisArg` (необов'язковий) | [`*`](https://matreshka.js.org/ua/#type-any) | Об'єкт, який використовується в якості ``this`` при виклику ``mapFn`` | ## Посилання - [Array.from](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Array/from) ## Приклади ```js const matreshkaArray = Matreshka.Array.from([1, 2, 3, 4]); ``` ```js const matreshkaArray = Matreshka.Array.from([1, 2, 3, 4], item => item * 2); ``` **Спадкування методу** ```js class MyClass extends Matreshka.Array { // ... } const myArray = MyClass.from([1, 2, 3, 4]); console.log(myArray instanceof MyClass); // true ``` --- # Matreshka.Array.of **Метод** ```js Matreshka.Array.of() → matreshkaArray ``` Метод створює новий екземпляр [`Matreshka.Array`](https://matreshka.js.org/ua/#Matreshka.Array) з довільного числа агрумент, незалежно від числа або типу аргументів **Повертає:** [`matreshkaArray`](https://matreshka.js.org/ua/#type-matreshka-array) ## Посилання - [Array.of](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Array/of) ## Приклади ```js const matreshkaArray = Matreshka.Array.of(1, 2, 3, 4); ``` **Спадкування методу** ```js class MyClass extends Matreshka.Array { // ... } const myArray = MyClass.of(1, 2, 3, 4); console.log(myArray instanceof MyClass); // true ``` --- # Matreshka.binders **Простір імен** **Імпорт:** ```js import { binders } from 'matreshka'; ``` Простір імен для байндерів. З коробки містить байндери загального призначення (для зв'язування атрибутів і ін.). Цей об'єкт можна розширювати власними властивостями, щоб не засмічувати глобальний простір імен. Візьміть до уваги невелику угоду: кожна властивість з неймспейсу ``Matreshka.binders`` має бути оформлено у вигляді функції (такі функції іноді називають "binder creator"), що повертає байндер-об'єкт. > У цій документації властивості з ``Matreshka.binders`` використовуються безпосередньо, але для поліпшення читабельності коду, рекомендується виносити їх в окремі змінні. ```js const html = Matreshka.binders.html; // ... this.bindNode('x', node, html()); ``` Або імпортувати в якості CJS модуля: ```js // імпорт відразу декількох байндерів import { binders } from 'matreshka'; const { html, text, prop } = binders; ``` Біндери входять до пакета ``matreshka``. ## Посилання - [`Matreshka#bindNode`](https://matreshka.js.org/ua/#Matreshka-bindNode) - [`Matreshka.defaultBinders`](https://matreshka.js.org/ua/#Matreshka.defaultBinders) ## Приклади ```js Matreshka.binders.myCoolBinder = (var1, var2) => { return { on: 'click', getValue() { ... }, setValue() { ... }, initialize() { ... }, destroy() { ... } }; }; this.bindNode('myKey', '.my-element', Matreshka.binders.myCoolBinder('Hello', 'World')); ``` ## Байндери - [`attr`](https://matreshka.js.org/ua/#Matreshka.binders.attr) – Повертає байндер, який змінює атрибут DOM елемента на значення властивості об'єкту - [`className`](https://matreshka.js.org/ua/#Matreshka.binders.className) – Повертає байндер, який перемикає ім'я класу DOM елемента в залежності від значення властивості об'єкта. Якщо значення властивості нестрого дорівнює ``true``, ім'я класу додається, в іншому випадку - забирається. Логіку можна змінити, передавши ``false`` другим аргументом, і, таким чином, ім'я класу буде додаватися, коли значення властивості нестрого дорівнює ``false`` і навпаки. - [`dataset`](https://matreshka.js.org/ua/#Matreshka.binders.dataset) – Повертає байндер, який змінює властивість [dataset](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/dataset) DOM элемента в залежності від значення властивості об'єкта. - [`display`](https://matreshka.js.org/ua/#Matreshka.binders.display) – Повертає байндер для одностороннього зв'язування, який змінює видимість DOM елементу (використовуючи ``style.display``), в залежності від значення властивості об'єкта - [`existence`](https://matreshka.js.org/ua/#Matreshka.binders.existence) – Повертає байндер для одностороннього зв'язування, що перемикає наявність елемента в DOM дереві, в залежності від значення властивості об'єкта - [`html`](https://matreshka.js.org/ua/#Matreshka.binders.html) – Повертає байндер, який змінює ``innerHTML`` DOM елемента в залежності від значення властивості об'єкта - [`input`](https://matreshka.js.org/ua/#Matreshka.binders.input) – Повертає байндер, що зв'язує властивість об'єкта з елементом ``input``. Безпосередньо байндер використовувати не обов'язково, так як він входить в список [`Matreshka.defaultBinders`](https://matreshka.js.org/ua/#Matreshka.defaultBinders). - [`output`](https://matreshka.js.org/ua/#Matreshka.binders.output) – Повертає байндер, що зв'язує властивість об'єкта з елементом ``output``. Безпосередньо байндер використовувати не обов'язково, так як він входить в список [`Matreshka.defaultBinders`](https://matreshka.js.org/ua/#Matreshka.defaultBinders). - [`progress`](https://matreshka.js.org/ua/#Matreshka.binders.progress) – Повертає байндер, що зв'язує властивість об'єкта з елементом ``progress``. Безпосередньо байндер використовувати не обов'язково, так як він входить в список [`Matreshka.defaultBinders`](https://matreshka.js.org/ua/#Matreshka.defaultBinders). - [`prop`](https://matreshka.js.org/ua/#Matreshka.binders.prop) – Повертає байндер, який змінює властивість DOM елемента на значення властивості об'єкта - [`select`](https://matreshka.js.org/ua/#Matreshka.binders.select) – Повертає байндер, що зв'язує властивість об'єкта з елементом ``select``. Безпосередньо байндер використовувати не обов'язково, так як він входить в список [`Matreshka.defaultBinders`](https://matreshka.js.org/ua/#Matreshka.defaultBinders). - [`style`](https://matreshka.js.org/ua/#Matreshka.binders.style) – Повертає байндер, який змінює задану властивість стилю DOM елемента в залежності від значення властивості об'єкта - [`text`](https://matreshka.js.org/ua/#Matreshka.binders.text) – Повертає байндер, який змінює ``textContent`` (текстовий вміст) DOM елемента в залежності від значення властивості об'єкта. - [`textarea`](https://matreshka.js.org/ua/#Matreshka.binders.textarea) – Повертає байндер, що зв'язує властивість об'єкта з елементом ``textarea``. Безпосередньо байндер використовувати не обов'язково, так як він входить в список [`Matreshka.defaultBinders`](https://matreshka.js.org/ua/#Matreshka.defaultBinders). --- # Matreshka.binders.attr **Метод** **Імпорт:** ```js import { binders } from 'matreshka'; const { attr } = binders; ``` ```js Matreshka.binders.attr(attribute, [mappingFn]) → binder ``` Повертає байндер, який змінює атрибут DOM елемента на значення властивості об'єкту Значення властивості можна перетворити за допомогою переданої функції ``mappingFn``. ``undefined`` і ``null`` встановлюють порожній атрибут; атрибут не видаляється. **Повертає:** [`binder`](https://matreshka.js.org/ua/#type-binder) ## Аргументи | Ім'я | Тип | Опис | | --- | --- | --- | | `attribute` | [`string`](https://matreshka.js.org/ua/#type-string) | Ім'я атрибута | | `mappingFn` (необов'язковий) | [`function`](https://matreshka.js.org/ua/#type-function) | Відображаюча функція | ## Приклади ```js this.bindNode('image', 'img.my-image', Matreshka.binders.attr('src')); this.image = 'http://example.com/cats.jpg'; ``` **Використання ``mappingFn``** ```js this.bindNode('myKey', '.my-node', Matreshka.binders.attr('foo', value => `Hello, ${value}`)); this.myKey = 'World'; // атрибут foo має значення "Hello, World" ``` --- # Matreshka.binders.className **Метод** **Імпорт:** ```js import { binders } from 'matreshka'; const { className } = binders; ``` ```js Matreshka.binders.className(className, [bool=true]) → binder ``` Повертає байндер, який перемикає ім'я класу DOM елемента в залежності від значення властивості об'єкта. Якщо значення властивості нестрого дорівнює ``true``, ім'я класу додається, в іншому випадку - забирається. Логіку можна змінити, передавши ``false`` другим аргументом, і, таким чином, ім'я класу буде додаватися, коли значення властивості нестрого дорівнює ``false`` і навпаки. **Повертає:** [`binder`](https://matreshka.js.org/ua/#type-binder) ## Аргументи | Ім'я | За замовчуванням | Тип | Опис | | --- | --- | --- | --- | | `className` | | [`string`](https://matreshka.js.org/ua/#type-string) | | | `bool` (необов'язковий) | `true` | [`boolean`](https://matreshka.js.org/ua/#type-boolean) | | ## Приклади ```js this.bindNode('myKey', '.my-element', Matreshka.binders.className('blah')); this.myKey = true; // додає клас 'blah' this.myKey = false; // вбирає клас 'blah' ``` ```js this.bindNode('myKey', '.my-element', Matreshka.binders.className('blah', false)); this.myKey = false; // додає клас 'blah' this.myKey = true; // вбирає клас 'blah' ``` --- # Matreshka.binders.dataset **Метод** **Імпорт:** ```js import { binders } from 'matreshka'; const { dataset } = binders; ``` ```js Matreshka.binders.dataset(property, [mappingFn]) → binder ``` Повертає байндер, який змінює властивість [dataset](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/dataset) DOM элемента в залежності від значення властивості об'єкта. Значення властивості можна перетворити за допомогою переданої функції ``mappingFn``. ``undefined`` і ``null`` показуються як порожній рядок. **Повертає:** [`binder`](https://matreshka.js.org/ua/#type-binder) ## Аргументи | Ім'я | Тип | Опис | | --- | --- | --- | | `property` | [`string`](https://matreshka.js.org/ua/#type-string) | Властивість dataset | | `mappingFn` (необов'язковий) | [`function`](https://matreshka.js.org/ua/#type-function) | Відображаюча функція | ## Приклади ```js this.bindNode('myKey', '.my-element', Matreshka.binders.dataset('myProp')); this.myKey = 'foo'; ``` **Використання ``mappingFn``** ```js this.bindNode('myKey', '.my-element', Matreshka.binders.dataset('myProp', value => `Hello, ${value}`)); this.myKey = 'foo'; // атрибут data-my-prop має значення "Hello, foo" ``` --- # Matreshka.binders.display **Метод** **Імпорт:** ```js import { binders } from 'matreshka'; const { display } = binders; ``` ```js Matreshka.binders.display([bool=true]) → binder ``` Повертає байндер для одностороннього зв'язування, який змінює видимість DOM елементу (використовуючи ``style.display``), в залежності від значення властивості об'єкта **Повертає:** [`binder`](https://matreshka.js.org/ua/#type-binder) ## Аргументи | Ім'я | За замовчуванням | Тип | Опис | | --- | --- | --- | --- | | `bool` (необов'язковий) | `true` | [`boolean`](https://matreshka.js.org/ua/#type-boolean) | Якщо аргумент дорівнює ``true``, то елемент ховається при неправдивому значенні властивості, якщо дорівнює ``false``, ховається при правдивому значенні | ## Приклади ```js this.bindNode('myKey', '.my-element', Matreshka.binders.display(true)); ``` ```js this.bindNode('myKey', '.my-element', Matreshka.binders.display(false)); ``` --- # Matreshka.binders.existence **Метод** **Імпорт:** ```js import { binders } from 'matreshka'; const { existence } = binders; ``` ```js Matreshka.binders.existence([bool=true]) → binder ``` Повертає байндер для одностороннього зв'язування, що перемикає наявність елемента в DOM дереві, в залежності від значення властивості об'єкта Байндер працює так само, як і [`Matreshka.binders.display`](https://matreshka.js.org/ua/#Matreshka.binders.display), але замість зміни видимості елемента, змінюється наявність елемента на сторінці. Байндер може бути корисним: - Для великих додатків: в залежності від стану роутера показати ту чи іншу сторінку; - Для реалізації нескінченного скролінгу; - Для інших тасків, де потрібно сховати елемент, але його наявність в DOM дереві не є обов'язковою. **Повертає:** [`binder`](https://matreshka.js.org/ua/#type-binder) ## Аргументи | Ім'я | За замовчуванням | Тип | Опис | | --- | --- | --- | --- | | `bool` (необов'язковий) | `true` | [`boolean`](https://matreshka.js.org/ua/#type-boolean) | Якщо аргумент дорівнює ``true``, то елемент зникає при неправдивому значенні властивості, якщо дорівнює ``false``, зникає при правдивому значенні | ## Приклади ```js this.bindNode('myKey', '.my-element', Matreshka.binders.existence(true)); ``` ```js this.bindNode('myKey', '.my-element', Matreshka.binders.existence(false)); ``` --- # Matreshka.binders.html **Метод** **Імпорт:** ```js import { binders } from 'matreshka'; const { html } = binders; ``` ```js Matreshka.binders.html([mappingFn]) → binder ``` Повертає байндер, який змінює ``innerHTML`` DOM елемента в залежності від значення властивості об'єкта Значення властивості можна перетворити за допомогою переданої функції ``mappingFn``. ``undefined`` і ``null`` показуються як порожній рядок. **Повертає:** [`binder`](https://matreshka.js.org/ua/#type-binder) ## Аргументи | Ім'я | Тип | Опис | | --- | --- | --- | | `mappingFn` (необов'язковий) | [`function`](https://matreshka.js.org/ua/#type-function) | Відображаюча функція | ## Приклади ```js this.bindNode('myKey', '.my-element', Matreshka.binders.html()); // встановить innerHTML элемента як "
    foo
    " this.myKey = '
    foo
    '; ``` **Використання ``mappingFn``** ```js this.bindNode('myKey', '.my-element', Matreshka.binders.html(value => `Hello, ${value}`)); // встановить innerHTML элемента як "Hello,
    foo
    " this.myKey = '
    foo
    '; ``` --- # Matreshka.binders.prop **Метод** **Імпорт:** ```js import { binders } from 'matreshka'; const { prop } = binders; ``` ```js Matreshka.binders.prop(property, [mappingFn]) → binder ``` Повертає байндер, який змінює властивість DOM елемента на значення властивості об'єкта Значення властивості можна перетворити за допомогою переданої функції ``mappingFn``. **Повертає:** [`binder`](https://matreshka.js.org/ua/#type-binder) ## Аргументи | Ім'я | Тип | Опис | | --- | --- | --- | | `property` | [`string`](https://matreshka.js.org/ua/#type-string) | Ім'я властивості | | `mappingFn` (необов'язковий) | [`function`](https://matreshka.js.org/ua/#type-function) | Відображаюча функція | ## Приклади ```js this.bindNode('disabled', '.my-button', Matreshka.binders.prop('disabled')); // встановлює властивість disabled = true для елемента this.disabled = true; // встановлює властивість disabled = false для елемента this.disabled = false; ``` **Використання ``mappingFn``** ```js this.bindNode('myProp', '.my-node', Matreshka.binders.prop('foo', value => `Hello, ${value}`)); this.myProp = 'World'; // властивість елемента foo має значення "Hello, World" ``` --- # Matreshka.binders.style **Метод** **Імпорт:** ```js import { binders } from 'matreshka'; const { style } = binders; ``` ```js Matreshka.binders.style(property, [mappingFn]) → binder ``` Повертає байндер, який змінює задану властивість стилю DOM елемента в залежності від значення властивості об'єкта Значення властивості можна перетворити за допомогою переданої функції ``mappingFn``. **Повертає:** [`binder`](https://matreshka.js.org/ua/#type-binder) ## Аргументи | Ім'я | Тип | Опис | | --- | --- | --- | | `property` | [`string`](https://matreshka.js.org/ua/#type-string) | Властивість ``style`` (camel-cased) | | `mappingFn` (необов'язковий) | [`function`](https://matreshka.js.org/ua/#type-function) | Відображаюча функція | ## Приклади ```js this.bindNode('myKey', '.my-node', Matreshka.binders.style('backgroundColor')); this.myKey = 'red'; // колір фону .my-node став червоним ``` **Використання ``mappingFn``** ```js this.bindNode('myKey', '.my-element', Matreshka.binders.style('backgroundImage', value => `url("${value}")`)); this.myKey = 'cats.jpg'; // backgroundImage дорівнює "url("cats.jpg")" ``` --- # Matreshka.binders.text **Метод** **Імпорт:** ```js import { binders } from 'matreshka'; const { text } = binders; ``` ```js Matreshka.binders.text([mappingFn]) → binder ``` Повертає байндер, який змінює ``textContent`` (текстовий вміст) DOM елемента в залежності від значення властивості об'єкта. ``Matreshka.binders.text`` дозволяє вивести вміст властивості як є. Значення властивості можна перетворити за допомогою переданої функції ``mappingFn``. ``undefined`` і ``null`` показуються як порожній рядок. **Повертає:** [`binder`](https://matreshka.js.org/ua/#type-binder) ## Аргументи | Ім'я | Тип | Опис | | --- | --- | --- | | `mappingFn` (необов'язковий) | [`function`](https://matreshka.js.org/ua/#type-function) | Відображаюча функція | ## Приклади ```js this.bindNode('myKey', '.my-element', Matreshka.binders.text()); this.myKey = 'foo'; // встановить textContent элемента як "foo" ``` **Використання ``mappingFn``** ```js this.bindNode('myKey', '.my-element', Matreshka.binders.text(value => `Hello, ${value}`)); this.myKey = 'foo'; // встановить textContent элемента як "Hello, foo" ``` --- # Matreshka.binders.input **Метод** **Імпорт:** ```js import { binders } from 'matreshka'; const { input } = binders; ``` ```js Matreshka.binders.input([type]) → binder ``` Повертає байндер, що зв'язує властивість об'єкта з елементом ``input``. Безпосередньо байндер використовувати не обов'язково, так як він входить в список [`Matreshka.defaultBinders`](https://matreshka.js.org/ua/#Matreshka.defaultBinders). Для текстових полів ``undefined`` і ``null`` показуються як порожній рядок. Для ``radio``: позначений перемикач встановлює властивості своє ``value``; знятий перемикач властивість не змінює. **Повертає:** [`binder`](https://matreshka.js.org/ua/#type-binder) ## Аргументи | Ім'я | Тип | Опис | | --- | --- | --- | | `type` (необов'язковий) | [`string`](https://matreshka.js.org/ua/#type-string) | Тип інпута | ## Приклади ```js this.bindNode('myKey', '.my-input', Matreshka.binders.input('range')); ``` --- # Matreshka.binders.output **Метод** **Імпорт:** ```js import { binders } from 'matreshka'; const { output } = binders; ``` ```js Matreshka.binders.output() → binder ``` Повертає байндер, що зв'язує властивість об'єкта з елементом ``output``. Безпосередньо байндер використовувати не обов'язково, так як він входить в список [`Matreshka.defaultBinders`](https://matreshka.js.org/ua/#Matreshka.defaultBinders). ``undefined`` і ``null`` показуються як порожній рядок. **Повертає:** [`binder`](https://matreshka.js.org/ua/#type-binder) ## Приклади ```js this.bindNode('myKey', '.my-output', Matreshka.binders.output()); ``` --- # Matreshka.binders.progress **Метод** **Імпорт:** ```js import { binders } from 'matreshka'; const { progress } = binders; ``` ```js Matreshka.binders.progress() → binder ``` Повертає байндер, що зв'язує властивість об'єкта з елементом ``progress``. Безпосередньо байндер використовувати не обов'язково, так як він входить в список [`Matreshka.defaultBinders`](https://matreshka.js.org/ua/#Matreshka.defaultBinders). **Повертає:** [`binder`](https://matreshka.js.org/ua/#type-binder) ## Приклади ```js this.bindNode('myKey', '.my-progress', Matreshka.binders.progress()); ``` --- # Matreshka.binders.select **Метод** **Імпорт:** ```js import { binders } from 'matreshka'; const { select } = binders; ``` ```js Matreshka.binders.select([multiple=false]) → binder ``` Повертає байндер, що зв'язує властивість об'єкта з елементом ``select``. Безпосередньо байндер використовувати не обов'язково, так як він входить в список [`Matreshka.defaultBinders`](https://matreshka.js.org/ua/#Matreshka.defaultBinders). ``undefined`` і ``null`` вибирають опцію без значення, якщо вона є. Якщо ``multiple`` дорівнює ``true``, властивість може бути масивом значень, одним значенням або ``null`` (нічого не вибрано); значення порівнюються як рядки, тому числа теж працюють. **Повертає:** [`binder`](https://matreshka.js.org/ua/#type-binder) ## Аргументи | Ім'я | За замовчуванням | Тип | Опис | | --- | --- | --- | --- | | `multiple` (необов'язковий) | `false` | [`boolean`](https://matreshka.js.org/ua/#type-boolean) | Чи є селект ``multiple`` | ## Приклади ```js this.bindNode('myKey', '.my-select', Matreshka.binders.select(true)); ``` --- # Matreshka.binders.textarea **Метод** **Імпорт:** ```js import { binders } from 'matreshka'; const { textarea } = binders; ``` ```js Matreshka.binders.textarea() → binder ``` Повертає байндер, що зв'язує властивість об'єкта з елементом ``textarea``. Безпосередньо байндер використовувати не обов'язково, так як він входить в список [`Matreshka.defaultBinders`](https://matreshka.js.org/ua/#Matreshka.defaultBinders). **Повертає:** [`binder`](https://matreshka.js.org/ua/#type-binder) ## Приклади ```js this.bindNode('myKey', '.my-textarea', Matreshka.binders.textarea()); ``` --- # Matreshka.Router **Клас** **Імпорт:** ```js import { Router } from 'matreshka/router'; ``` [`Matreshka.initRouter`](https://matreshka.js.org/ua/#Matreshka.initRouter) побудований на класі ``Matreshka.Router``. Він приймає єдиний аргумент - тип роутера (``"hash"``, ``"history"`` або довільний рядок). За замовчуванням бібліотека створює два екземпляри ``Matreshka.Router`` з типами ``hash`` і ``history``. Вони знаходяться в ``Matreshka.Router.hash`` і ``Matreshka.Router.history``. Роутер ініціалізується ліниво, тому, якщо просто підключити скрипт до сторінки, бібліотека нічого не робить. Для цих двох екземплярів використовується патерн «одинак». Це означає, що при спробі створити ще один екземпляр типу ``hash`` через ``new Matreshka.Router('hash')`` замість нового екземпляра повернеться ``Matreshka.Router.hash``. Так уся робота з URL зібрана в одному місці, це добре для продуктивності і виключає колізії. Об'єкти, передані в ``initRouter``, просто підписуються на зміни роутера потрібного типу. Власні екземпляри (не hash і не history) ``Matreshka.Router`` можна створити вручну, якщо потрібно згенерувати URL для подальшого використання. У цьому випадку зміни властивостей не чіпають ``hash`` і не викликають ``pushState``. #### Властивості Екземпляри ``Matreshka.Router`` мають 3 властивості. - ``path`` - актуальний URL, наприклад ``/foo/bar/baz/``. - ``hashPath`` - актуальний URL з префіксом hashbang, наприклад ``#!/foo/bar/baz/`` - ``parts`` - масив усіх частин шляху, наприклад ``['foo', 'bar', 'baz']``. Усі ці властивості створені за допомогою [`Matreshka#calc`](https://matreshka.js.org/ua/#Matreshka-calc), тобто при зміні однієї властивості інші змінюються автоматично. ```js Matreshka.Router.hash.path = '/foo/bar/baz/'; ``` Змінюючи ці властивості, можна запускати потрібні процедури (оновити шлях, змінити підписані об'єкти тощо) #### Методи - ``subscribe(object, route)`` - підписує об'єкт на зміни маршруту. - ``init()`` - використовується для лінивої ініціалізації в методі ``subscribe`` (викликати вручну не потрібно). ## Аргументи | Ім'я | Тип | Опис | | --- | --- | --- | | `type` | [`string`](https://matreshka.js.org/ua/#type-string) | ``"hash"``, ``"history"`` або довільний рядок | ## Приклади ```js const customRouter = new Matreshka.Router('myType'); const object = { a: 'foo', b: 'bar' }; customRouter.subscribe(object, '/a/b/'); console.log(customRouter.path); // /foo/bar/ ``` --- # * **Тип** Будь-який тип ## Приклади ```js let whatever = 'foo'; whatever = 42; ``` --- # $nodes **Тип** Колекція DOM вузлів. Наприклад, масив вузлів, NodeList або jQuery. ## Приклади ```js let $nodes = $('.foo'); $nodes = document.querySelectorAll('.bar'); ``` --- # array **Тип** Масив ## Приклади ```js const arr = ['foo', undefined, null, () => {}]; ``` --- # binder **Тип** ``binder`` (байндер, прів'язчик) містить всю інформацію про те, як синхронізувати значення властивості з прив'язаним до нього DOM елементом. Для всіх методів байндера контекст (``this``) - відповідний DOM вузол. ## Властивості | Ім'я | Тип | Опис | | --- | --- | --- | | `on` (необов'язковий) | [`string`](https://matreshka.js.org/ua/#type-string) \| [`function`](https://matreshka.js.org/ua/#type-function) | Ім'я DOM події (або список імен подій, розділених пробілами), після спрацювання якогї витягується стан DOM елемента і встановлюється властивість. Крім цього, значенням властивості може бути функція, яка встановлює обробник довільним чином. | | `getValue` (необов'язковий) | [`function`](https://matreshka.js.org/ua/#type-function) | Функція, яка відповідає за те, як витягти стан DOM елемента | | `setValue` (необов'язковий) | [`function`](https://matreshka.js.org/ua/#type-function) | Функція, яка відповідає за те, як встановити значення DOM елементу | | `initialize` (необов'язковий) | [`function`](https://matreshka.js.org/ua/#type-function) | Функція, яка запускається при ініціалізації прив'язки. Наприклад, може бути використана для ініціалізації jQuery плагіна | | `destroy` (необов'язковий) | [`function`](https://matreshka.js.org/ua/#type-function) | Функція, яка викликається під час роботи ``unbindNode``. Якщо Байндер досить складний, ``destroy`` може містити видалення логіки яка більше не потрібна та звільнення пам'яті | ## Приклади ```js const binder = { on: 'click', getValue(bindingOptions) { return this.value; }, setValue(v, bindingOptions) { this.value = v; }, initialize(bindingOptions) { alert('A binding is initialized'); }, destroy(bindingOptions) { alert('A binding is destroyed'); } }; this.bindNode('a', '.my-checkbox', binder); ``` ```js const binder = { on(callback, bindingOptions) { this.onclick = callback; } // ... }; // ... ``` --- # boolean **Тип** Логічний тип ## Приклади ```js const bool = true; ``` --- # class **Тип** Клас створений за допомогою синтаксису ECMAScript 2015 або повернений функцією [`Matreshka.Class`](https://matreshka.js.org/ua/#Matreshka.Class) ## Приклади ```js class MyClass { method() { ... } }; ``` ```js const MyClass = Matreshka.Class({ method() { ... } }); ``` --- # eventHandler **Тип** Функція-обробник події. Приймає будь-які аргументи, передані в [`Matreshka#trigger`](https://matreshka.js.org/ua/#Matreshka-trigger) ## Аргументи | Ім'я | Тип | Опис | | --- | --- | --- | | `options` | `...*` | будь-які аргументи, передані в виклик [`Matreshka#trigger`](https://matreshka.js.org/ua/#Matreshka-trigger) після імені події | ## Приклади ```js const eventHandler = (...args) => { console.log(args); }; this.on('fyeah', eventHandler); // logs 'foo', 'bar', 'baz' this.trigger('fyeah', 'foo', 'bar', 'baz'); ``` --- # eventNames **Тип** Ім'я події або кілька імен, розділених пробілами. ##### Довільні події ```js this.on('myevent', () => {...}); this.trigger('myevent'); ``` ##### ``change:KEY``, що викликається, коли властивість змінюється ```js this.on('change:x', evt => {...}); this.x = 42; ``` ##### ``beforechange:KEY``, що викликається, перед зміною властивості ```js this.on('beforechange:x', evt => {...}); this.x = 42; ``` ##### ``addevent:NAME`` і ``addevent``, що викликаються, коли подія ініціалізується ```js // для всіх подій this.on('addevent', evt => {...}); // для події "someevent" this.on('addevent:someevent', evt => {...}); // генерує події "addevent" та "addevent:someevent" this.on('someevent', evt => {...}); ``` ##### ``removeevent:NAME`` і ``removeevent``, що викликаються, коли обробник події видаляється ```js // для всіх подій this.on('removeevent', evt => {...}); // для події "someevent" this.on('removeevent:someevent', evt => {...}); // генерує події "removeevent" та "removeevent:someevent" this.off('someevent', evt => {...}); ``` ##### ``DOM_EVENT::KEY``, де DOM_EVENT - це им'я DOM події, KEY - ключ. Генерується тоді, коли подія DOM_EVENT спрацьовує на елементі, який пов'язаний з KEY. ```js this.bindNode('x', '.my-div'); this.on('click::x', evt => { alert('clicked ".my-div"'); }); ``` ##### ``DOM_EVENT::KEY(SELECTOR)``, де DOM_EVENT - це им'я DOM події, KEY - ключ, SELECTOR - селектор. Генерується тоді, коли подія DOM_EVENT спрацьовує на елементі, який відповідає селектору SELECTOR, і знаходиться в елементі, який пов'язаний з властивістю KEY. ```html
    ``` ```js this.bindNode('x', '.my-div'); this.on('click::x(.my-button)', evt => { alert('clicked ".my-button"'); }); ``` ##### ``DOM_EVENT::(SELECTOR)``, де DOM_EVENT - це ім'я DOM події, SELECTOR - селектор. Генерується тоді, коли подія DOM_EVENT спрацьовує на елементі, який відповідає селектору SELECTOR, і знаходиться в пісочниці поточного об'єкта. ```js this.bindNode('sandbox', '.my-div'); this.on('click::(.my-button)', evt => { alert('clicked ".my-button"'); }); ``` Те ж саме, що і: ```js this.bindNode('sandbox', '.my-div'); this.on('click::sandbox(.my-button)', evt => { alert('clicked ".my-button"'); }); ``` ##### Делеговані події ``PATH@EVENT``, де PATH - це шлях до об'єкта, події якого ми бажаємо прослуховувати, EVENT - це ім'я події. ```js this.on('a@someevent', () => {...}); this.on('a.b.c@change:d', () => {...}); ``` При виникненні необхідності слухати зміни в усіх елементах [`Matreshka.Array`](https://matreshka.js.org/ua/#Matreshka.Array) або у всіх властивостях, що відповідають за дані [`Matreshka.Object`](https://matreshka.js.org/ua/#Matreshka.Object), замість імені властивості можна вказати зірочку "*". ```js this.on('*@someevent', () => {...}); this.on('*.b.*.d@change:e', () => {...}); ``` #### Різні комбінації Всі наведені вище варіанти синтаксису можна комбінувати довільним способом. ```js this.on('x.y.z@click::(.my-selector)', () => {...}); ``` --- # eventOptions **Тип** Об'єкт події Це звичайний об'єкт, котрий може містити службові прапори або довільні дані, які потраплять в обробник події ## Приклади ```js const eventOptions = { silent: true }; this.a = 1; this.on('change:a', () => { alert('a is changed'); }); this.set('a', 2, eventOptions); // no alert ``` ```js const eventOptions = { f: 'yeah' }; this.a = 1; this.on('change:a', eventOptions => { alert(eventOptions.f); }); this.set('a', 2, eventOptions); // alerts "yeah" ``` --- # function **Тип** Функція ## Приклади ```js function comeOnBarbieLetsGoParty() { alert("I'm a Barbie girl, in a Barbie world"); } ``` --- # matreshka **Тип** Екземпляр класу [`Matreshka`](https://matreshka.js.org/ua/#Matreshka) ## Приклади ```js const matreshka = new Matreshka(); obj.calc('a', 'b'); ``` --- # matreshkaArray **Тип** Екземпляр класу [`Matreshka.Array`](https://matreshka.js.org/ua/#Matreshka.Array) ## Приклади ```js const arr = new Matreshka.Array(1, 2, 3); arr.push(4); ``` --- # matreshkaObject **Тип** Екземпляр класу [`Matreshka.Object`](https://matreshka.js.org/ua/#Matreshka.Object) ## Приклади ```js const obj = new Matreshka.Object({ foo: 'x' }); obj.setData({ bar: 'y' }); ``` --- # node **Тип** DOM вузол ## Приклади ```js const node = document.querySelector('.foo'); ``` --- # null **Тип** null ## Приклади ```js const x = null; ``` --- # number **Тип** Число ## Приклади ```js const num = 42; ``` --- # object **Тип** Об'єкт ## Приклади ```js const obj = { foo: 'x', ['bar']: 'y' }; ``` --- # string **Тип** Строка ## Приклади ```js const foo = 'bar'; ``` --- # FAQ ## Як працює Matreshka.js? Фреймворк використовує акцессори (accessors) для реалізації двостороннього зв'язування даних і вилову подій зміни властивостей. Для того щоб зрозуміти, як працює двостороннє зв'язування (зокрема, функція [`Matreshka.bindNode`](https://matreshka.js.org/ua/#Matreshka.bindNode)), погляньте на цей код: ```js function bindNode(object, key, node, binder) { let value = object[key]; Object.defineProperty(object, key, { get() { return value; }, set(v) { binder.setValue.call(node, v); } }); node.addEventListener(binder.on, () => { value = binder.getValue.call(node); }); }; ``` Для спрощення, функція не підтримує зв'язок багато-до-багатьох і інші фічі оригіналу. ## Як попередньо відрендерити додаток на сервері? Можна використовувати Matreshka.js на сервері Node.js (потрібна наявність [jsdom](https://github.com/jsdom/jsdom), точніше, об'єкта ``window``, доступного глобально) або скористатися абсолютно будь-яким шаблонізатором на будь-якій серверній платформі. Перший варіант підходить для статичної генерації HTML, другий - для сторінок, які генеруються при кожному зверненні користувача. Завдання клієнтської сторони - відтворити додаток з HTML. [`Matreshka#bindNode`](https://matreshka.js.org/ua/#Matreshka-bindNode) витягне стан елемента і привласнить його властивості, а [`Matreshka.Array#restore`](https://matreshka.js.org/ua/#Matreshka.Array-restore) відновить стан колекції. ## Що таке debounce? У документації часто зустрічається фраза "мікропаттерн debounce". Це поширений патерн, який перетворює кілька викликів функції протягом певного часу в один виклик. Детальніше [тут](https://davidwalsh.name/javascript-debounce-function). ## Що з себе повинен представляти великий додаток? Додаток на базі Matreshka.js, як правило, представляє з себе один вкладений JavaScript об'єкт, кожна гілка якого - екземпляр [`Matreshka`](https://matreshka.js.org/ua/#Matreshka). Нові гілки додатку створюються за допомогою [`Matreshka#instantiate`](https://matreshka.js.org/ua/#Matreshka-instantiate), що гарантує цілісність програми та можливість повернути попередній стан додатку або однієї його гілки звичайними привласненням. ## Як відрендерити один об'єкт в контейнерах декількох колекцій? Перше: потрібно встановити класу цього об'єкту властивість ``bindRenderedAsSandbox`` зі значенням ``false``. Це відключає автоматичне створення пісочниці при рендеринзі об'єкта в масиві (так як заборонено одному об'єкту мати дві пісочниці). Друге: за подією ``render`` перевірити, в якій масив був вставлений об'єкт і оголосити байндінги, відповідні до масиву. Батьківський масив і відмальований елемент можна отримати, звернувшись до властивостей ``parentArray`` і ``node`` об'єкта події. Приклад. Є клас об'єкта ``User`` і дві колекції: ``UsersA`` і ``UsersB`` (їх [`Matreshka.Array#itemRenderer`](https://matreshka.js.org/ua/#Matreshka.Array-itemRenderer) може відрізнятися). Для обох колекцій ``User`` використовується в якості [`Matreshka.Array#Model`](https://matreshka.js.org/ua/#Matreshka.Array-Model). ```js class User extends Matreshka.Object { constructor() { super(); this.bindRenderedAsSandbox = false; setInterval(() => { // змінивши name зміняться і всі пов'язані // з цією властивістю елементи this.name = Math.random(); }, 5000); } onRender(evt) { const { parentArray, node } = evt; if(parentArray instanceof UsersA) { this.bindNode({ // створюємо псевдо-пісочницю // для синтаксичного цукру в селекторах // (це не обов'язково) nodeA: node, name: ':bound(nodeA) .name', email: ':bound(nodeA) .email', }); } else if(parentArray instanceof UsersB) { this.bindNode({ nodeB: node, name: ':bound(nodeB) .user-name', }); } } } ``` Насправді є багато способів вирішення цієї задачі. Наприклад, можна оголошувати байндінги на рівні масиву (тобто масив буде слухати подію ``render`` вставлених об'єктів) або на рівні масиву прив'язувати тільки псевдо-песоніцу, а на рівні об'єкта слухати подію ``bind`` і оголошувати інші прив'язки...