Event

Приём проектирования «поведение»

Делегирование событий можно использовать для добавления элементам «поведения» (behavior), декларативно задавая хитрые обработчики установкой специальных HTML-атрибутов и классов.

Приём проектирования «поведение» состоит из двух частей:

  1. Элементу ставится пользовательский атрибут, описывающий его поведение.
  2. При помощи делегирования ставится обработчик на документ, который ловит все клики (или другие события) и, если элемент имеет нужный атрибут, производит соответствующее действие.

Например, здесь HTML-атрибут добавляет кнопкам поведение: «увеличить значение при клике»:

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

Элементов с атрибутом может быть сколько угодно. Новые могут добавляться в HTML-код в любой момент. При помощи делегирования мы фактически добавили новый «псевдостандартный» атрибут в HTML, который добавляет элементу новую возможность («поведение»).

Всегда используйте метод для обработчиков на уровне документа

Когда мы устанавливаем обработчик событий на объект , мы всегда должны использовать метод , а не , т.к. в случае последнего могут возникать конфликты: новые обработчики будут перезаписывать уже существующие.

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

Ещё один пример поведения. Сделаем так, что при клике на элемент с атрибутом будет скрываться/показываться элемент с заданным :

Ещё раз подчеркнём, что мы сделали. Теперь для того, чтобы добавить скрытие-раскрытие любому элементу, даже не надо знать JavaScript, можно просто написать атрибут .

Это бывает очень удобно – не нужно писать JavaScript-код для каждого элемента, который должен так себя вести. Просто используем поведение. Обработчики на уровне документа сделают это возможным для элемента в любом месте страницы.

Мы можем комбинировать несколько вариантов поведения на одном элементе.

Шаблон «поведение» может служить альтернативой для фрагментов JS-кода в вёрстке.

JS Уроки

JS HOMEJS IntroductionJS Where ToJS OutputJS StatementsJS SyntaxJS CommentsJS VariablesJS OperatorsJS ArithmeticJS AssignmentJS Data TypesJS FunctionsJS ObjectsJS ScopeJS EventsJS StringsJS String MethodsJS NumbersJS Number MethodsJS ArraysJS Array MethodsJS Array SortJS Array IterationJS DatesJS Date FormatsJS Date Get MethodsJS Date Set MethodsJS MathJS RandomJS BooleansJS ComparisonsJS ConditionsJS SwitchJS Loop ForJS Loop WhileJS BreakJS Type ConversionJS BitwiseJS RegExpJS ErrorsJS DebuggingJS HoistingJS Strict ModeJS this KeywordJS Style GuideJS Best PracticesJS MistakesJS PerformanceJS Reserved WordsJS VersionsJS Version ES5JS Version ES6JS JSON

JavaScript

JS Array
concat()
constructor
copyWithin()
entries()
every()
fill()
filter()
find()
findIndex()
forEach()
from()
includes()
indexOf()
isArray()
join()
keys()
length
lastIndexOf()
map()
pop()
prototype
push()
reduce()
reduceRight()
reverse()
shift()
slice()
some()
sort()
splice()
toString()
unshift()
valueOf()

JS Boolean
constructor
prototype
toString()
valueOf()

JS Classes
constructor()
extends
static
super

JS Date
constructor
getDate()
getDay()
getFullYear()
getHours()
getMilliseconds()
getMinutes()
getMonth()
getSeconds()
getTime()
getTimezoneOffset()
getUTCDate()
getUTCDay()
getUTCFullYear()
getUTCHours()
getUTCMilliseconds()
getUTCMinutes()
getUTCMonth()
getUTCSeconds()
now()
parse()
prototype
setDate()
setFullYear()
setHours()
setMilliseconds()
setMinutes()
setMonth()
setSeconds()
setTime()
setUTCDate()
setUTCFullYear()
setUTCHours()
setUTCMilliseconds()
setUTCMinutes()
setUTCMonth()
setUTCSeconds()
toDateString()
toISOString()
toJSON()
toLocaleDateString()
toLocaleTimeString()
toLocaleString()
toString()
toTimeString()
toUTCString()
UTC()
valueOf()

