Объект события

Чтобы хорошо обработать событие, недостаточно знать о том, что это – «клик» или «нажатие клавиши». Могут понадобиться детали: координаты курсора, введённый символ и другие, в зависимости от события.

Детали произошедшего браузер записывает в «объект события», который передаётся первым аргументом в обработчик.

Свойства объекта события

Пример ниже демонстрирует использование объекта события:

<input type="button" value="Нажми меня" id="elem">

<script>
  elem.onclick = function(event) {
    // вывести тип события, элемент и координаты клика
    alert(event.type + " на " + event.currentTarget);
    alert(event.clientX + ":" + event.clientY);
  }
</script>

Свойства объекта event:

event.type
Тип события, в данном случае click
event.currentTarget
Элемент, на котором сработал обработчик. Значение – в точности такое же, как и у this, но бывают ситуации, когда обработчик является методом объекта и его this при помощи bind привязан к этому объекту, тогда мы можем использовать event.currentTarget.
event.clientX / event.clientY
Координаты курсора в момент клика (относительно окна)

Есть также и ряд других свойств, в зависимости от событий, которые мы разберём в дальнейших главах, когда будем подробно знакомиться с событиями мыши, клавиатуры и так далее.

Объект события доступен и в HTML

При назначении обработчика в HTML, тоже можно использовать переменную event, это будет работать кросс-браузерно:

<input type="button" onclick="alert(event.type)" value="Тип события">

Это возможно потому, что когда браузер из атрибута создаёт функцию-обработчик, то она выглядит так: function(event) { alert(event.type) }. То есть, её первый аргумент называется "event".

Особенности IE8-

IE8- вместо передачи параметра обработчику создаёт глобальный объект window.event. Обработчик может обратиться к нему.

Работает это так:

elem.onclick = function() {
  // window.event - объект события
  alert( window.event.clientX );
};

Кроссбраузерное решение

Универсальное решение для получения объекта события:

element.onclick = function(event) {
  event = event || window.event; // (*)

  // Теперь event - объект события во всех браузерах.
};

Строка (*), в случае, если функция не получила event (IE8-), использует window.event.-событие event.

Можно написать и иначе, если мы сами не используем переменную event в замыкании:

element.onclick = function(e) {
  e = e || event;

  // Теперь e - объект события во всех браузерах.
};

Итого

  • Объект события содержит ценную информацию о деталях события.
  • Он передается первым аргументом event в обработчик для всех браузеров, кроме IE8-, в которых используется глобальная переменная window.event.

Кросс-браузерно для JavaScript-обработчика получаем объект события так:

element.onclick = function(event) {
  event = event || window.event;

  // Теперь event - объект события во всех браузерах.
};

Еще вариант:

element.onclick = function(e) {
  e = e || event; // если нет другой внешней переменной event
  ...
};

Задачи

важность: 5

Сделайте так, что при клике по полю мяч перемещался на место клика.

Требования:

  • Мяч после перелёта должен становиться центром ровно под курсор мыши, если это возможно без вылета за край поля.
  • CSS-анимация не обязательна, но желательна.
  • Мяч должен останавливаться у границ поля, ни в коем случае не вылетать за них.
  • При прокрутке страницы с полем ничего не должно ломаться.

Замечания:

  • Код не должен зависеть от конкретных размеров мяча и поля.
  • Вам пригодятся свойства event.clientX/event.clientY

Открыть песочницу для задачи.

Мяч под курсор мыши

Основная сложность первого этапа – сдвинуть мяч под курсор, т.к. координаты клика e.clientX/Y – относительно окна, а мяч позиционирован абсолютно внутри поля, его координаты left/top нужно ставить относительно левого-верхнего внутреннего (внутри рамки!) угла поля.

Чтобы правильно вычислить координаты мяча, нужно получить координаты угла поля и вычесть их из clientX/Y:

var field = document.getElementById('field');
var ball = document.getElementById('ball');

field.onclick = function(e) {

  var fieldCoords = field.getBoundingClientRect();
  var fieldInnerCoords = {
    top: fieldCoords.top + field.clientTop,
    left: fieldCoords.left + field.clientLeft
  };

  ball.style.left = e.clientX - fieldInnerCoords.left + 'px';
  ball.style.top = e.clientY - fieldInnerCoords.top + 'px';

};

Далее мяч нужно сдвинуть на половину его ширины и высоты ball.clientWidth/clientHeight, чтобы он оказался центром под курсором.

Здесь есть важный «подводный камень» – размеры мяча в исходном документе не прописаны. Там просто стоит <img>. Но на момент выполнения JavaScript картинка, возможно, ещё не загрузилась, так что высота и ширина мяча будут неизвестны (а они необходимы для центрирования).

Нужно добавить width/height в тег <img> или задать размеры в CSS, тогда на момент выполнения JavaScript будет знать их и передвинет мяч правильно.

Код, который полностью центрирует мяч, вы найдете в полном решении:

Открыть решение в песочнице.

Карта учебника

Комментарии

перед тем как писать…
  • Приветствуются комментарии, содержащие дополнения и вопросы по статье, и ответы на них.
  • Для одной строки кода используйте тег <code>, для нескольких строк кода — тег <pre>, если больше 10 строк — ссылку на песочницу (plnkr, JSBin, codepen…)
  • Если что-то непонятно в статье — пишите, что именно и с какого места.