This commit is contained in:
Ilya Kantor 2017-03-21 14:41:49 +03:00
parent 4ae129054e
commit ab9ab64bd5
476 changed files with 3370 additions and 532 deletions

View 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);
}

View 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);
}

View file

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 11 KiB

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 25 KiB

After

Width:  |  Height:  |  Size: 25 KiB

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 75 KiB

After

Width:  |  Height:  |  Size: 75 KiB

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 172 KiB

After

Width:  |  Height:  |  Size: 172 KiB

Before After
Before After

View file

@ -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

View file

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 12 KiB

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 27 KiB

After

Width:  |  Height:  |  Size: 27 KiB

Before After
Before After

View 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') {

View file

@ -1,4 +1,4 @@
# Browser actions
# Browser default actions
Many events automatically lead to browser actions.

View 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.