JS Error
name
message

JS Global
decodeURI()
decodeURIComponent()
encodeURI()
encodeURIComponent()
escape()
eval()
Infinity
isFinite()
isNaN()
NaN
Number()
parseFloat()
parseInt()
String()
undefined
unescape()

JS JSON
parse()
stringify()

JS Math
abs()
acos()
acosh()
asin()
asinh()
atan()
atan2()
atanh()
cbrt()
ceil()
clz32()
cos()
cosh()
E
exp()
expm1()
floor()
fround()
LN2
LN10
log()
log10()
log1p()
log2()
LOG2E
LOG10E
max()
min()
PI
pow()
random()
round()
sign()
sin()
sqrt()
SQRT1_2
SQRT2
tan()
tanh()
trunc()

JS Number
constructor
isFinite()
isInteger()
isNaN()
isSafeInteger()
MAX_VALUE
MIN_VALUE
NEGATIVE_INFINITY
NaN
POSITIVE_INFINITY
prototype
toExponential()
toFixed()
toLocaleString()
toPrecision()
toString()
valueOf()

JS OperatorsJS RegExp
constructor
compile()
exec()
g
global
i
ignoreCase
lastIndex
m
multiline
n+
n*
n?
n{X}
n{X,Y}
n{X,}
n$
^n
?=n
?!n
source
test()
toString()

(x|y)
.
\w
\W
\d
\D
\s
\S
\b
\B
\0
\n
\f
\r
\t
\v
\xxx
\xdd
\uxxxx

JS Statements
break
class
continue
debugger
do…while
for
for…in
for…of
function
if…else
return
switch
throw
try…catch
var
while

JS String
charAt()
charCodeAt()
concat()
constructor
endsWith()
fromCharCode()
includes()
indexOf()
lastIndexOf()
length
localeCompare()
match()
prototype
repeat()
replace()
search()
slice()
split()
startsWith()
substr()
substring()
toLocaleLowerCase()
toLocaleUpperCase()
toLowerCase()
toString()
toUpperCase()
trim()
valueOf()

Движение мыши

Каждый раз, когда перемещается курсов мыши, срабатывает событие «mousemove» из набора JavaScript mouse events. Оно может быть использовано для отслеживания положения мыши. Это применяется при реализации возможности перетаскивания элементов мышью.

В следующем примере программа выводит на экран панель и устанавливает обработчики событий таким образом, что при перетаскивании эта панель становится уже или шире:

<p>Потяните за край панели, чтобы изменить ее ширину:</p>
<div style="background: orange; width: 60px; height: 20px">
</div>
<script>
  var lastX; // Отслеживает последнюю позицию X мыши
  var rect = document.querySelector("div");
  rect.addEventListener("mousedown", function(event) {
    if (event.which == 1) {
      lastX = event.pageX;
      addEventListener("mousemove", moved);
      event.preventDefault(); // Предотвращает выделение
    }
  });

  function buttonPressed(event) {
    if (event.buttons == null)
      return event.which != 0;
    else
      return event.buttons != 0;
  }
  function moved(event) {
    if (!buttonPressed(event)) {
      removeEventListener("mousemove", moved);
    } else {
      var dist = event.pageX - lastX;
      var newWidth = Math.max(10, rect.offsetWidth + dist);
      rect.style.width = newWidth + "px";
      lastX = event.pageX;
    }
  }
</script>

Обратите внимание, что обработчик «mousemove» зарегистрирован для всего окна. Даже если во время изменения размеров мышь выходит за пределы панели, мы все равно обновляем ширину панели и прекращаем JavaScript touch events, когда клавиша мыши была отпущена

