Skip to content

Event delegation #262

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jan 19, 2022
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -10,18 +10,18 @@

<div id="container">
<div class="pane">
<h3>Horse</h3>
<p>The horse is one of two extant subspecies of Equus ferus. It is an odd-toed ungulate mammal belonging to the taxonomic family Equidae. The horse has evolved over the past 45 to 55 million years from a small multi-toed creature, Eohippus, into the large, single-toed animal of today.</p>
<h3>Кінь</h3>
<p>Кінь є одним із двох існуючих підвидів дикого коня (Equus ferus). Це парнокопитний ссавець, що належить до таксономічної родини коневих (Equidae). За останні 45-55 мільйонів років кінь еволюціонував із маленької багатопалої істоти, Еогіппа (Eohippus), до великої однопалої тварини сучасності.</p>
<button class="remove-button">[x]</button>
</div>
<div class="pane">
<h3>Donkey</h3>
<p>The donkey or ass (Equus africanus asinus) is a domesticated member of the horse family, Equidae. The wild ancestor of the donkey is the African wild ass, E. africanus. The donkey has been used as a working animal for at least 5000 years.</p>
<h3>Осел</h3>
<p>Осел (Equus africanus asinus) є одомашненим представником сімейства коней (Equidae). Диким предком осла є африканський дикий осел (E. africanus). Осел використовувався як робоча тварина щонайменше 5000 років.</p>
<button class="remove-button">[x]</button>
</div>
<div class="pane">
<h3>Cat</h3>
<p>The domestic cat (Latin: Felis catus) is a small, typically furry, carnivorous mammal. They are often called house cats when kept as indoor pets or simply cats when there is no need to distinguish them from other felids and felines. Cats are often valued by humans for companionship and for their ability to hunt vermin.
<h3>Кіт</h3>
<p>Домашній кіт (лат. Felis catus) — невеликий, типово пухнастий, хижий ссавець. Їх часто називають домашніми котами, якщо їх триваюсь вдома, або просто котами, коли немає необхідності відрізняти їх від інших котячих. Люди часто цінують котів за товариські стосунки і за їх здатність полювати на шкідників.
</p>
<button class="remove-button">[x]</button>
</div>
Original file line number Diff line number Diff line change
@@ -10,25 +10,25 @@

<div id="container">
<div class="pane">
<h3>Horse</h3>
<p>The horse is one of two extant subspecies of Equus ferus. It is an odd-toed ungulate mammal belonging to the taxonomic family Equidae. The horse has evolved over the past 45 to 55 million years from a small multi-toed creature, Eohippus, into the large, single-toed animal of today.</p>
<h3>Кінь</h3>
<p>Кінь є одним із двох існуючих підвидів дикого коня (Equus ferus). Це парнокопитний ссавець, що належить до таксономічної родини коневих (Equidae). За останні 45-55 мільйонів років кінь еволюціонував із маленької багатопалої істоти, Еогіппа (Eohippus), до великої однопалої тварини сучасності.</p>
<button class="remove-button">[x]</button>
</div>
<div class="pane">
<h3>Donkey</h3>
<p>The donkey or ass (Equus africanus asinus) is a domesticated member of the horse family, Equidae. The wild ancestor of the donkey is the African wild ass, E. africanus. The donkey has been used as a working animal for at least 5000 years.</p>
<h3>Осел</h3>
<p>Осел (Equus africanus asinus) є одомашненим представником сімейства коней (Equidae). Диким предком осла є африканський дикий осел (E. africanus). Осел використовувався як робоча тварина щонайменше 5000 років.</p>
<button class="remove-button">[x]</button>
</div>
<div class="pane">
<h3>Cat</h3>
<p>The domestic cat (Latin: Felis catus) is a small, typically furry, carnivorous mammal. They are often called house cats when kept as indoor pets or simply cats when there is no need to distinguish them from other felids and felines. Cats are often valued by humans for companionship and for their ability to hunt vermin.
<h3>Кіт</h3>
<p>Домашній кіт (лат. Felis catus) — невеликий, типово пухнастий, хижий ссавець. Їх часто називають домашніми котами, якщо їх триваюсь вдома, або просто котами, коли немає необхідності відрізняти їх від інших котячих. Люди часто цінують котів за товариські стосунки і за їх здатність полювати на шкідників.
</p>
<button class="remove-button">[x]</button>
</div>
</div>

