|
12 | 12 |
|
13 | 13 | Для события `mouseover`: |
14 | 14 |
|
15 | | -- `event.target` -- это элемент, на который курсор зашёл. |
| 15 | +- `event.target` -- это элемент, на который курсор перешёл. |
16 | 16 | - `event.relatedTarget` -- это элемент, с которого курсор ушёл. |
17 | 17 |
|
18 | 18 | Для события `mouseout` наоборот: |
19 | 19 |
|
20 | 20 | - `event.target` -- это элемент, с которого курсор ушёл. |
21 | | -- `event.relatedTarget` -- это элемент, на который курсор зашёл. |
| 21 | +- `event.relatedTarget` -- это элемент, на который курсор перешёл. |
22 | 22 |
|
23 | 23 | ```online |
24 | 24 | В примере ниже каждое изображение - отдельный элемент. При движении курсора по этим элементам в текстовом поле отображаются произошедшие события. |
25 | 25 |
|
26 | | -Каждое из них содержит информацию о том, откуда на соответствующий элемент пришёл и куда с него ушёл курсор. |
| 26 | +Каждое из них содержит информацию о том, откуда на соответствующий элемент перешёл и куда с него ушёл курсор. |
27 | 27 |
|
28 | 28 | [codetabs src="mouseoverout" height=280] |
29 | 29 | ``` |
30 | 30 |
|
31 | 31 | ```warn header="Свойство `relatedTarget` может быть `null`" |
32 | 32 | Свойство `relatedTarget` может быть `null`. |
33 | 33 |
|
34 | | -Это нормально и означает, что указатель мыши пришёл не с другого элемента, а из-за пределов окна браузера. Или же, наоборот, ушёл за пределы окна. |
| 34 | +Это нормально и означает, что указатель мыши перешёл не с другого элемента, а из-за пределов окна браузера. Или же, наоборот, ушёл за пределы окна. |
35 | 35 |
|
36 | 36 | Разработчикам следует держать в голове такие варианты при использовании `event.relatedTarget` в своём коде. Если, например, написать `event.relatedTarget.tagName`, то при отсутствии `event.relatedTarget` будет ошибка. |
37 | 37 | ``` |
|
57 | 57 |  |
58 | 58 |
|
59 | 59 | <div style="display:none"> |
60 | | -В случае быстрого прохождения курсором промежуточных элементов события вообще могут не генерироваться. Но если уж курсор пришёл на элемент (было сгенерировано `mouseover`), то гарантировано при выходе с того элемента будет запущено событие `mouseout`. |
| 60 | +В случае быстрого прохождения курсором промежуточных элементов события вообще могут не генерироваться. Но если уж курсор перешёл на элемент (было сгенерировано `mouseover`), то гарантировано при выходе с того элемента будет запущено событие `mouseout`. |
61 | 61 | </div> |
62 | 62 |
|
63 | 63 | ```online |
|
72 | 72 |
|
73 | 73 | ## "Лишний" mouseout при уходе на потомка |
74 | 74 |
|
75 | | -Представьте ситуацию -- курсор мыши зашёл на элемент. Сгенерировано событие `mouseover`. Затем курсор перешёл на дочерний элемент. Интересно, что в таком случае будет сгенерировано `mouseout`. То есть курсор всё ещё на элементе, но мы получили `mouseout`! |
| 75 | +Представьте ситуацию -- курсор мыши перешёл на элемент. Сгенерировано событие `mouseover`. Затем курсор перешёл на дочерний элемент. Интересно, что в таком случае будет сгенерировано `mouseout`. То есть курсор всё ещё на элементе, но мы получили `mouseout`! |
76 | 76 |
|
77 | 77 |  |
78 | 78 |
|
79 | 79 | Это выглядит странно, но легко объясняется. |
80 | 80 |
|
81 | | -**По логике браузера, курсор мыши может быть только над одним элементом в любой момент времени - над самым глубоко вложенным (и имеющим самое большое значение z-index).** |
| 81 | +**По логике браузера, курсор мыши может быть только над одним элементом в любой момент времени - над самым глубоко вложенным (и/или имеющим приоритетное значение z-index).** |
82 | 82 |
|
83 | 83 | Таким образом, если курсор переходит на другой элемент (пусть даже дочерний), то он покидает предыдущий. Достаточно просто. |
84 | 84 |
|
|
91 | 91 | [codetabs height=360 src="mouseoverout-child"] |
92 | 92 |
|
93 | 93 | 1. При входе на синий элемент -- мы получили `mouseover [target: blue]`. |
94 | | -2. Затем при переходе на красный -- `mouseout [target: blue]` (уход с родителя). |
| 94 | +2. Затем при переходе с синего на красный -- `mouseout [target: blue]` (уход с родителя). |
95 | 95 | 3. ...и сразу же `mouseover [target: red]`. |
96 | 96 |
|
97 | | -Таким образом, для обработчика, который не принимает во внимание свойство `target`, ситуация выглядит так, как будто курсор ушёл с родительского элемента, запустив `mouseout` на строке `(2)`, а затем вернулся обратно, запустив `mouseover` на строке `(3)`. |
| 97 | +Таким образом, для обработчика, который не принимает во внимание свойство `target`, ситуация выглядит так, как будто курсор ушёл с родительского элемента, запустив `mouseout` `(2)`, а затем вернулся обратно, запустив `mouseover` `(3)`. |
98 | 98 |
|
99 | 99 | Если постоянно передвигать курсор мышки с/на элемент, то мы получим много "ложных" срабатываний обработчиков. В простых случаях это может быть незаметно для пользователя, но в сложных случаях могут проявляться нежелательные побочные эффекты. |
100 | 100 |
|
101 | 101 | Чтобы их избежать, можно использовать события `mouseenter/mouseleave`. |
102 | 102 |
|
103 | 103 | ## События mouseenter и mouseleave |
104 | 104 |
|
105 | | -События `mouseenter/mouseleave` похожи на `mouseover/mouseout`. Они тоже генерируются, когда курсор мыши заходит на элемент или покидает его. |
| 105 | +События `mouseenter/mouseleave` похожи на `mouseover/mouseout`. Они тоже генерируются, когда курсор мыши переходит на элемент или покидает его. |
106 | 106 |
|
107 | 107 | Но есть и пара важных отличий: |
108 | 108 |
|
109 | | -1. Переходы внутри элемента на дочерние элементы не считаются. |
| 109 | +1. Переходы внутри элемента по дочерним элементам не считаются. |
110 | 110 | 2. События `mouseenter/mouseleave` не всплывают. |
111 | 111 |
|
112 | 112 | Эти события интуитивно очень понятны. |
113 | 113 |
|
114 | 114 | Когда курсор становится над элементом -- генерируется `mouseenter`, и не имеет значения, где именно находится курсор внутри элемента. Событие `mouseleave` происходит, когда курсор покидает элемент. |
115 | 115 |
|
116 | | -Если мы вернёмся к одному из прошлых примеров и в этот раз поставим обработчики событий `mouseenter/mouseleave` на синий `<div>`, а далее произведем те же действия -- мы увидим, что сгенерируются только события, связанные с движением курсора относительно синего `<div>`. Ничего не произойдет при переходе на красный `<div>` и обратно. Переходы с/на дочерние элементы игнорируются. |
| 116 | +Если мы вернёмся к одному из прошлых примеров и в этот раз поставим обработчики событий `mouseenter/mouseleave` на синий `<div>`, а далее произведём те же действия -- мы увидим, что сгенерируются только события, связанные с движением курсора относительно синего `<div>`. Ничего не произойдет при переходе на красный `<div>` и обратно. Переходы с/на дочерние элементы игнорируются. |
117 | 117 |
|
118 | 118 | [codetabs height=340 src="mouseleave"] |
119 | 119 |
|
120 | 120 | ## Делегирование событий |
121 | 121 |
|
122 | 122 | События `mouseenter/leave` простые и легкие в использовании. Но они не всплывают. Таким образом, мы не можем их делегировать. |
123 | 123 |
|
124 | | -Представьте ситуацию, что мы хотим обрабатывать события, сгенерированные при движении курсора по ячейкам таблицы. И в таблице сотни ячеек. |
| 124 | +Представьте ситуацию, когда мы хотим обрабатывать события, сгенерированные при движении курсора по ячейкам таблицы. И в таблице сотни ячеек. |
125 | 125 |
|
126 | 126 | Очевидное решение -- определить обработчик на родительском элементе `<table>` и там обрабатывать возникающие события. Но `mouseenter/leave` не всплывают. То есть если событие происходит на ячейке `<td>`, то только обработчик на `<td>` может поймать его. |
127 | 127 |
|
@@ -182,4 +182,4 @@ table.onmouseout = function(event) { |
182 | 182 | - Быстрое движение мышкой может не запустить события `mouseover, mousemove, mouseout` на промежуточных элементах. |
183 | 183 | - События `mouseover/out` и `mouseenter/leave` имеют дополнительное свойство: `relatedTarget`. Оно дополняет свойство `target` и содержит ссылку на элемент, с/на который мы переходим. |
184 | 184 | - События `mouseover/out` запускаются, даже когда происходит переход с родительского на дочерний элемент. В этом случае предполагается, что курсор мыши может быть только над одним элементом в любой момент времени - над самым глубоко вложенным. |
185 | | -- События `mouseenter/leave` не всплывают и не генерируются, когда курсор переходит на дочерний элемент. Они следят только за переходами с/на сам элемент, не принимая во внимание его дочерние элементы. |
| 185 | +- События `mouseenter/leave` не всплывают и не генерируются, когда курсор переходит на дочерний элемент. Они запускаются только при переходах с/на сам элемент, не принимая во внимание его дочерние элементы. |
0 commit comments