Мы должны прекратить изменение размера панели, когда пользователь отпускает клавишу мыши. К сожалению, не все браузеры устанавливают для событий «mousemove» свойство which. Существует стандартное свойство buttons, которое предоставляет аналогичную информацию, но оно также поддерживается не во всех браузерах. К счастью, все основные браузеры поддерживают что-то одно: либо buttons, либо which. Функция buttonPressed в приведенном выше примере сначала пытается использовать свойство buttons, и, если оно не доступно, переходит к which.

Когда курсор мыши наводится или покидает узел, запускаются события «mouseover» или «mouseout«. Они могут использоваться для создания эффектов при наведении курсора мыши, вывода какой-нибудь подписи или изменения стиля элемента.

Чтобы создать такой эффект, недостаточно просто начать его отображение при возникновении события «mouseover» и завершить после события «mouseout«. Когда мышь перемещается от узла к одному из его дочерних элементов, для родительского узла происходит событие «mouseout«. Хотя указатель мыши не покинул диапазон распространения узла.

Что еще хуже, эти JavaScript event распространяются так же, как и другие события. Когда мышь покидает один из дочерних узлов, для которого зарегистрирован обработчик, возникнет событие «mouseout«.

Чтобы обойти эту проблему, можно использовать свойство объекта события relatedTarget. В случае возникновения события «mouseover» оно указывает, на какой элемент был наведен курсор мыши до этого. А в случае возникновения «mouseout» — к какому элементу перемещается указатель. Мы будем изменять эффект наведения мыши только, когда relatedTarget находится вне нашего целевого узла.

В этом случае мы изменяем поведение, потому что курсор мыши был наведен на узел из-за его пределов (или наоборот):

<p>Наведите курсор мыши на этот <strong>абзац</strong>.</p>
<script>
  var para = document.querySelector("p");
  function isInside(node, target) {
    for (; node != null; node = node.parentNode)
      if (node == target) return true;
  }
  para.addEventListener("mouseover", function(event) {
    if (!isInside(event.relatedTarget, para))
      para.style.color = "red";
  });
  para.addEventListener("mouseout", function(event) {
    if (!isInside(event.relatedTarget, para))
      para.style.color = "";
  });
</script>

Функция isInside отслеживает родительские связи заданного узла или пока не будет достигнута верхняя часть документа (когда node равен нулю). Либо не будет найден родительский элемент, который нам нужен.

Эффект наведения гораздо проще создать с помощью псевдоселектора CSS :hover, как показано в следующем примере. Но когда эффект наведения предполагает что-то более сложное, чем просто изменение стиля целевого узла, тогда нужно использовать прием с использованием событий «mouseover» и «mouseout» (JavaScript mouse events):

<style>
  p:hover { color: red }
</style>
<p>Наведите курсор мыши на этот <strong>абзац</strong>.</p>

The addEventListener() method

Example

Add an event listener that fires when a user clicks a button:

document.getElementById(«myBtn»).addEventListener(«click», displayDate);

The method attaches an event handler to the specified element.

The method attaches an event handler to an element without overwriting existing event handlers.

You can add many event handlers to one element.

You can add many event handlers of the same type to one element, i.e two «click» events.

You can add event listeners to any DOM object not only HTML elements. i.e the window object.

The method makes it easier to control how the event reacts to bubbling.

When using the method, the JavaScript is separated from the HTML markup, for better readability
and allows you to add event listeners even when you do not control the HTML markup.

You can easily remove an event listener by using the method.

Отличия IE8-

Чтобы было проще ориентироваться, я собрал отличия IE8-, которые имеют отношение ко всплытию, в одну секцию.

Их знание понадобится, если вы решите писать на чистом JS, без фреймворков и вам понадобится поддержка IE8-.

Нет свойства

Обратим внимание, что при назначении обработчика через у нас есть , поэтому , как правило, не нужно, а вот при назначении через обработчик не получает , так что текущий элемент, если нужен, можно будет взять лишь из замыкания.

Вместо в IE8- используется

Если мы пишем обработчик, который будет поддерживать и IE8- и современные браузеры, то можно начать его так:

Для остановки всплытия используется код .

Кросс-браузерно остановить всплытие можно так:

Далее в учебнике мы будем использовать стандартные свойства и вызовы, поскольку добавление этих строк, обеспечивающих совместимость – достаточно простая и очевидная задача. Кроме того, никто не мешает подключить полифил.

Ещё раз хотелось бы заметить – эти отличия нужно знать при написании JS-кода с поддержкой IE8- без фреймворков. Почти все JS-фреймворки обеспечивают кросс-браузерную поддержку , и .

Частые ошибки

Если вы только начинаете работать с событиями, обратите внимание на следующие моменты. Функция должна быть присвоена как , а не

Функция должна быть присвоена как , а не .

Если добавить скобки, то – это уже вызов функции, результат которого (равный , так как функция ничего не возвращает) будет присвоен . Так что это не будет работать.

…А вот в разметке, в отличие от свойства, скобки нужны:

Это различие просто объяснить. При создании обработчика браузером из атрибута, он автоматически создаёт функцию с телом из значения атрибута: .

Так что разметка генерирует такое свойство:

Используйте именно функции, а не строки.

Назначение обработчика строкой также сработает. Это сделано из соображений совместимости, но делать так не рекомендуется.

Не используйте для обработчиков.

Такой вызов работать не будет:

Регистр DOM-свойства имеет значение.

Используйте , а не , потому что DOM-свойства чувствительны к регистру.

Event handlers

To react on events we can assign a handler – a function that runs in case of an event.

Handlers are a way to run JavaScript code in case of user actions.

There are several ways to assign a handler. Let’s see them, starting from the simplest one.

A handler can be set in HTML with an attribute named .

For instance, to assign a handler for an , we can use , like here:

On mouse click, the code inside runs.

Please note that inside we use single quotes, because the attribute itself is in double quotes. If we forget that the code is inside the attribute and use double quotes inside, like this: , then it won’t work right.

An HTML-attribute is not a convenient place to write a lot of code, so we’d better create a JavaScript function and call it there.

Here a click runs the function :

As we know, HTML attribute names are not case-sensitive, so works as well as and … But usually attributes are lowercased: .

We can assign a handler using a DOM property .

For instance, :

If the handler is assigned using an HTML-attribute then the browser reads it, creates a new function from the attribute content and writes it to the DOM property.

So this way is actually the same as the previous one.

These two code pieces work the same:

  1. Only HTML:

  2. HTML + JS:

In the first example, the HTML attribute is used to initialize the , while in the second example – the script, that’s all the difference.

As there’s only one property, we can’t assign more than one event handler.

In the example below adding a handler with JavaScript overwrites the existing handler:

To remove a handler – assign .

События клавиш

Когда пользователь нажимает клавишу на клавиатуре, браузер запускает событие «keydown«. Когда он отпускает клавишу, срабатывает событие «keyup«:

<p>Эта страница становится фиолетовой, когда вы нажимаете клавишу V.</p>
<script>
  addEventListener("keydown", function(event) {
    if (event.keyCode == 86)
      document.body.style.background = "violet";
  });
  addEventListener("keyup", function(event) {
    if (event.keyCode == 86)
      document.body.style.background = "";
  });
</script>

Также это событие срабатывает, когда пользователь нажимает и удерживает клавишу, или пока клавиша удерживается. Например, если требуется увеличить скорость персонажа в игре, нажав на клавишу со стрелкой, и снова уменьшить ее, отпустив клавишу, то нужно быть осторожным, чтобы не увеличивать скорость каждый раз, пока клавиша нажата.

В предыдущем примере использовано свойство объекта event keycode JavaScript. С его помощью определяется, какая именно клавиша была нажата или отпущена. Ноне всегда очевидно, как привести числовой код клавиши к фактической клавише.

