Объект-обработчик: handleEvent
Мы можем назначить обработчиком не только функцию, но и объект при помощи addEventListener
. В этом случае, когда происходит событие, вызывается метод объекта handleEvent
.
К примеру:
<button id="elem">Нажми меня</button>
<script>
elem.addEventListener('click', {
handleEvent(event) {
alert(event.type + " на " + event.currentTarget);
}
});
</script>
Как видим, если addEventListener
получает объект в качестве обработчика, он вызывает object.handleEvent(event)
, когда происходит событие.
Мы также можем использовать класс для этого:
<button id="elem">Нажми меня</button>
<script>
class Menu {
handleEvent(event) {
switch(event.type) {
case 'mousedown':
elem.innerHTML = "Нажата кнопка мыши";
break;
case 'mouseup':
elem.innerHTML += "...и отжата.";
break;
}
}
}
let menu = new Menu();
elem.addEventListener('mousedown', menu);
elem.addEventListener('mouseup', menu);
</script>
Здесь один и тот же объект обрабатывает оба события. Обратите внимание, мы должны явно назначить оба обработчика через addEventListener
. Тогда объект menu
будет получать события mousedown
и mouseup
, но не другие (не назначенные) типы событий.
Метод handleEvent
не обязательно должен выполнять всю работу сам. Он может вызывать другие методы, которые заточены под обработку конкретных типов событий, вот так:
<button id="elem">Нажми меня</button>
<script>
class Menu {
handleEvent(event) {
// mousedown -> onMousedown
let method = 'on' + event.type[0].toUpperCase() + event.type.slice(1);
this[method](event);
}
onMousedown() {
elem.innerHTML = "Кнопка мыши нажата";
}
onMouseup() {
elem.innerHTML += "...и отжата.";
}
}
let menu = new Menu();
elem.addEventListener('mousedown', menu);
elem.addEventListener('mouseup', menu);
</script>
Теперь обработка событий разделена по методам, что упрощает поддержку кода.
Итого
Есть три способа назначения обработчиков событий:
- Атрибут HTML:
onclick="..."
. - DOM-свойство:
elem.onclick = function
. - Специальные методы:
elem.addEventListener(event, handler[, phase])
для добавления,removeEventListener
для удаления.
HTML-атрибуты используются редко потому, что JavaScript в HTML-теге выглядит немного странно. К тому же много кода там не напишешь.
DOM-свойства вполне можно использовать, но мы не можем назначить больше одного обработчика на один тип события. Во многих случаях с этим ограничением можно мириться.
Последний способ самый гибкий, однако нужно писать больше всего кода. Есть несколько типов событий, которые работают только через него, к примеру transitionend
и DOMContentLoaded
. Также addEventListener
поддерживает объекты в качестве обработчиков событий. В этом случае вызывается метод объекта handleEvent
.
Не важно, как вы назначаете обработчик – он получает объект события первым аргументом. Этот объект содержит подробности о том, что произошло.
Мы изучим больше о событиях и их типах в следующих главах.
Практика
Скрыть элемент по нажатию кнопки
Добавьте JavaScript к кнопке button
, чтобы при нажатии элемент <div id="text">
исчезал.
Добавить кнопку закрытия
важность: 5
Есть список сообщений.
При помощи JavaScript для каждого сообщения добавьте в верхний правый угол кнопку закрытия.
Пример блоков и стилей
<style>
body {
margin: 10px auto;
width: 470px;
}
h3 {
margin: 0;
padding-bottom: .3em;
padding-right: 20px;
font-size: 1.1em;
}
p {
margin: 0;
padding: 0 0 .5em;
}
.pane {
background: #edf5e1;
padding: 10px 20px 10px;
border-top: solid 2px #c4df9b;
position: relative;
}
.remove-button {
position: absolute;
font-size: 110%;
top: 0;
color: darkred;
right: 10px;
display: block;
width: 24px;
height: 24px;
border: none;
background: transparent;
cursor: pointer;
}
</style>
<div>
<div class="pane"><button class="remove-button">[x]</button>
<h3>Лошадь</h3>
<p>Домашняя лошадь — животное семейства непарнокопытных, одомашненный и единственный сохранившийся подвид дикой лошади, вымершей в дикой природе, за исключением небольшой популяции лошади Пржевальского.</p>
</div>
<div class="pane"><button class="remove-button">[x]</button>
<h3>Осёл</h3>
<p>Домашний осёл (лат. Equus asinus asinus), или ишак, — одомашненный подвид дикого осла (Equus asinus), сыгравший важную историческую роль в развитии хозяйства и культуры человека и по-прежнему широко в хозяйстве многих развивающихся стран.</p>
</div>
<div class="pane"><button class="remove-button">[x]</button>
<h3>Кошка</h3>
<p>Кошка, или домашняя кошка (лат. Felis silvestris catus), — домашнее животное, одно из наиболее популярных(наряду с собакой) «животных-компаньонов». Являясь одиночным охотником на грызунов и других мелких животных, кошка — социальное животное, использующее для общения широкий диапазон звуковых сигналов.</p>
</div>
</div>
Подсказка:
Чтобы добавить кнопку закрытия, мы можем использовать либо position:absolute
(и сделать плитку (pane
) position:relative
) либо float:right
. Преимущество варианта с float:right
в том, что кнопка закрытия никогда не перекроет текст, но вариант position:absolute
даёт больше свободы для действий. В общем, выбор за вами.
Тогда для каждой плитки код может выглядеть следующим образом:
pane.insertAdjacentHTML("afterbegin", '<button class="remove-button">[x]</button>');
Элемент <button>
становится pane.firstChild
, таким образом мы можем добавить на него обработчик события:
pane.firstChild.onclick = () => pane.remove();
Карусель
важность: 4
Создайте «Карусель» –- ленту изображений, которую можно листать влево-вправо нажатием на стрелочки.
В дальнейшем к ней можно будет добавить анимацию, динамическую подгрузку и другие возможности.
P.S. В этой задаче разработка структуры HTML/CSS составляет 90% решения.
Решение: https://ru.js.cx/task/carousel/solution/
Подсказка:
Лента изображений в разметке должна быть представлена как список ul/li
с картинками <img>
.
Нужно расположить ленту внутри <div>
фиксированного размера, так чтобы в один момент была видна только нужная часть списка:
Чтобы список сделать горизонтальным, нам нужно применить CSS-свойство display: inline-block
для <li>
.
Для тега <img>
мы также должны настроить display
, поскольку по умолчанию он inline
. Во всех элементах типа inline
резервируется дополнительное место под «хвосты» символов. И чтобы его убрать, нам нужно прописать display:block
.
Для «прокрутки» будем сдвигать <ul>
. Это можно делать по-разному, например, назначением CSS-свойства transform: translateX()
(лучше для производительности) или margin-left
:
У внешнего <div>
фиксированная ширина, поэтому «лишние» изображения обрезаются.
Вся карусель – это самостоятельный «графический компонент» на странице, таким образом нам лучше его «обернуть» в отдельный <div class="carousel">
и уже модифицировать стили внутри него.