<script>
// ...your code...
// ...Ваш код...
</script>

</body>
Original file line number Diff line number Diff line change
@@ -2,12 +2,12 @@ importance: 5

---

# Hide messages with delegation
# Приховайте повідомлення за допомогою делегування

There's a list of messages with removal buttons `[x]`. Make the buttons work.
Є список повідомлень із кнопками видалення `[x]`. Зробіть так, щоб кнопки працювали.

Like this:
В результаті має працювати наступним чином:

[iframe src="solution" height=420]

P.S. Should be only one event listener on the container, use event delegation.
P.S. У контейнері має бути лише один прослуховувач подій, використовуйте делегування.
6 changes: 3 additions & 3 deletions 2-ui/2-events/03-event-delegation/2-sliding-tree/solution.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
The solution has two parts.
Рішення складається з двох частин.

1. Wrap every tree node title into `<span>`. Then we can CSS-style them on `:hover` and handle clicks exactly on text, because `<span>` width is exactly the text width (unlike without it).
2. Set a handler to the `tree` root node and handle clicks on that `<span>` titles.
1. Обертаємо кожен заголовок дерева в `<span>`. Тоді ми можемо додати їм CSS стилі на `:hover` і обробляти клік саме по тексту, тому що ширина `<span>` повністю співпадає з шириною тексту.
2. Встановлюємо обробник на кореневий вузол `tree` та обробляємо кліки на елементах `<span>`, які містять заголовки.
Original file line number Diff line number Diff line change
@@ -17,60 +17,60 @@
<body>

<ul class="tree" id="tree">
<li>Animals
<li>Тварини
<ul>
<li>Mammals
<li>Ссавці
<ul>
<li>Cows</li>
<li>Donkeys</li>
<li>Dogs</li>
<li>Tigers</li>
<li>Корови</li>
<li>Осли</li>
<li>Собаки</li>
<li>Тигри</li>
</ul>
</li>
<li>Other
<li>Інші
<ul>
<li>Snakes</li>
<li>Birds</li>
<li>Lizards</li>
<li>Змії</li>
<li>Птахи</li>
<li>Ящірки</li>
</ul>
</li>
</ul>
</li>
<li>Fishes
<li>Риби
<ul>
<li>Aquarium
<li>Акваріумні
<ul>
<li>Guppy</li>
<li>Angelfish</li>
<li>Гуппі</li>
<li>Риба-янгол</li>
</ul>
</li>
<li>Sea
<li>Морські
<ul>
<li>Sea trout</li>
<li>Морська форель</li>
</ul>
</li>
</ul>
</li>
</ul>

<script>
// move all text into <span>
// they occupy exactly the place necessary for the text,
// помістіть кожен текстовий вузол у елемент <span>
// він займає саме те місце, яке необхідне для тексту,
for (let li of tree.querySelectorAll('li')) {
let span = document.createElement('span');
li.prepend(span);
span.append(span.nextSibling); // move the text node into span
span.append(span.nextSibling); // поміщаємо текстовий вузол у span
}

// catch clicks on whole tree
// ловимо кліки на всьому дереві
tree.onclick = function(event) {

if (event.target.tagName != 'SPAN') {
return;
}

let childrenContainer = event.target.parentNode.querySelector('ul');
if (!childrenContainer) return; // no children
if (!childrenContainer) return; // дітей немає

childrenContainer.hidden = !childrenContainer.hidden;
}
Original file line number Diff line number Diff line change
@@ -6,36 +6,36 @@
<body>