Для считывания значений клавиш букв и цифр используется код символа Unicode. Он связан с буквой (в верхнем регистре) или цифрой, обозначенной на клавише. Метод charCodeAt для строк позволяет получить это значение:

console.log("Violet".charCodeAt(0));
// → 86
console.log("1".charCodeAt(0));
// → 49

С другими клавишами связаны менее предсказуемые коды клавиш. Лучший способ определить нужный код, это поэкспериментировать. Зарегистрировать обработчик события нажатия клавиши, который фиксирует коды клавиш, которые он получает, и нажать нужную клавишу.

Такие клавиши, как Shift, Ctrl, Alt порождают события, как обычные клавиши. Но при отслеживании комбинаций клавиш также можно определить, нажаты ли эти клавиши, по свойствам событий клавиатуры и JavaScript mouse events: shiftKey, ctrlKey, altKey и metaKey:

<p>Чтобы продолжить, нажмите Ctrl-Space.</p>
<script>
  addEventListener("keydown", function(event) {
    if (event.keyCode == 32 && event.ctrlKey)
      console.log("Continuing!");
  });
</script>

События «keydown» и «keyup» предоставляют информацию о фактическом нажатии клавиш. Но что, если нам нужен сам вводимый текст? Получать текст из кодов клавиш неудобно. Для этого существует событие, «keypress«, которое срабатывает сразу после «keydown«. Оно повторяется вместе с «keydown«, пока клавиша нажата. Но только для клавиш, с помощью которых производится ввод символов.

Свойство charCode в объекте события содержит код, который может быть интерпретирован, как код символа Unicode. Мы можем использовать функцию String.fromCharCode, чтобы преобразовать этот код в строку из одного символа.

<p>Установите фокус ввода на этой странице и наберите что-нибудь.</p>
<script>
  addEventListener("keypress", function(event) {
    console.log(String.fromCharCode(event.charCode));
  });
</script>

Узел DOM, в котором происходит событие зависит, от того элемента, который находился в фокусе ввода при нажатии клавиши. Обычные узлы не могут находиться в фокусе ввода (если не установить для них атрибут tabindex), но такие элементы, как ссылки, кнопки и поля формы, могут.

Если никакой конкретный элемент не выделен фокусом ввода, то в качестве целевого узла для событий клавиши и JavaScript touch events выступает document.body.

Значения параметров

Параметр Описание
type Строковое значение, представляющее тип события для прослушивания (значение чувствительно к регистру). Обязательный параметр.
listener Объект, который получает уведомление при возникновении события указанного типа (объект, реализующий интерфейс Event). Это должен быть объект, реализующий интерфейс EventListener, или функция JavaScript. Обязательный параметр.
options Объект, указывающий характеристики прослушивателя событий (является необязательным параметром). Доступные опции:

  • capture — Логическое значение, которое определяет будут ли события этого типа отправлены зарегистрированному прослушивателю (обработчику события) перед отправкой любому EventTarget, расположенному под ним в дереве DOM. Если передать логическое значение true, то функция будет зарегистрирована как перехватывающий обработчик и будет вызываться в фазе перехвата (capture phase). Значение по умолчанию false — обработчик события будет срабатывать в фазе всплытия (bubbling phase).
  • once — Логическое значение, которое указывает на то, что обработчик события должен быть вызван не более одного раза после добавления. Если указано логическое значение true, то прослушиватель будет автоматически удален при вызове.
  • passive — Логическое значение, которое, если соответствует значению true, указывает на то, что функция, указанная прослушивателем, никогда не отменит действие события по умолчанию (вызовет метод preventDefault()). Если обработчик события всё же вызовет метод preventDefault(), то браузер пользователя проигнорирует его, и создаст при этом предупреждение в консоли.
