event options
This commit is contained in:
parent
c8e7222bb2
commit
fa8ffbe998
3 changed files with 31 additions and 9 deletions
|
@ -216,7 +216,7 @@ Web-standard developers understood that long ago and suggested an alternative wa
|
||||||
The syntax to add a handler:
|
The syntax to add a handler:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
element.addEventListener(event, handler[, phase]);
|
element.addEventListener(event, handler[, options]);
|
||||||
```
|
```
|
||||||
|
|
||||||
`event`
|
`event`
|
||||||
|
@ -225,15 +225,17 @@ element.addEventListener(event, handler[, phase]);
|
||||||
`handler`
|
`handler`
|
||||||
: The handler function.
|
: The handler function.
|
||||||
|
|
||||||
`phase`
|
`options`
|
||||||
: An optional argument, the "phase" for the handler to work. To be covered later. Usually we don't use it.
|
: An additional optional object with properties:
|
||||||
|
- `once`: if `true`, then the listener is automatically removed after it triggers.
|
||||||
|
- `capture`: the phrase where to handle the event, to be covered later in the chapter <info:bubbling-and-capturing>. For historical reasons, `options` can also be `false/true`, that's the same as `{capture: false/true}`.
|
||||||
|
- `passive`: if `true`, then the handler will not `preventDefault()`, we'll cover that later in <info:default-browser-action>.
|
||||||
|
|
||||||
|
|
||||||
To remove the handler, use `removeEventListener`:
|
To remove the handler, use `removeEventListener`:
|
||||||
|
|
||||||
|
|
||||||
```js
|
```js
|
||||||
// exactly the same arguments as addEventListener
|
element.removeEventListener(event, handler[, options]);
|
||||||
element.removeEventListener(event, handler[, phase]);
|
|
||||||
```
|
```
|
||||||
|
|
||||||
````warn header="Removal requires the same function"
|
````warn header="Removal requires the same function"
|
||||||
|
|
|
@ -136,9 +136,9 @@ That is: for a click on `<td>` the event first goes through the ancestors chain
|
||||||
|
|
||||||
Handlers added using `on<event>`-property or using HTML attributes or using `addEventListener(event, handler)` don't know anything about capturing, they only run on the 2nd and 3rd phases.
|
Handlers added using `on<event>`-property or using HTML attributes or using `addEventListener(event, handler)` don't know anything about capturing, they only run on the 2nd and 3rd phases.
|
||||||
|
|
||||||
To catch an event on the capturing phase, we need to set the 3rd argument of `addEventListener` to `true`.
|
To catch an event on the capturing phase, we need to set the event options of `addEventListener` to `{capture: true}` (or just `true`).
|
||||||
|
|
||||||
There are two possible values for that optional last argument:
|
There are two possible values `capture` option:
|
||||||
|
|
||||||
- If it's `false` (default), then the handler is set on the bubbling phase.
|
- If it's `false` (default), then the handler is set on the bubbling phase.
|
||||||
- If it's `true`, then the handler is set on the capturing phase.
|
- If it's `true`, then the handler is set on the capturing phase.
|
||||||
|
@ -182,12 +182,16 @@ Please note that `P` shows up two times: at the end of capturing and at the star
|
||||||
|
|
||||||
There's a property `event.eventPhase` that tells us the number of the phase on which the event was caught. But it's rarely used, because we usually know it in the handler.
|
There's a property `event.eventPhase` that tells us the number of the phase on which the event was caught. But it's rarely used, because we usually know it in the handler.
|
||||||
|
|
||||||
|
```smart header="To remove the handler, `removeEventListener` needs the same phase"
|
||||||
|
If we `addEventListener(..., true)`, then we should mention the same phase in `removeEventListener(..., true)` to correctly remove the handler.
|
||||||
|
```
|
||||||
|
|
||||||
## Summary
|
## Summary
|
||||||
|
|
||||||
The event handling process:
|
The event handling process:
|
||||||
|
|
||||||
- When an event happens -- the most nested element where it happens gets labeled as the "target element" (`event.target`).
|
- When an event happens -- the most nested element where it happens gets labeled as the "target element" (`event.target`).
|
||||||
- Then the event first moves from the document root down to the `event.target`, calling handlers assigned with `addEventListener(...., true)` on the way.
|
- Then the event first moves from the document root down to the `event.target`, calling handlers assigned with `addEventListener(...., true)` on the way (`true` is a shorthand for `{capture: true}`).
|
||||||
- Then the event moves from `event.target` up to the root, calling handlers assigned using `on<event>` and `addEventListener` without the 3rd argument or with the 3rd argument `false`.
|
- Then the event moves from `event.target` up to the root, calling handlers assigned using `on<event>` and `addEventListener` without the 3rd argument or with the 3rd argument `false`.
|
||||||
|
|
||||||
Each handler can access `event` object properties:
|
Each handler can access `event` object properties:
|
||||||
|
|
|
@ -93,6 +93,20 @@ But if you click the second one, there's no focus.
|
||||||
|
|
||||||
That's because the browser action is canceled on `mousedown`. The focusing is still possible if we use another way to enter the input. For instance, the `key:Tab` key to switch from the 1st input into the 2nd. But not with the mouse click any more.
|
That's because the browser action is canceled on `mousedown`. The focusing is still possible if we use another way to enter the input. For instance, the `key:Tab` key to switch from the 1st input into the 2nd. But not with the mouse click any more.
|
||||||
|
|
||||||
|
## The "passive" handler option
|
||||||
|
|
||||||
|
The optional `passive: true` option of `addEventListener` signals the browser that the handler is not going to call `preventDefault()`.
|
||||||
|
|
||||||
|
Why that may be needed?
|
||||||
|
|
||||||
|
There are some events like `touchmove` on mobile devices (when the user moves their finger across the screen), that cause scrolling by default, but that scrolling can be prevented using `preventDefault()` in the handler.
|
||||||
|
|
||||||
|
So when the browser detects such event, it has first to process all handlers, and then if `preventDefault` is not called anywhere, it can proceed with scrolling. That may cause unnecessary delays and "jitters" in the UI.
|
||||||
|
|
||||||
|
The `passive: true` options tells the browser that the handler is not going to cancel scrolling. Then browser scrolls immediately providing a maximally fluent experience, and the event is handled by the way.
|
||||||
|
|
||||||
|
For some browsers (Firefox, Chrome), `passive` is `true` by default for `touchstart` and `touchmove` events.
|
||||||
|
|
||||||
|
|
||||||
## event.defaultPrevented
|
## event.defaultPrevented
|
||||||
|
|
||||||
|
@ -215,6 +229,8 @@ All the default actions can be prevented if we want to handle the event exclusiv
|
||||||
|
|
||||||
To prevent a default action -- use either `event.preventDefault()` or `return false`. The second method works only for handlers assigned with `on<event>`.
|
To prevent a default action -- use either `event.preventDefault()` or `return false`. The second method works only for handlers assigned with `on<event>`.
|
||||||
|
|
||||||
|
The `passive: true` option of `addEventListener` tells the browser that the action is not going to be prevented. That's useful for some mobile events, like `touchstart` and `touchmove`, to tell the browser that it should not wait for all handlers to finish before scrolling.
|
||||||
|
|
||||||
If the default action was prevented, the value of `event.defaultPrevented` becomes `true`, otherwise it's `false`.
|
If the default action was prevented, the value of `event.defaultPrevented` becomes `true`, otherwise it's `false`.
|
||||||
|
|
||||||
```warn header="Stay semantic, don't abuse"
|
```warn header="Stay semantic, don't abuse"
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue