You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: 2-ui/2-events/04-default-browser-action/article.md
+28-30Lines changed: 28 additions & 30 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -15,7 +15,7 @@
15
15
Есть два способа отменить действие браузера:
16
16
17
17
- Основной способ – это воспользоваться объектом `event`. Для отмены действия браузера существует стандартный метод `event.preventDefault()`.
18
-
- Если же обработчик назначен через `on<событие>` (не через `addEventListener`), то можно просто вернуть `false` из обработчика.
18
+
- Если же обработчик назначен через `on<событие>` (не через `addEventListener`), то также можно вернуть `false` из обработчика.
19
19
20
20
В следующем примере при клике по ссылке переход не произойдет:
21
21
@@ -30,7 +30,7 @@
30
30
31
31
Единственное исключение – это `return false` из обработчика, назначенного через `on<событие>`.
32
32
33
-
В других случаях return не нужен, он никак не обрабатываются.
33
+
В других случаях `return` не нужен, он никак не обрабатываются.
34
34
```
35
35
36
36
### Пример: меню
@@ -49,7 +49,7 @@
49
49
50
50
[iframe height=70 src="menu" link edit]
51
51
52
-
HTML-разметка сделана так, что все элементы меню являются не кнопками, а ссылками, то есть тегами `<a>`. В этом подходе есть некоторые преимущества, например:
52
+
В HTML-разметке все элементы меню являются не кнопками, а ссылками, то есть тегами `<a>`. В этом подходе есть некоторые преимущества, например:
53
53
54
54
- Некоторые посетители очень любят сочетание "правый клик – открыть в новом окне". Если мы будем использовать `<button>` или `<span>`, то данное сочетание работать не будет.
55
55
- Поисковые движки переходят по ссылкам `<a href="...">` при индексации.
alert( href ); // может быть подгрузка с сервера, генерация интерфейса и т.п.
67
67
68
68
*!*
69
-
returnfalse; // отменить переход по url
69
+
returnfalse; // отменить действие браузера (переход по ссылке)
70
70
*/!*
71
71
};
72
72
```
73
73
74
-
Если мы уберём `return false`, то после выполнения обработчика события браузер выполнит "действие по умолчанию" - переход по адресу из `href`.
74
+
Если мы уберём `return false`, то после выполнения обработчика события браузер выполнит "действие по умолчанию" - переход по адресу из `href`. А это нам здесь не нужно, мы обрабатываем клик сами.
75
75
76
-
Кстати, использование здесь делегирования событий делает наше меню гибким. Мы можем добавить вложенные списки и стилизовать их с помощью CSS – обработчик не потребует изменений.
76
+
Кстати, использование здесь делегирования событий делает наше меню очень гибким. Мы можем добавить вложенные списки и стилизовать их с помощью CSS – обработчик не потребует изменений.
77
77
78
-
79
-
## Отмена последующих событий
80
-
81
-
Некоторые события естественным образом вытекают друг из друга. Если мы отменим первое событие, то последующие не выполнятся.
78
+
````smart header="События, вытекающие из других"
79
+
Некоторые события естественным образом вытекают друг из друга. Если мы отменим первое событие, то последующие не возникнут.
82
80
83
81
Например, событие `mousedown` для поля `<input>` приводит к фокусировке на нём и запускает событие `focus`. Если мы отменим событие `mousedown`, то фокусирования не произойдёт.
84
82
85
-
В следующем примере попробуйте нажать на первом `<input>` -- происходит событие `focus`. Это нормально.
86
-
87
-
Но если вы нажимаете по второму элементу, то события `focus` не будет.
83
+
В следующем примере попробуйте нажать на первом `<input>` -- происходит событие `focus`. Но если вы нажимаете по второму элементу, то события `focus` не будет.
Это потому, что отменено стандартное действие `mousedown`. Но фокусировка на элементе всё ещё возможна, если мы будем использовать другой способ. Например, нажатием клавиши `key:Tab` можно перейти от первого поля ввода ко второму. Но только не через нажатие мышью по элементу, это больше не работает.
90
+
Это потому, что отменено стандартное действие `mousedown`. Впрочем, фокусировка на элементе всё ещё возможна, если мы будем использовать другой способ. Например, нажатием клавиши `key:Tab` можно перейти от первого поля ввода ко второму. Но только не через клик мышью на элемент, это больше не работает.
Опция `passive: true` сообщает браузеру, что обработчик не собирается отменять прокрутку. Тогда браузер начинает её немедленно, обеспечивая максимально плавный интерфейс, параллельно обрабатывая событие.
107
104
108
-
Для некоторых браузеров (Firefox, Chrome) опция `passive` по умолчанию включена `true` для таких событий, как `touchstart` и `touchmove`.
105
+
Для некоторых браузеров (Firefox, Chrome) опция `passive` по умолчанию включена в `true` для таких событий, как `touchstart` и `touchmove`.
Помните, в главе <info:bubbling-and-capturing> мы говорили о `event.stopPropagation()` и упоминали, что останавливать "всплытие" - плохо?
118
115
119
-
Иногда вместо этого мы можем использовать `event.defaultPrevented`.
116
+
Иногда вместо этого мы можем использовать `event.defaultPrevented`, чтобы просигналить другим обработчикам, что событие обработано.
120
117
121
-
Давайте посмотрим практический пример, где остановка всплытия кажется обязательной, но на самом деле мы можем обойтись без него.
118
+
Давайте посмотрим практический пример.
122
119
123
120
По умолчанию браузер при событии `contextmenu` (клик правой кнопкой мыши) показывает контекстное меню со стандартными опциями. Мы можем отменить событие по умолчанию и показать своё меню, как здесь:
124
121
125
122
```html autorun height=50 no-beautify run
126
-
<button>Кликните правой кнопкой мыши для вызова контекстного меню браузера</button>
123
+
<button>Правый клик вызывает контекстное меню браузера</button>
Кликните правой кнопкой мыши для вызова нашего контекстного меню
126
+
Правый клик вызывает наше контекстное меню
130
127
</button>
131
128
```
132
129
133
-
Теперь предположим, что мы хотим реализовать собственное контекстное меню для всего документа с нашими опциями. И внутри документа мы можем иметь другие элементы, у которых может быть своё контекстное меню:
130
+
Теперь в дополнение к этому контекстному меню реализуем контекстное меню для всего документа.
131
+
132
+
При правом клике должно показываться ближайшее контекстное меню.
134
133
135
134
```html autorun height=80 no-beautify run
136
-
<p>Кликните правой кнопкой здесь для контекстного меню документа</p>
137
-
<buttonid="elem">Кликните правой кнопкой здесь для контекстного меню кнопки</button>
135
+
<p>Правый клик здесь вызывает контекстное меню документа</p>
136
+
<buttonid="elem">Правый клик здесь вызывает контекстное меню кнопки</button>
Проблема заключается в том, что когда мы кликаем по элементу `elem`, то мы получаем два меню: контекстное меню для кнопки и (событие всплывает вверх) контекстное меню для документа.
153
152
154
-
Одним из решений будет полностью обработать событие в обработчике кнопки и остановить всплытие, используя`event.stopPropagation()`:
153
+
Как это поправить? Одно из решений - это подумать: "Когда мы обрабатываем правый клик в обработчике на кнопке, остановим всплытие", и вызвать`event.stopPropagation()`:
155
154
156
155
```html autorun height=80 no-beautify run
157
-
<p>Кликните правой кнопкой для меню документа</p>
158
-
<buttonid="elem">Кликните правой кнопкой для меню кнопки (добавлен event.stopPropagation)</button>
156
+
<p>Правый клик вызывает меню документа</p>
157
+
<buttonid="elem">Правый клик вызывает меню кнопки (добавлен event.stopPropagation)</button>
Есть также несколько альтернативных путей, чтобы реализовать вложенные контекстные меню. Одним из них является специальный глобальный объект с методом, который обрабатывает `document.oncontextmenu`, и также методами, позволяющими хранить в нём различные "низкоуровневые" обработчики.
208
+
Есть также несколько альтернативных путей, чтобы реализовать вложенные контекстные меню. Одним из них является единый глобальный объект с обработчиком `document.oncontextmenu` и методами, позволяющими хранить в нём другие обработчики.
210
209
211
210
Объект будет перехватывать любой клик правой кнопкой мыши, просматривать сохранённые обработчики и запускать соответствующий.
Но нам следует сохранять семантическое значение HTML элементов. Например, не кнопки, а тег `<a>` должен применяться для переходов по ссылкам.
240
238
241
-
Помимо того, что это "хорошо", это делает ваш HTML лучше с точки зрения доступности.
239
+
Помимо того, что это "хорошо", это делает ваш HTML лучше с точки зрения доступности для инвалидов и с особых устройств.
242
240
243
241
Также, если мы рассматриваем пример с тегом `<a>`, то обратите внимание: браузер предоставляет возможность открывать ссылки в новом окне (кликая правой кнопкой мыши или используя другие возможности). И пользователям это нравится. Но если мы заменим ссылку кнопкой и стилизуем её как ссылку, используя CSS, то специфичные функции браузера для тега `<a>` всё равно работать не будут.
0 commit comments