up
Before Width: | Height: | Size: 23 KiB After Width: | Height: | Size: 23 KiB |
Before Width: | Height: | Size: 46 KiB After Width: | Height: | Size: 46 KiB |
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 26 KiB After Width: | Height: | Size: 26 KiB |
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 30 KiB After Width: | Height: | Size: 30 KiB |
0
2-ui/2-events/4-bubbling-and-capturing/both.view/example.css → 2-ui/2-events/02-bubbling-and-capturing/both.view/example.css
Executable file → Normal file
0
2-ui/2-events/4-bubbling-and-capturing/both.view/index.html → 2-ui/2-events/02-bubbling-and-capturing/both.view/index.html
Executable file → Normal file
4
2-ui/2-events/4-bubbling-and-capturing/both.view/script.js → 2-ui/2-events/02-bubbling-and-capturing/both.view/script.js
Executable file → Normal file
|
@ -1,6 +1,6 @@
|
|||
var elems = document.querySelectorAll('form,div,p');
|
||||
let elems = document.querySelectorAll('form,div,p');
|
||||
|
||||
for (var i = 0; i < elems.length; i++) {
|
||||
for (let i = 0; i < elems.length; i++) {
|
||||
elems[i].addEventListener("click", highlightThis, true);
|
||||
elems[i].addEventListener("click", highlightThis, false);
|
||||
}
|
0
2-ui/2-events/4-bubbling-and-capturing/capture.view/index.html → 2-ui/2-events/02-bubbling-and-capturing/capture.view/index.html
Executable file → Normal file
4
2-ui/2-events/4-bubbling-and-capturing/capture.view/script.js → 2-ui/2-events/02-bubbling-and-capturing/capture.view/script.js
Executable file → Normal file
|
@ -1,6 +1,6 @@
|
|||
var elems = document.querySelectorAll('form,div,p');
|
||||
let elems = document.querySelectorAll('form,div,p');
|
||||
|
||||
for (var i = 0; i < elems.length; i++) {
|
||||
for (let i = 0; i < elems.length; i++) {
|
||||
elems[i].addEventListener("click", highlightThis, true);
|
||||
}
|
||||
|
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 25 KiB |
Before Width: | Height: | Size: 75 KiB After Width: | Height: | Size: 75 KiB |
Before Width: | Height: | Size: 172 KiB After Width: | Height: | Size: 172 KiB |
|
@ -45,7 +45,7 @@ let selectedTd;
|
|||
|
||||
*!*
|
||||
table.onclick = function(event) {
|
||||
var target = event.target; // where was the click?
|
||||
let target = event.target; // where was the click?
|
||||
|
||||
if (target.tagName != 'TD') return; // not on TD? Then we're not interested
|
||||
|
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 27 KiB After Width: | Height: | Size: 27 KiB |
0
2-ui/2-events/5-event-delegation/bagua.view/bagua.css → 2-ui/2-events/03-event-delegation/bagua.view/bagua.css
Executable file → Normal file
6
2-ui/2-events/5-event-delegation/bagua.view/index.html → 2-ui/2-events/03-event-delegation/bagua.view/index.html
Executable file → Normal file
|
@ -64,12 +64,12 @@
|
|||
</table>
|
||||
|
||||
<script>
|
||||
var table = document.getElementById('bagua-table');
|
||||
let table = document.getElementById('bagua-table');
|
||||
|
||||
var selectedTd;
|
||||
let selectedTd;
|
||||
|
||||
table.onclick = function(event) {
|
||||
var target = event.target;
|
||||
let target = event.target;
|
||||
|
||||
while (target != this) {
|
||||
if (target.tagName == 'TD') {
|
|
@ -1,4 +1,4 @@
|
|||
# Browser actions
|
||||
# Browser default actions
|
||||
|
||||
Many events automatically lead to browser actions.
|
||||
|
0
2-ui/2-events/7-default-browser-action/menu.view/index.html → 2-ui/2-events/04-default-browser-action/menu.view/index.html
Executable file → Normal file
0
2-ui/2-events/7-default-browser-action/menu.view/menu.css → 2-ui/2-events/04-default-browser-action/menu.view/menu.css
Executable file → Normal file
0
2-ui/2-events/7-default-browser-action/menu.view/menu.js → 2-ui/2-events/04-default-browser-action/menu.view/menu.js
Executable file → Normal file
|
@ -1,4 +1,4 @@
|
|||
# Custom events
|
||||
# Dispatching custom events
|
||||
|
||||
We can not only assign handlers, but also generate events form JavaScript.
|
||||
|
||||
|
@ -141,25 +141,22 @@ For instance:
|
|||
<h1 id="elem">Hello for John!</h1>
|
||||
|
||||
<script>
|
||||
// additional details come with the event to the handler
|
||||
elem.addEventListener("hello", function(event) {
|
||||
alert(*!*event.detail.name*/!*);
|
||||
});
|
||||
|
||||
let event = new CustomEvent("hello", {
|
||||
elem.dispatchEvent(new CustomEvent("hello", {
|
||||
*!*
|
||||
detail: { name: "John" }
|
||||
*/!*
|
||||
});
|
||||
|
||||
elem.dispatchEvent(event);
|
||||
</script>
|
||||
```
|
||||
|
||||
The `detail` property can have any data.
|
||||
The `detail` property can have any data. Technically we could live without, because we can assign any properties into a regular `new Event` object after its creation. But `CustomEvent` provides the special `detail` field for it to evade conflicts with other event properties.
|
||||
|
||||
Once again, technically we can assign any properties into a regular `new Event` object after its creation. But `CustomEvent` provides the special `detail` field, so that we can write to it safely, without conflicts with standard event properties.
|
||||
|
||||
Also using the right class tells something about "what kind of event" it is, and `CustomEvent` is better for that matter. So we should use it for our events.
|
||||
The event class tells something about "what kind of event" it is, and if the event is custom, then we should use `CustomEvent` just to be clear about what it is.
|
||||
|
||||
## event.preventDefault()
|
||||
|
||||
|
@ -189,7 +186,7 @@ A handler set by `rabbit.addEventListener('hide',...)` will learn about that and
|
|||
<script>
|
||||
// hide() will be called automatically in 2 seconds
|
||||
function hide() {
|
||||
let event = new Event("hide", {
|
||||
let event = new CustomEvent("hide", {
|
||||
cancelable: true // without that flag preventDefault doesn't work
|
||||
});
|
||||
if (!rabbit.dispatchEvent(event)) {
|
||||
|
@ -211,13 +208,70 @@ A handler set by `rabbit.addEventListener('hide',...)` will learn about that and
|
|||
</script>
|
||||
```
|
||||
|
||||
|
||||
## Events-in-events are synchronous
|
||||
|
||||
Usually events are processed asynchronously. That is: if the browser is processing `onclick` and in the process a new event occurs, then it awaits till `onclick` processing is finished.
|
||||
|
||||
The exception is when one event is initiated from within another one.
|
||||
|
||||
Then the control jumps to the nested event handler, and after it goes back.
|
||||
|
||||
For instance, here the nested `menu-open` event is processed synchronously, during the `onclick`:
|
||||
|
||||
```html run
|
||||
<button id="menu">Menu (click me)</button>
|
||||
|
||||
<script>
|
||||
// 1 -> nested -> 2
|
||||
menu.onclick = function() {
|
||||
alert(1);
|
||||
|
||||
// alert("nested")
|
||||
menu.dispatchEvent(new CustomEvent("menu-open", {
|
||||
bubbles: true
|
||||
}));
|
||||
|
||||
alert(2);
|
||||
};
|
||||
|
||||
document.addEventListener('menu-open', () => alert('nested'))
|
||||
</script>
|
||||
```
|
||||
|
||||
Please note that the nested event `menu-open` bubbles up and is handled on the `document`. The propagation of the nested event is fully finished before the processing gets back to the outer code (`onclick`).
|
||||
|
||||
That's not only about `dispatchEvent`, there are other cases. JavaScript in an event handler can call methods that lead to other events -- they are too processed synchronously.
|
||||
|
||||
If we don't like it, we can either put the `dispatchEvent` (or other event-triggering call) at the end of `onclick` or, if inconvenient, wrap it in `setTimeout(...,0)`:
|
||||
|
||||
```html run
|
||||
<button id="menu">Menu (click me)</button>
|
||||
|
||||
<script>
|
||||
// 1 -> 2 -> nested
|
||||
menu.onclick = function() {
|
||||
alert(1);
|
||||
|
||||
// alert(2)
|
||||
setTimeout(() => menu.dispatchEvent(new CustomEvent("menu-open", {
|
||||
bubbles: true
|
||||
})), 0);
|
||||
|
||||
alert(2);
|
||||
};
|
||||
|
||||
document.addEventListener('menu-open', () => alert('nested'))
|
||||
</script>
|
||||
```
|
||||
|
||||
## Summary
|
||||
|
||||
To generate an event, we first need to create an event object.
|
||||
|
||||
The generic `Event(name, options)` constructor accepts an arbitrary event name and the `options` object with two properties:
|
||||
- `bubbles:true` if the event should bubble.
|
||||
- `cancelable:true` is the `event.preventDefault()` should work.
|
||||
- `bubbles: true` if the event should bubble.
|
||||
- `cancelable: true` is the `event.preventDefault()` should work.
|
||||
|
||||
Other constructors of native events like `MouseEvent`, `KeyboardEvent` and so on accept properties specific to that event type. For instance, `clientX` for mouse events.
|
||||
|