useCapture Логическое значение, которое определяет будут ли события этого типа отправлены зарегистрированному прослушивателю (обработчику события) перед отправкой любому EventTarget, расположенному под ним в дереве DOM.
Если передать логическое значение true, то функция будет зарегистрирована как перехватывающий обработчик и будет вызываться в фазе перехвата (capture phase). Значение по умолчанию false — обработчик события будет срабатывать в фазе всплытия (bubbling phase). Необязательный параметр. Параметр useCapture не всегда был необязательным, в идеале, вы должны включить его для более широкой браузерной поддержки.

Инициализация обработчика через атрибут

Этот способ позволяет прописать обработчик напрямую в разметке. Выполняется это посредством указания JavaScript кода в атрибуте . Вместо необходимо написать имя (тип) события (например: ).

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

<!-- onclick - атрибут, содержащий код, который будет выполняться всякий раз при наступлении события click на этом элементе -->
<button type="button" onclick="alert(Date())">Текущая дата</button>

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

Например:

<script>
  // функция sum
  function sum() {
    const number1 = +document.querySelector('#number1').value;
    const number2 = +document.querySelector('#number2').value;
    const sum = number1 + number2;
    document.querySelector('#answer').textContent = sum;
  }
</script>

<input type="text" id="number1">
<input type="text" id="number2">
<div id="answer"></div>
<button type="button" onclick="sum()">Посчитать</button>

В этом примере мы указали в качестве обработчика функцию .

При этом задавать обработчик напрямую в разметке не является хорошей практикой, т.к. это приведёт к смешиванию JavaScript и HTML кода.

Отмена действия браузера

Есть два способа отменить действие браузера:

  • Основной способ – это воспользоваться объектом . Для отмены действия браузера существует стандартный метод .
  • Если же обработчик назначен через (не через ), то также можно вернуть из обработчика.

Возвращать не нужно

Обычно значение, которое возвращает обработчик события, игнорируется.

Единственное исключение – это из обработчика, назначенного через .

В других случаях не нужен, он никак не обрабатывается.

Рассмотрим меню для сайта, например:

Данный пример при помощи CSS может выглядеть так:

В HTML-разметке все элементы меню являются не кнопками, а ссылками, то есть тегами . В этом подходе есть некоторые преимущества, например:

  • Некоторые посетители очень любят сочетание «правый клик – открыть в новом окне». Если мы будем использовать или , то данное сочетание работать не будет.
  • Поисковые движки переходят по ссылкам при индексации.

Например, вот так:

Если мы уберём , то после выполнения обработчика события браузер выполнит «действие по умолчанию» – переход по адресу из . А это нам здесь не нужно, мы обрабатываем клик сами.

Кстати, использование здесь делегирования событий делает наше меню очень гибким. Мы можем добавить вложенные списки и стилизовать их с помощью CSS – обработчик не потребует изменений.

События, вытекающие из других

Некоторые события естественным образом вытекают друг из друга. Если мы отменим первое событие, то последующие не возникнут.

Например, событие для поля приводит к фокусировке на нём и запускает событие . Если мы отменим событие , то фокусирования не произойдёт.

В следующем примере попробуйте нажать на первом – происходит событие . Но если вы нажимаете по второму элементу, то события не будет.

Это потому, что отменено стандартное действие . Впрочем, фокусировка на элементе всё ещё возможна, если мы будем использовать другой способ. Например, нажатием клавиши Tab можно перейти от первого поля ввода ко второму. Но только не через клик мышью на элемент, это больше не работает.

Parameter Values

Parameter Description
event Required. A String that specifies the name of the event.Note: Do
not use the «on» prefix. For example, use «click» instead of «onclick».For a list of all HTML DOM events, look at our complete HTML DOM Event Object Reference.
function Required. Specifies the function to run when the event occurs. When
the event occurs, an event object is passed to the function as
the first parameter. The type of the event object depends on the specified event.
For example, the «click» event belongs to the MouseEvent object.
useCapture Optional. A Boolean value that specifies whether the event should be
executed in the capturing or in the bubbling phase. Possible values:

  • true — The event handler is executed in the capturing phase
  • false- Default. The event handler is executed in the bubbling phase