<ul class="tree" id="tree">
<li>Animals
<li>Тварини
<ul>
<li>Mammals
<li>Ссавці
<ul>
<li>Cows</li>
<li>Donkeys</li>
<li>Dogs</li>
<li>Tigers</li>
<li>Корови</li>
<li>Осли</li>
<li>Собаки</li>
<li>Тигри</li>
</ul>
</li>
<li>Other
<li>Інші
<ul>
<li>Snakes</li>
<li>Birds</li>
<li>Lizards</li>
<li>Змії</li>
<li>Птахи</li>
<li>Ящірки</li>
</ul>
</li>
</ul>
</li>
<li>Fishes
<li>Риби
<ul>
<li>Aquarium
<li>Акваріумні
<ul>
<li>Guppy</li>
<li>Angelfish</li>
<li>Гуппі</li>
<li>Риба-янгол</li>
</ul>
</li>
<li>Sea
<li>Морські
<ul>
<li>Sea trout</li>
<li>Морська форель</li>
</ul>
</li>
</ul>
10 changes: 5 additions & 5 deletions 2-ui/2-events/03-event-delegation/2-sliding-tree/task.md
Original file line number Diff line number Diff line change
@@ -2,13 +2,13 @@ importance: 5

---

# Tree menu
# Деревоподібне меню

Create a tree that shows/hides node children on click:
Створіть дерево, яке показує/приховує дочірні вузли при кліці:

[iframe border=1 src="solution"]

Requirements:
Вимоги:

- Only one event handler (use delegation)
- A click outside the node title (on an empty space) should not do anything.
- Тільки один обробник подій (використовуйте делегування)
- Клік поза заголовком вузла (на порожньому місці) не має нічого робити.
Original file line number Diff line number Diff line change
@@ -25,30 +25,30 @@
<table id="grid">
<thead>
<tr>
<th data-type="number">Age</th>
<th data-type="string">Name</th>
<th data-type="number">Вік</th>
<th data-type="string">Ім’я</th>
</tr>
</thead>
<tbody>
<tr>
<td>5</td>
<td>John</td>
<td>Іван</td>
</tr>
<tr>
<td>2</td>
<td>Pete</td>
<td>Петро</td>
</tr>
<tr>
<td>12</td>
<td>Ann</td>
<td>Ганна</td>
</tr>
<tr>
<td>9</td>
<td>Eugene</td>
<td>Євген</td>
</tr>
<tr>
<td>1</td>
<td>Ilya</td>
<td>Ілля</td>
</tr>
</tbody>
</table>
@@ -59,10 +59,10 @@
if (e.target.tagName != 'TH') return;

let th = e.target;
// if TH, then sort
// cellIndex is the number of th:
// 0 for the first column
// 1 for the second column, etc
// якщо клітинка TH, тоді сортувати
// cellIndex - це номер клітинки th:
// 0 для першого стовпця
// 1 для другого і т.д.
sortGrid(th.cellIndex, th.dataset.type);
};

@@ -71,7 +71,7 @@

let rowsArray = Array.from(tbody.rows);

// compare(a, b) compares two rows, need for sorting
// compare(a, b) порівнює два рядки, необхідно для сортування
let compare;

switch (type) {
@@ -87,7 +87,7 @@
break;
}

// sort
// сортування
rowsArray.sort(compare);

tbody.append(...rowsArray);
Original file line number Diff line number Diff line change
@@ -5,18 +5,18 @@
<meta charset="utf-8">
<style>
table {
border-collapse: collapse;
}
th, td {
border: 1px solid black;
padding: 4px;
}
th {
cursor: pointer;
}
th:hover {
background: yellow;
}
border-collapse: collapse;
}
th, td {
border: 1px solid black;
padding: 4px;
}
th {
cursor: pointer;
}
th:hover {
background: yellow;
}
</style>
</head>

