"</tr><tr>"
.
-5. If the month has finished, but the table row is not yet full, add empty `"</tr><tr>"
.
+4. If the month has finished, but the table row is not yet full, add empty `
`, then the sequence is:
-1. `HTML` -> `BODY` -> `FORM` -> `DIV -> P` (capturing phase, the first listener):
-2. `P` -> `DIV` -> `FORM` -> `BODY` -> `HTML` (bubbling phase, the second listener).
-
-Please note, the `P` shows up twice, because we've set two listeners: capturing and bubbling. The target triggers at the end of the first and at the beginning of the second phase.
+1. `HTML` -> `BODY` -> `FORM` -> `DIV` (capturing phase, the first listener):
+2. `P` (target phrase, triggers two times, as we've set two listeners: capturing and bubbling)
+3. `DIV` -> `FORM` -> `BODY` -> `HTML` (bubbling phase, the second listener).
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.
@@ -192,7 +190,7 @@ There's a property `event.eventPhase` that tells us the number of the phase on w
If we `addEventListener(..., true)`, then we should mention the same phase in `removeEventListener(..., true)` to correctly remove the handler.
```
-````smart header="Listeners on the same element and same phase run in their set order"
+````smart header="Listeners on same element and same phase run in their set order"
If we have multiple event handlers on the same phase, assigned to the same element with `addEventListener`, they run in the same order as they are created:
```js
@@ -201,20 +199,14 @@ elem.addEventListener("click", e => alert(2));
```
````
-```smart header="The `event.stopPropagation()` during the capturing also prevents the bubbling"
-The `event.stopPropagation()` method and its sibling `event.stopImmediatePropagation()` can also be called on the capturing phase. Then not only the futher capturing is stopped, but the bubbling as well.
-
-In other words, normally the event goes first down ("capturing") and then up ("bubbling"). But if `event.stopPropagation()` is called during the capturing phase, then the event travel stops, no bubbling will occur.
-```
-
## Summary
When an event happens -- the most nested element where it happens gets labeled as the "target element" (`event.target`).
-- Then the event moves down from the document root to `event.target`, calling handlers assigned with `addEventListener(..., true)` on the way (`true` is a shorthand for `{capture: true}`).
+- Then the event moves down from the document root to `event.target`, calling handlers assigned with `addEventListener(...., true)` on the way (`true` is a shorthand for `{capture: true}`).
- Then handlers are called on the target element itself.
-- Then the event bubbles up from `event.target` to the root, calling handlers assigned using `on Drag the ball. Drag the ball. Mouse over here to see the date Date: ${new Date()} Date: ${new Date()}` may be suited for that exactly ` `, it knows everything about it, so it should get the chance first. Then its immediate parent also knows about the context, but a little bit less, and so on till the very top element that handles general concepts and runs the last one.
+The same for event handlers. The code that set the handler on a particular element knows maximum details about the element and what it does. A handler on a particular ` ` may be suited for that exactly ` `, it knows everything about it, so it should get the chance first. Then its immediate parent also knows about the context, but a little bit less, and so on till the very top element that handles general concepts and runs the last.
Bubbling and capturing lay the foundation for "event delegation" -- an extremely powerful event handling pattern that we study in the next chapter.
diff --git a/2-ui/2-events/02-bubbling-and-capturing/event-order-bubbling.svg b/2-ui/2-events/02-bubbling-and-capturing/event-order-bubbling.svg
index 2ea88f08..e3d74989 100644
--- a/2-ui/2-events/02-bubbling-and-capturing/event-order-bubbling.svg
+++ b/2-ui/2-events/02-bubbling-and-capturing/event-order-bubbling.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/2-ui/2-events/02-bubbling-and-capturing/eventflow.svg b/2-ui/2-events/02-bubbling-and-capturing/eventflow.svg
index 566064cd..e7db9bff 100644
--- a/2-ui/2-events/02-bubbling-and-capturing/eventflow.svg
+++ b/2-ui/2-events/02-bubbling-and-capturing/eventflow.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/2-ui/2-events/03-event-delegation/article.md b/2-ui/2-events/03-event-delegation/article.md
index 88118374..3d8beda0 100644
--- a/2-ui/2-events/03-event-delegation/article.md
+++ b/2-ui/2-events/03-event-delegation/article.md
@@ -1,11 +1,11 @@
# Event delegation
-Capturing and bubbling allow us to implement one of the most powerful event handling patterns called *event delegation*.
+Capturing and bubbling allow us to implement one of most powerful event handling patterns called *event delegation*.
The idea is that if we have a lot of elements handled in a similar way, then instead of assigning a handler to each of them -- we put a single handler on their common ancestor.
-In the handler we get `event.target` to see where the event actually happened and handle it.
+In the handler we get `event.target`, see where the event actually happened and handle it.
Let's see an example -- the [Ba-Gua diagram](http://en.wikipedia.org/wiki/Ba_gua) reflecting the ancient Chinese philosophy.
@@ -101,8 +101,8 @@ table.onclick = function(event) {
Explanations:
1. The method `elem.closest(selector)` returns the nearest ancestor that matches the selector. In our case we look for ` ` on the way up from the source element.
-2. If `event.target` is not inside any ` `, then the call returns immediately, as there's nothing to do.
-3. In case of nested tables, `event.target` may be a ` `, but lying outside of the current table. So we check if that's actually *our table's* ` `.
+2. If `event.target` is not inside any ` `, then the call returns `null`, and we don't have to do anything.
+3. In case of nested tables, `event.target` may be a ` ` lying outside of the current table. So we check if that's actually *our table's* ` `.
4. And, if it's so, then highlight it.
As the result, we have a fast, efficient highlighting code, that doesn't care about the total number of ` ` in the table.
@@ -121,7 +121,7 @@ The first idea may be to assign a separate handler to each button. But there's a
The handler reads the attribute and executes the method. Take a look at the working example:
-```html autorun height=60 run untrusted
+```html autorun height=60 run
```
-If we're on `#parent` and then move the pointer deeper into `#child`, we get `mouseout` on `#parent`!
+If we're on `#parent` and then move the pointer deeper into `#child`, but we get `mouseout` on `#parent`!

diff --git a/2-ui/3-event-details/3-mousemove-mouseover-mouseout-mouseenter-mouseleave/mouseover-bubble-nested.svg b/2-ui/3-event-details/3-mousemove-mouseover-mouseout-mouseenter-mouseleave/mouseover-bubble-nested.svg
index 6044eff1..07830295 100644
--- a/2-ui/3-event-details/3-mousemove-mouseover-mouseout-mouseenter-mouseleave/mouseover-bubble-nested.svg
+++ b/2-ui/3-event-details/3-mousemove-mouseover-mouseout-mouseenter-mouseleave/mouseover-bubble-nested.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/2-ui/3-event-details/3-mousemove-mouseover-mouseout-mouseenter-mouseleave/mouseover-mouseout-from-outside.svg b/2-ui/3-event-details/3-mousemove-mouseover-mouseout-mouseenter-mouseleave/mouseover-mouseout-from-outside.svg
index 22335b52..07176ba2 100644
--- a/2-ui/3-event-details/3-mousemove-mouseover-mouseout-mouseenter-mouseleave/mouseover-mouseout-from-outside.svg
+++ b/2-ui/3-event-details/3-mousemove-mouseover-mouseout-mouseenter-mouseleave/mouseover-mouseout-from-outside.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/2-ui/3-event-details/3-mousemove-mouseover-mouseout-mouseenter-mouseleave/mouseover-mouseout-over-elems.svg b/2-ui/3-event-details/3-mousemove-mouseover-mouseout-mouseenter-mouseleave/mouseover-mouseout-over-elems.svg
index 437f03b1..262ddf59 100644
--- a/2-ui/3-event-details/3-mousemove-mouseover-mouseout-mouseenter-mouseleave/mouseover-mouseout-over-elems.svg
+++ b/2-ui/3-event-details/3-mousemove-mouseover-mouseout-mouseenter-mouseleave/mouseover-mouseout-over-elems.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/2-ui/3-event-details/3-mousemove-mouseover-mouseout-mouseenter-mouseleave/mouseover-mouseout.svg b/2-ui/3-event-details/3-mousemove-mouseover-mouseout-mouseenter-mouseleave/mouseover-mouseout.svg
index 1277ddff..784f435d 100644
--- a/2-ui/3-event-details/3-mousemove-mouseover-mouseout-mouseenter-mouseleave/mouseover-mouseout.svg
+++ b/2-ui/3-event-details/3-mousemove-mouseover-mouseout-mouseenter-mouseleave/mouseover-mouseout.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/2-ui/3-event-details/3-mousemove-mouseover-mouseout-mouseenter-mouseleave/mouseover-to-child.svg b/2-ui/3-event-details/3-mousemove-mouseover-mouseout-mouseenter-mouseleave/mouseover-to-child.svg
index 78210845..b38d76fb 100644
--- a/2-ui/3-event-details/3-mousemove-mouseover-mouseout-mouseenter-mouseleave/mouseover-to-child.svg
+++ b/2-ui/3-event-details/3-mousemove-mouseover-mouseout-mouseenter-mouseleave/mouseover-to-child.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/2-ui/3-event-details/3-mousemove-mouseover-mouseout-mouseenter-mouseleave/mouseoverout-fast.view/script.js b/2-ui/3-event-details/3-mousemove-mouseover-mouseout-mouseenter-mouseleave/mouseoverout-fast.view/script.js
index 5752e83a..6d87199c 100755
--- a/2-ui/3-event-details/3-mousemove-mouseover-mouseout-mouseenter-mouseleave/mouseoverout-fast.view/script.js
+++ b/2-ui/3-event-details/3-mousemove-mouseover-mouseout-mouseenter-mouseleave/mouseoverout-fast.view/script.js
@@ -3,7 +3,7 @@ parent.onmouseover = parent.onmouseout = parent.onmousemove = handler;
function handler(event) {
let type = event.type;
- while (type.length < 11) type += ' ';
+ while (type < 11) type += ' ';
log(type + " target=" + event.target.id)
return false;
diff --git a/2-ui/3-event-details/4-mouse-drag-and-drop/2-drag-heroes/solution.view/field.svg b/2-ui/3-event-details/4-mouse-drag-and-drop/2-drag-heroes/solution.view/field.svg
index f5bd9f4f..ca8bbc3b 100644
--- a/2-ui/3-event-details/4-mouse-drag-and-drop/2-drag-heroes/solution.view/field.svg
+++ b/2-ui/3-event-details/4-mouse-drag-and-drop/2-drag-heroes/solution.view/field.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/2-ui/3-event-details/4-mouse-drag-and-drop/article.md b/2-ui/3-event-details/4-mouse-drag-and-drop/article.md
index 4c928eef..b74c13f1 100644
--- a/2-ui/3-event-details/4-mouse-drag-and-drop/article.md
+++ b/2-ui/3-event-details/4-mouse-drag-and-drop/article.md
@@ -4,9 +4,9 @@ Drag'n'Drop is a great interface solution. Taking something and dragging and dro
In the modern HTML standard there's a [section about Drag and Drop](https://html.spec.whatwg.org/multipage/interaction.html#dnd) with special events such as `dragstart`, `dragend`, and so on.
-These events allow us to support special kinds of drag'n'drop, such as handling dragging a file from OS file-manager and dropping it into the browser window. Then JavaScript can access the contents of such files.
+These events are useful in that they allow us to solve simple tasks easily. For instance, they allow us to handle the drag'n'drop of "external" files into the browser, so we can take a file in the OS file-manager and drop it into the browser window, thereby giving JavaScript access to its contents.
-But native Drag Events also have limitations. For instance, we can't prevent dragging from a certain area. Also we can't make the dragging "horizontal" or "vertical" only. And there are many other drag'n'drop tasks that can't be done using them. Also, mobile device support for such events is very weak.
+But native Drag Events also have limitations. For instance, we can't limit dragging by a certain area. Also we can't make it "horizontal" or "vertical" only. And there are other drag'n'drop tasks that can't be done using that API. Also, mobile device support for such events is almost non-existant.
So here we'll see how to implement Drag'n'Drop using mouse events.
@@ -14,23 +14,26 @@ So here we'll see how to implement Drag'n'Drop using mouse events.
The basic Drag'n'Drop algorithm looks like this:
-1. On `mousedown` - prepare the element for moving, if needed (maybe create a clone of it, add a class to it or whatever).
-2. Then on `mousemove` move it by changing `left/top` with `position:absolute`.
-3. On `mouseup` - perform all actions related to finishing the drag'n'drop.
+1. On `mousedown` - prepare the element for moving, if needed (maybe create a copy of it).
+2. Then on `mousemove` move it by changing `left/top` and `position:absolute`.
+3. On `mouseup` - perform all actions related to a finished Drag'n'Drop.
-These are the basics. Later we'll see how to add other features, such as highlighting current underlying elements while we drag over them.
+These are the basics. Later we can extend it, for instance, by highlighting droppable (available for the drop) elements when hovering over them.
-Here's the implementation of dragging a ball:
+Here's the algorithm for drag'n'drop of a ball:
```js
-ball.onmousedown = function(event) {
- // (1) prepare to moving: make absolute and on top by z-index
+ball.onmousedown = function(event) { // (1) start the process
+
+ // (2) prepare to moving: make absolute and on top by z-index
ball.style.position = 'absolute';
ball.style.zIndex = 1000;
-
// move it out of any current parents directly into body
// to make it positioned relative to the body
- document.body.append(ball);
+ document.body.append(ball);
+ // ...and put that absolutely positioned ball under the pointer
+
+ moveAt(event.pageX, event.pageY);
// centers the ball at (pageX, pageY) coordinates
function moveAt(pageX, pageY) {
@@ -38,17 +41,14 @@ ball.onmousedown = function(event) {
ball.style.top = pageY - ball.offsetHeight / 2 + 'px';
}
- // move our absolutely positioned ball under the pointer
- moveAt(event.pageX, event.pageY);
-
function onMouseMove(event) {
moveAt(event.pageX, event.pageY);
}
- // (2) move the ball on mousemove
+ // (3) move the ball on mousemove
document.addEventListener('mousemove', onMouseMove);
- // (3) drop the ball, remove unneeded handlers
+ // (4) drop the ball, remove unneeded handlers
ball.onmouseup = function() {
document.removeEventListener('mousemove', onMouseMove);
ball.onmouseup = null;
@@ -64,10 +64,10 @@ Here's an example in action:
[iframe src="ball" height=230]
-Try to drag'n'drop with the mouse and you'll see such behavior.
+Try to drag'n'drop the mouse and you'll see such behavior.
```
-That's because the browser has its own drag'n'drop support for images and some other elements. It runs automatically and conflicts with ours.
+That's because the browser has its own Drag'n'Drop for images and some other elements that runs automatically and conflicts with ours.
To disable it:
@@ -93,14 +93,14 @@ So we should listen on `document` to catch it.
## Correct positioning
-In the examples above the ball is always moved so that its center is under the pointer:
+In the examples above the ball is always moved so, that it's center is under the pointer:
```js
ball.style.left = pageX - ball.offsetWidth / 2 + 'px';
ball.style.top = pageY - ball.offsetHeight / 2 + 'px';
```
-Not bad, but there's a side effect. To initiate the drag'n'drop, we can `mousedown` anywhere on the ball. But if "take" it from its edge, then the ball suddenly "jumps" to become centered under the mouse pointer.
+Not bad, but there's a side-effect. To initiate the drag'n'drop, we can `mousedown` anywhere on the ball. But if "take" it from its edge, then the ball suddenly "jumps" to become centered under the mouse pointer.
It would be better if we keep the initial shift of the element relative to the pointer.
@@ -124,7 +124,7 @@ Let's update our algorithm:
```js
// onmousemove
- // ball has position:absolute
+ // ball has position:absoute
ball.style.left = event.pageX - *!*shiftX*/!* + 'px';
ball.style.top = event.pageY - *!*shiftY*/!* + 'px';
```
@@ -219,7 +219,7 @@ That's why the initial idea to put handlers on potential droppables doesn't work
So, what to do?
-There's a method called `document.elementFromPoint(clientX, clientY)`. It returns the most nested element on given window-relative coordinates (or `null` if given coordinates are out of the window). If there are multiple overlapping elements on the same coordinates, then the topmost one is returned.
+There's a method called `document.elementFromPoint(clientX, clientY)`. It returns the most nested element on given window-relative coordinates (or `null` if given coordinates are out of the window).
We can use it in any of our mouse event handlers to detect the potential droppable under the pointer, like this:
@@ -276,7 +276,7 @@ function onMouseMove(event) {
}
```
-In the example below when the ball is dragged over the soccer goal, the goal is highlighted.
+In the example below when the ball is dragged over the soccer gate, the gate is highlighted.
[codetabs height=250 src="ball4"]
@@ -300,4 +300,4 @@ We can lay a lot on this foundation.
- We can use event delegation for `mousedown/up`. A large-area event handler that checks `event.target` can manage Drag'n'Drop for hundreds of elements.
- And so on.
-There are frameworks that build architecture over it: `DragZone`, `Droppable`, `Draggable` and other classes. Most of them do the similar stuff to what's described above, so it should be easy to understand them now. Or roll your own, as you can see that that's easy enough to do, sometimes easier than adapting a third-party solution.
+There are frameworks that build architecture over it: `DragZone`, `Droppable`, `Draggable` and other classes. Most of them do the similar stuff to described above, so it should be easy to understand them now. Or roll our own, as you can see that's easy enough to do, sometimes easier than adapting a third-part solution.
diff --git a/2-ui/3-event-details/4-mouse-drag-and-drop/ball.view/index.html b/2-ui/3-event-details/4-mouse-drag-and-drop/ball.view/index.html
index 8751c70a..3fdd7fe7 100644
--- a/2-ui/3-event-details/4-mouse-drag-and-drop/ball.view/index.html
+++ b/2-ui/3-event-details/4-mouse-drag-and-drop/ball.view/index.html
@@ -13,13 +13,16 @@
```
-The `onkeydown` handler here uses `checkPhoneKey` to check for the key pressed. If it's valid (from `0..9` or one of `+-()`), then it returns `true`, otherwise `false`.
+Please note that special keys, such as `key:Backspace`, `key:Left`, `key:Right`, `key:Ctrl+V`, do not work in the input. That's a side-effect of the strict filter `checkPhoneKey`.
-As we know, the `false` value returned from the event handler, assigned using a DOM property or an attribute, such as above, prevents the default action, so nothing appears in the `` for keys that don't pass the test. (The `true` value returned doesn't affect anything, only returning `false` matters)
+Let's relax it a little bit:
-Please note that special keys, such as `key:Backspace`, `key:Left`, `key:Right`, do not work in the input. That's a side effect of the strict filter `checkPhoneKey`. These keys make it return `false`.
-
-Let's relax the filter a little bit by allowing arrow keys `key:Left`, `key:Right` and `key:Delete`, `key:Backspace`:
```html autorun height=60 run
@@ -165,9 +162,7 @@ function checkPhoneKey(key) {
Now arrows and deletion works well.
-Even though we have the key filter, one still can enter anything using a mouse and right-click + Paste. Mobile devices provide other means to enter values. So the filter is not 100% reliable.
-
-The alternative approach would be to track the `oninput` event -- it triggers *after* any modification. There we can check the new `input.value` and modify it/highlight the `` when it's invalid. Or we can use both event handlers together.
+...But we still can enter anything by using a mouse and right-click + Paste. So the filter is not 100% reliable. We can just let it be like that, because most of time it works. Or an alternative approach would be to track the `input` event -- it triggers after any modification. There we can check the new value and highlight/modify it when it's invalid.
## Legacy
@@ -175,12 +170,6 @@ In the past, there was a `keypress` event, and also `keyCode`, `charCode`, `whic
There were so many browser incompatibilities while working with them, that developers of the specification had no way, other than deprecating all of them and creating new, modern events (described above in this chapter). The old code still works, as browsers keep supporting them, but there's totally no need to use those any more.
-## Mobile Keyboards
-
-When using virtual/mobile keyboards, formally known as IME (Input-Method Editor), the W3C standard states that a KeyboardEvent's [`e.keyCode` should be `229`](https://www.w3.org/TR/uievents/#determine-keydown-keyup-keyCode) and [`e.key` should be `"Unidentified"`](https://www.w3.org/TR/uievents-key/#key-attr-values).
-
-While some of these keyboards might still use the right values for `e.key`, `e.code`, `e.keyCode`... when pressing certain keys such as arrows or backspace, there's no guarantee, so your keyboard logic might not always work on mobile devices.
-
## Summary
Pressing a key always generates a keyboard event, be it symbol keys or special keys like `key:Shift` or `key:Ctrl` and so on. The only exception is `key:Fn` key that sometimes presents on a laptop keyboard. There's no keyboard event for it, because it's often implemented on lower level than OS.
diff --git a/2-ui/3-event-details/5-keyboard-events/german-layout.svg b/2-ui/3-event-details/5-keyboard-events/german-layout.svg
new file mode 100644
index 00000000..8a880e8e
--- /dev/null
+++ b/2-ui/3-event-details/5-keyboard-events/german-layout.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/2-ui/3-event-details/7-keyboard-events/keyboard-dump.view/index.html b/2-ui/3-event-details/5-keyboard-events/keyboard-dump.view/index.html
similarity index 95%
rename from 2-ui/3-event-details/7-keyboard-events/keyboard-dump.view/index.html
rename to 2-ui/3-event-details/5-keyboard-events/keyboard-dump.view/index.html
index a0d5a4f4..40106283 100644
--- a/2-ui/3-event-details/7-keyboard-events/keyboard-dump.view/index.html
+++ b/2-ui/3-event-details/5-keyboard-events/keyboard-dump.view/index.html
@@ -28,7 +28,7 @@
-
+
diff --git a/2-ui/3-event-details/7-keyboard-events/keyboard-dump.view/script.js b/2-ui/3-event-details/5-keyboard-events/keyboard-dump.view/script.js
similarity index 96%
rename from 2-ui/3-event-details/7-keyboard-events/keyboard-dump.view/script.js
rename to 2-ui/3-event-details/5-keyboard-events/keyboard-dump.view/script.js
index d97f7a7b..5eba24c7 100644
--- a/2-ui/3-event-details/7-keyboard-events/keyboard-dump.view/script.js
+++ b/2-ui/3-event-details/5-keyboard-events/keyboard-dump.view/script.js
@@ -5,8 +5,6 @@ let lastTime = Date.now();
function handle(e) {
if (form.elements[e.type + 'Ignore'].checked) return;
- area.scrollTop = 1e6;
-
let text = e.type +
' key=' + e.key +
' code=' + e.code +
diff --git a/2-ui/3-event-details/7-keyboard-events/keyboard-dump.view/style.css b/2-ui/3-event-details/5-keyboard-events/keyboard-dump.view/style.css
similarity index 100%
rename from 2-ui/3-event-details/7-keyboard-events/keyboard-dump.view/style.css
rename to 2-ui/3-event-details/5-keyboard-events/keyboard-dump.view/style.css
diff --git a/2-ui/3-event-details/5-keyboard-events/us-layout.svg b/2-ui/3-event-details/5-keyboard-events/us-layout.svg
new file mode 100644
index 00000000..699277e0
--- /dev/null
+++ b/2-ui/3-event-details/5-keyboard-events/us-layout.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/2-ui/3-event-details/6-pointer-events/article.md b/2-ui/3-event-details/6-pointer-events/article.md
deleted file mode 100644
index b8873e9d..00000000
--- a/2-ui/3-event-details/6-pointer-events/article.md
+++ /dev/null
@@ -1,282 +0,0 @@
-# Pointer events
-
-Pointer events are a modern way to handle input from a variety of pointing devices, such as a mouse, a pen/stylus, a touchscreen, and so on.
-
-## The brief history
-
-Let's make a small overview, so that you understand the general picture and the place of Pointer Events among other event types.
-
-- Long ago, in the past, there were only mouse events.
-
- Then touch devices became widespread, phones and tablets in particular. For the existing scripts to work, they generated (and still generate) mouse events. For instance, tapping a touchscreen generates `mousedown`. So touch devices worked well with web pages.
-
- But touch devices have more capabilities than a mouse. For example, it's possible to touch multiple points at once ("multi-touch"). Although, mouse events don't have necessary properties to handle such multi-touches.
-
-- So touch events were introduced, such as `touchstart`, `touchend`, `touchmove`, that have touch-specific properties (we don't cover them in detail here, because pointer events are even better).
-
- Still, it wasn't enough, as there are many other devices, such as pens, that have their own features. Also, writing code that listens for both touch and mouse events was cumbersome.
-
-- To solve these issues, the new standard Pointer Events was introduced. It provides a single set of events for all kinds of pointing devices.
-
-As of now, [Pointer Events Level 2](https://www.w3.org/TR/pointerevents2/) specification is supported in all major browsers, while the newer [Pointer Events Level 3](https://w3c.github.io/pointerevents/) is in the works and is mostly compatible with Pointer Events level 2.
-
-Unless you develop for old browsers, such as Internet Explorer 10, or for Safari 12 or below, there's no point in using mouse or touch events any more -- we can switch to pointer events.
-
-Then your code will work well with both touch and mouse devices.
-
-That said, there are some important peculiarities that one should know in order to use Pointer Events correctly and avoid surprises. We'll make note of them in this article.
-
-## Pointer event types
-
-Pointer events are named similarly to mouse events:
-
-| Pointer event | Similar mouse event |
-|---------------|-------------|
-| `pointerdown` | `mousedown` |
-| `pointerup` | `mouseup` |
-| `pointermove` | `mousemove` |
-| `pointerover` | `mouseover` |
-| `pointerout` | `mouseout` |
-| `pointerenter` | `mouseenter` |
-| `pointerleave` | `mouseleave` |
-| `pointercancel` | - |
-| `gotpointercapture` | - |
-| `lostpointercapture` | - |
-
-As we can see, for every `mouse
-
-
-
-
-
diff --git a/2-ui/3-event-details/6-pointer-events/ball.view/index.html b/2-ui/3-event-details/6-pointer-events/ball.view/index.html
deleted file mode 100644
index 8bbef8f6..00000000
--- a/2-ui/3-event-details/6-pointer-events/ball.view/index.html
+++ /dev/null
@@ -1,30 +0,0 @@
-
-
-
-
-
-
-
-
diff --git a/2-ui/3-event-details/6-pointer-events/multitouch.view/index.html b/2-ui/3-event-details/6-pointer-events/multitouch.view/index.html
deleted file mode 100644
index d46e1bc1..00000000
--- a/2-ui/3-event-details/6-pointer-events/multitouch.view/index.html
+++ /dev/null
@@ -1,28 +0,0 @@
-
-
-
-
-