Parameter Values

Parameter Description
event Required. A String that specifies the name of the event.Note: Do
not use the «on» prefix. For example, use «click» instead of «onclick».For a list of all HTML DOM events, look at our complete HTML DOM Event Object Reference.
function Required. Specifies the function to run when the event occurs. When
the event occurs, an event object is passed to the function as
the first parameter. The type of the event object depends on the specified event.
For example, the «click» event belongs to the MouseEvent object.
useCapture Optional. A Boolean value that specifies whether the event should be
executed in the capturing or in the bubbling phase. Possible values:

  • true — The event handler is executed in the capturing phase
  • false- Default. The event handler is executed in the bubbling phase

Распространение

Обработчики событий (например, JavaScript touch events), зарегистрированные для родительских узлов, также будут принимать события, которые происходят в дочерних элементах. Если была нажата кнопка, находящаяся внутри абзаца, обработчики событий абзаца также получат событие click.

Событие распространяется от узла, в котором оно произошло, в родительский узел и в корень документа. После того, как все обработчики, зарегистрированные в конкретном узле, вступили в действие по очереди, возможность реагировать на событие получают обработчики, зарегистрированные для всего окна.

В любой момент обработчик события может вызвать для объекта события метод stopPropagation, чтобы предотвратить распространение события дальше. Это может быть полезно, когда у вас есть кнопка внутри другого интерактивного элемента, и вы не хотите, чтобы при нажатии кнопки активировалось поведение, заданное для клика мышью по внешним элементам.

В следующем примере мы регистрируем обработчики «MouseDown» как для кнопки, так и для абзаца. При клике правой клавишей (JavaScript mouse events) обработчик вызывает метод stopPropagation, который предотвращает запуск обработчика абзаца. При нажатии на кнопку другой клавишей мыши запускаются оба обработчика:

<p>Абзац и в нем <button>кнопка</button>.</p>
<script>
  var para = document.querySelector("p");
  var button = document.querySelector("button");
  para.addEventListener("mousedown", function() {
    console.log("Handler for paragraph.");
  });
  button.addEventListener("mousedown", function(event) {
    console.log("Handler for button.");
    if (event.which == 3)
      event.stopPropagation();
  });
</script>

Большинство объектов событий имеют свойство target, которое указывает на узел, в котором они возникли. Вы можете использовать это свойство, чтобы случайно не обрабатывать какое-то событие, которое распространяется вверх из узла.

Также можно использовать JavaScript event target, чтобы расширить диапазон события определенного типа. Например, если у вас есть узел, содержащий длинный список кнопок, более удобно зарегистрировать один обработчик клика для внешнего узла и использовать свойство target, чтобы отслеживать, была ли нажата кнопка, а не регистрировать экземпляры обработчика для всех кнопок:

<button>A</button>
<button>B</button>
<button>C</button>
<script>
  document.body.addEventListener("click", function(event) {
    if (event.target.nodeName == "BUTTON")
      console.log("Clicked", event.target.textContent);
  });
</script>

Целевой элемент event.target

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

Самый глубокий элемент, который вызывает событие, называется «целевым» или «исходным» элементом и доступен как .

Отличия от (=):

  • – это исходный элемент, на котором произошло событие, в процессе всплытия он неизменен.
  • – это текущий элемент, до которого дошло всплытие, на нём сейчас выполняется обработчик.

Например, если стоит только один обработчик , то он «поймает» все клики внутри формы. Где бы ни был клик внутри – он всплывёт до элемента , на котором сработает обработчик.

При этом:

  • () всегда будет сама форма, так как обработчик сработал на ней.
  • будет содержать ссылку на конкретный элемент внутри формы, самый вложенный, на котором произошёл клик.

Результат
script.js
example.css
index.html

Возможна и ситуация, когда и – один и тот же элемент, например если в форме нет других тегов и клик был на самом элементе .

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Adblock
detector