@@ -25,36 +25,36 @@
<table id="grid">
<thead>
<tr>
<th data-type="number">Age</th>
<th data-type="string">Name</th>
<th data-type="number">Вік</th>
<th data-type="string">Ім’я</th>
</tr>
</thead>
<tbody>
<tr>
<td>5</td>
<td>John</td>
<td>Іван</td>
</tr>
<tr>
<td>2</td>
<td>Pete</td>
<td>Петро</td>
</tr>
<tr>
<td>12</td>
<td>Ann</td>
<td>Ганна</td>
</tr>
<tr>
<td>9</td>
<td>Eugene</td>
<td>Євген</td>
</tr>
<tr>
<td>1</td>
<td>Ilya</td>
<td>Ілля</td>
</tr>
</tbody>
</table>

<script>
// ...your code...
// ...Ваш код...
</script>

</body>
18 changes: 9 additions & 9 deletions 2-ui/2-events/03-event-delegation/3-sortable-table/task.md
Original file line number Diff line number Diff line change
@@ -13,31 +13,31 @@ Each `<th>` has the type in the attribute, like this:
<thead>
<tr>
*!*
<th data-type="number">Age</th>
<th data-type="string">Name</th>
<th data-type="number">Вік</th>
<th data-type="string">Ім’я</th>
*/!*
</tr>
</thead>
<tbody>
<tr>
<td>5</td>
<td>John</td>
<td>Іван</td>
</tr>
<tr>
<td>10</td>
<td>Ann</td>
<td>12</td>
<td>Ганна</td>
</tr>
...
</tbody>
</table>
```

In the example above the first column has numbers, and the second one -- strings. The sorting function should handle sort according to the type.
У наведеному вище прикладі перший стовпець містить числа, а другий — рядки. Функція сортування повинна обробляти сортування відповідно до типу.

Only `"string"` and `"number"` types should be supported.
Повинні підтримуватися лише типи `"string"` та `"number"`.

The working example:
Робочий приклад:

[iframe border=1 src="solution" height=190]

P.S. The table can be big, with any number of rows and columns.
P.S. Таблиця може бути великою, з будь-якою кількістю рядків і стовпців.
Original file line number Diff line number Diff line change
@@ -25,13 +25,13 @@

<body>

<p>LaLaLa LaLaLa LaLaLa LaLaLa LaLaLa LaLaLa LaLaLa LaLaLa LaLaLa</p>
<p>LaLaLa LaLaLa LaLaLa LaLaLa LaLaLa LaLaLa LaLaLa LaLaLa LaLaLa</p>
<p>ЛаЛаЛа ЛаЛаЛа ЛаЛаЛа ЛаЛаЛа ЛаЛаЛа ЛаЛаЛа ЛаЛаЛа ЛаЛаЛа ЛаЛаЛа</p>
<p>ЛаЛаЛа ЛаЛаЛа ЛаЛаЛа ЛаЛаЛа ЛаЛаЛа ЛаЛаЛа ЛаЛаЛа ЛаЛаЛа ЛаЛаЛа</p>

<button data-tooltip="the tooltip is longer than the element">Short button</button>
<button data-tooltip="HTML<br>tooltip">One more button</button>
<button data-tooltip="підказка довша за елемент">Мала кнопка</button>
<button data-tooltip="HTML<br>підказка">Ще одна кнопка</button>

<p>Scroll the page to make buttons appear on the top, check if the tooltips show up correctly.</p>
<p>Прокрутіть сторінку, щоб кнопки з’явилися вгорі. Перевірте, чи правильно відображаються підказки.</p>


<script>
@@ -40,25 +40,25 @@
document.onmouseover = function(event) {
let target = event.target;

// if we have tooltip HTML...
// якщо у нас є HTML підказка...
let tooltipHtml = target.dataset.tooltip;
if (!tooltipHtml) return;

// ...create the tooltip element
// ...створіть елемент підказки

tooltipElem = document.createElement('div');
tooltipElem.className = 'tooltip';
tooltipElem.innerHTML = tooltipHtml;
document.body.append(tooltipElem);

// position it above the annotated element (top-center)
// розташуйте його над анотованим елементом (угорі по центру)
let coords = target.getBoundingClientRect();

let left = coords.left + (target.offsetWidth - tooltipElem.offsetWidth) / 2;
if (left < 0) left = 0; // don't cross the left window edge
if (left < 0) left = 0; // не перетинайте лівий край вікна

let top = coords.top - tooltipElem.offsetHeight - 5;
if (top < 0) { // if crossing the top window edge, show below instead
if (top < 0) { // якщо перетинає верхній край вікна, розташуйте знизу
top = coords.top + target.offsetHeight + 5;
}

Original file line number Diff line number Diff line change
@@ -6,11 +6,11 @@
<style>
body {
height: 2000px;
/* make body scrollable, the tooltip should work after the scroll */
/* зробіть прокручування можливим для body, підказка повинна працювати після прокрутки */
}

.tooltip {
/* some styles for the tooltip, you can use your own instead */
/* деякі стилі для підказки, замість них ви можете використовувати власні */
position: fixed;
padding: 10px 20px;
border: 1px solid #b3c9ce;
@@ -26,17 +26,17 @@

<body>

<p>LaLaLa LaLaLa LaLaLa LaLaLa LaLaLa LaLaLa LaLaLa LaLaLa LaLaLa</p>
<p>LaLaLa LaLaLa LaLaLa LaLaLa LaLaLa LaLaLa LaLaLa LaLaLa LaLaLa</p>
<p>ЛаЛаЛа ЛаЛаЛа ЛаЛаЛа ЛаЛаЛа ЛаЛаЛа ЛаЛаЛа ЛаЛаЛа ЛаЛаЛа ЛаЛаЛа</p>
<p>ЛаЛаЛа ЛаЛаЛа ЛаЛаЛа ЛаЛаЛа ЛаЛаЛа ЛаЛаЛа ЛаЛаЛа ЛаЛаЛа ЛаЛаЛа</p>

<button data-tooltip="the tooltip is longer than the element">Short button</button>
<button data-tooltip="HTML<br>tooltip">One more button</button>
<button data-tooltip="підказка довша за елемент">Мала кнопка</button>
<button data-tooltip="HTML<br>підказка">Ще одна кнопка</button>

<p>Scroll the page to make buttons appear on the top, check if the tooltips show up correctly.</p>
<p>Прокрутіть сторінку, щоб кнопки з’явилися вгорі. Перевірте, чи правильно відображаються підказки.</p>


<script>
// ...your code...
// ...Ваш код...
</script>

</body>
38 changes: 19 additions & 19 deletions 2-ui/2-events/03-event-delegation/4-behavior-tooltip/task.md
Original file line number Diff line number Diff line change
@@ -2,37 +2,37 @@ importance: 5

---

# Tooltip behavior
# Поведінка підказки

Create JS-code for the tooltip behavior.
Створіть JS-код для поведінки спливаючої підказки.

When a mouse comes over an element with `data-tooltip`, the tooltip should appear over it, and when it's gone then hide.
При наведенні миші на елемент з `data-tooltip`, підказка має з’явитися над ним і ховатися при переході на інший елемент.

An example of annotated HTML:
Приклад HTML з підказками:
```html
<button data-tooltip="the tooltip is longer than the element">Short button</button>
<button data-tooltip="HTML<br>tooltip">One more button</button>
<button data-tooltip="підказка довша за елемент">Мала кнопка</button>
<button data-tooltip="HTML<br>підказка">Ще одна кнопка</button>
```

Should work like this:
Повинно працювати так:

[iframe src="solution" height=200 border=1]

In this task we assume that all elements with `data-tooltip` have only text inside. No nested tags (yet).
У цьому завданні ми припускаємо, що всі елементи з `data-tooltip` містять лише текст всередині. Немає вкладених тегів (поки що).

Details:
Деталі:

- The distance between the element and the tooltip should be `5px`.
- The tooltip should be centered relative to the element, if possible.
- The tooltip should not cross window edges. Normally it should be above the element, but if the element is at the page top and there's no space for the tooltip, then below it.
- The tooltip content is given in the `data-tooltip` attribute. It can be arbitrary HTML.
- Відстань між елементом і підказкою має бути `5px`.
- Підказка повинна бути відцентрована відносно елемента, якщо це можливо.
- Підказка не повинна перетинати краї вікна. Зазвичай вона має бути над елементом, але якщо елемент знаходиться у верхній частині сторінки і немає місця для підказки, то під ним.
- Вміст підказки вказується в атрибуті `data-tooltip`. Це може бути довільний HTML.

You'll need two events here:
- `mouseover` triggers when a pointer comes over an element.
- `mouseout` triggers when a pointer leaves an element.
Тут вам знадобляться дві події:
- `mouseover` спрацьовує, коли курсор переходить на елемент.
- `mouseout` спрацьовує, коли курсор покидає елемент.

Please use event delegation: set up two handlers on `document` to track all "overs" and "outs" from elements with `data-tooltip` and manage tooltips from there.
Будь ласка, використовуйте делегування подій: налаштуйте два обробники на `document`, щоб відстежувати всі "заходи" і "виходи" курсору на елементи з атрибутом `data-tooltip` і керувати підказками звідти.

After the behavior is implemented, even people unfamiliar with JavaScript can add annotated elements.
Після реалізації поведінки - люди, навіть не знайомі з JavaScript, зможуть додавати підказки до елементів.

P.S. Only one tooltip may show up at a time.
P.S. Одночасно може відображатися лише одна підказка.
178 changes: 89 additions & 89 deletions 2-ui/2-events/03-event-delegation/article.md

Large diffs are not rendered by default.

74 changes: 37 additions & 37 deletions 2-ui/2-events/03-event-delegation/bagua.view/index.html
Original file line number Diff line number Diff line change
@@ -7,57 +7,57 @@

<table id="bagua-table">
<tr>
<th colspan="3"><em>Bagua</em> Chart: Direction, Element, Color, Meaning</th>
<th colspan="3">Таблиця <em>Багуа</em>: Напрямок, Елемент, Колір, Значення</th>
</tr>
<tr>
<td class="nw"><strong>Northwest</strong>
<br>Metal
<br>Silver
<br>Elders
<td class="nw"><strong>Північний захід</strong>
<br>Метал
<br>Срібний
<br>Старійшини
</td>
<td class="n"><strong>North</strong>
<br>Water
<br>Blue
<br>Change
<td class="n"><strong>Північ</strong>
<br>Вода
<br>Блакитний
<br>Зміни
</td>
<td class="ne"><strong>Northeast</strong>
<br>Earth
<br>Yellow
<br>Direction
<td class="ne"><strong>Північний схід</strong>
<br>Земля
<br>Жовтий
<br>Напрямок
</td>
</tr>
<tr>
<td class="w"><strong>West</strong>
<br>Metal
<br>Gold
<br>Youth
<td class="w"><strong>Захід</strong>
<br>Метал
<br>Золотий
<br>Молодість
</td>
<td class="c"><strong>Center</strong>
<br>All
<br>Purple
<br>Harmony
<td class="c"><strong>Центр</strong>
<br>Все
<br>Пурпурний
<br>Гармонія
</td>
<td class="e"><strong>East</strong>
<br>Wood
<br>Blue
<br>Future
<td class="e"><strong>Схід</strong>
<br>Деревина
<br>Блакитний
<br>Майбутнє
</td>
</tr>
<tr>
<td class="sw"><strong>Southwest</strong>
<br>Earth
<br>Brown
<br>Tranquility
<td class="sw"><strong>Південний захід</strong>
<br>Земля
<br>Коричневий
<br>Спокій
</td>
<td class="s"><strong>South</strong>
<br>Fire
<br>Orange
<br>Fame
<td class="s"><strong>Південь</strong>
<br>Вогонь
<br>Помаранчевий
<br>Слава
</td>
<td class="se"><strong>Southeast</strong>
<br>Wood
<br>Green
<br>Romance
<td class="se"><strong>Південний схід</strong>
<br>Деревина
<br>Зелений
<br>Романтика
</td>
</tr>