up
After Width: | Height: | Size: 23 KiB |
After Width: | Height: | Size: 46 KiB |
|
@ -0,0 +1,51 @@
|
||||||
|
|
||||||
|
First we need to choose a method of positioning the ball.
|
||||||
|
|
||||||
|
We can't use `position:fixed` for it, because scrolling the page would move the ball from the field.
|
||||||
|
|
||||||
|
So we should use `position:absolute` and, to make the positioning really solid, make `field` itself positioned.
|
||||||
|
|
||||||
|
Then the ball will be positioned relatively to the field:
|
||||||
|
|
||||||
|
```css
|
||||||
|
#field {
|
||||||
|
width: 200px;
|
||||||
|
height: 150px;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ball {
|
||||||
|
position: absolute;
|
||||||
|
left: 0; /* relative to the closest positioned ancestor (field) */
|
||||||
|
top: 0;
|
||||||
|
transition: 1s all; /* CSS animation for left/top makes the ball fly */
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Next we need to assign the correct `ball.style.position.left/top`. They contain field-relative coordinates now.
|
||||||
|
|
||||||
|
Here's the picture:
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
We have `event.clientX/clientY` -- window-relative coordinates of the click.
|
||||||
|
|
||||||
|
To get field-relative `left` coordinate of the click, we can substract the field left edge and the border width:
|
||||||
|
|
||||||
|
```js
|
||||||
|
let left = event.clientX - fieldInnerCoords.left - field.clientLeft;
|
||||||
|
```
|
||||||
|
|
||||||
|
Normally, `ball.style.position.left` means the "left edge of the element" (the ball). So if we assign that `left`, then the ball edge would be under the mouse cursor.
|
||||||
|
|
||||||
|
We need to move the ball half-width left and half-height up to make it center.
|
||||||
|
|
||||||
|
So the final `left` would be:
|
||||||
|
|
||||||
|
```js
|
||||||
|
let left = event.clientX - fieldInnerCoords.left - field.clientLeft - ball.offsetWidth/2;
|
||||||
|
```
|
||||||
|
|
||||||
|
The vertical coordinate is calculated using the same logic.
|
||||||
|
|
||||||
|
Please note that the ball width/height must be known at the time we access `ball.offsetWidth`. Should be specified in HTML or CSS.
|
|
@ -0,0 +1,75 @@
|
||||||
|
<!DOCTYPE HTML>
|
||||||
|
<html>
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<style>
|
||||||
|
#field {
|
||||||
|
width: 200px;
|
||||||
|
height: 150px;
|
||||||
|
border: 10px solid black;
|
||||||
|
background-color: #00FF00;
|
||||||
|
position: relative;
|
||||||
|
overflow: hidden;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ball {
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
top: 0;
|
||||||
|
width: 40px;
|
||||||
|
height: 40px;
|
||||||
|
transition: all 1s;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body style="height:2000px">
|
||||||
|
|
||||||
|
Click on a field to move the ball there.
|
||||||
|
<br>
|
||||||
|
|
||||||
|
|
||||||
|
<div id="field">
|
||||||
|
<img src="https://en.js.cx/clipart/ball.svg" id="ball"> . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
|
||||||
|
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
field.onclick = function(event) {
|
||||||
|
|
||||||
|
// window-relative field coordinates
|
||||||
|
let fieldCoords = this.getBoundingClientRect();
|
||||||
|
|
||||||
|
// the ball has position:absolute, the field: position:relative
|
||||||
|
// so ball coordinates are relative to the field inner left-upper corner
|
||||||
|
let ballCoords = {
|
||||||
|
top: event.clientY - fieldInnerCoords.top - field.clientTop - ball.clientHeight / 2,
|
||||||
|
left: event.clientX - fieldInnerCoords.left - field.clientLeft - ball.clientWidth / 2
|
||||||
|
};
|
||||||
|
|
||||||
|
// prevent crossing the top field boundary
|
||||||
|
if (ballCoords.top < 0) ballCoords.top = 0;
|
||||||
|
|
||||||
|
// prevent crossing the left field boundary
|
||||||
|
if (ballCoords.left < 0) ballCoords.left = 0;
|
||||||
|
|
||||||
|
|
||||||
|
// // prevent crossing the right field boundary
|
||||||
|
if (ballCoords.left + ball.clientWidth > field.clientWidth) {
|
||||||
|
ballCoords.left = field.clientWidth - ball.clientWidth;
|
||||||
|
}
|
||||||
|
|
||||||
|
// prevent crossing the bottom field boundary
|
||||||
|
if (ballCoords.top + ball.clientHeight > field.clientHeight) {
|
||||||
|
ballCoords.top = field.clientHeight - ball.clientHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
ball.style.left = ballCoords.left + 'px';
|
||||||
|
ball.style.top = ballCoords.top + 'px';
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,30 @@
|
||||||
|
<!DOCTYPE HTML>
|
||||||
|
<html>
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<style>
|
||||||
|
#field {
|
||||||
|
width: 200px;
|
||||||
|
height: 150px;
|
||||||
|
border: 10px solid black;
|
||||||
|
background-color: #00FF00;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body style="height:2000px">
|
||||||
|
|
||||||
|
Click on a field to move the ball there.
|
||||||
|
<br> The ball should never leave the field.
|
||||||
|
|
||||||
|
|
||||||
|
<div id="field">
|
||||||
|
<img src="https://en.js.cx/clipart/ball.svg" id="ball"> . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
|
||||||
|
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,21 @@
|
||||||
|
importance: 5
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# Move the ball across the field
|
||||||
|
|
||||||
|
Move the ball across the field to a click. Like this:
|
||||||
|
|
||||||
|
[iframe src="solution" height="260" link]
|
||||||
|
|
||||||
|
Requirements:
|
||||||
|
|
||||||
|
- The ball center should come exactly under the pointer on click (if possible without crossing the field edge).
|
||||||
|
- CSS-animation is welcome.
|
||||||
|
- The ball must not cross field boundaries.
|
||||||
|
- When the page is scrolled, nothing should break.
|
||||||
|
|
||||||
|
Notes:
|
||||||
|
|
||||||
|
- The code should also work with different ball and field sizes, not be bound to any fixed values.
|
||||||
|
- Use properties `event.clientX/event.clientY` for click coordinates.
|
After Width: | Height: | Size: 11 KiB |
After Width: | Height: | Size: 26 KiB |
After Width: | Height: | Size: 12 KiB |
After Width: | Height: | Size: 30 KiB |
Before Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 27 KiB |
Before Width: | Height: | Size: 13 KiB |
Before Width: | Height: | Size: 33 KiB |
|
@ -325,6 +325,50 @@ Try the code below. In most browsers only the second handler works, not the firs
|
||||||
```
|
```
|
||||||
````
|
````
|
||||||
|
|
||||||
|
|
||||||
|
## Event object
|
||||||
|
|
||||||
|
To properly handle an event we'd want to know more about what's happened. Not just a "click" or a "keypress", but what were the pointer coordinates? Which key was pressed? And so on.
|
||||||
|
|
||||||
|
When an event happens, the browser creates an *event object*, puts details into it and passes it as an argument to the handler.
|
||||||
|
|
||||||
|
Here's an example of getting mouse coordinates from the event object:
|
||||||
|
|
||||||
|
```html run
|
||||||
|
<input type="button" value="Click me" id="elem">
|
||||||
|
|
||||||
|
<script>
|
||||||
|
elem.onclick = function(*!*event*/!*) {
|
||||||
|
// show event type, element and coordinates of the click
|
||||||
|
alert(event.type + " на " + event.currentTarget);
|
||||||
|
alert(event.clientX + ":" + event.clientY);
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
```
|
||||||
|
|
||||||
|
Some properties of `event` object:
|
||||||
|
|
||||||
|
`event.type`
|
||||||
|
: Event type, here it's `"click"`.
|
||||||
|
|
||||||
|
`event.currentTarget`
|
||||||
|
: Element that handled the event. That's exactly the same as `this`, unless you bind `this` to something else, and then `event.currentTarget` becomes useful.
|
||||||
|
|
||||||
|
`event.clientX / event.clientY`
|
||||||
|
: Window-relative coordinates of the cursor, for mouse events.
|
||||||
|
|
||||||
|
There are more properties. They depend on the event type, so we'll study them later when come to different events in details.
|
||||||
|
|
||||||
|
````smart header="The event object is also accessible from HTML"
|
||||||
|
If we assign a handler in HTML, we can also use the `event` object, like this:
|
||||||
|
|
||||||
|
```html autorun height=60
|
||||||
|
<input type="button" onclick="*!*alert(event.type)*/!*" value="Event type">
|
||||||
|
```
|
||||||
|
|
||||||
|
That's possible because when the browser reads the attribute, it creates a handler like this: `function(event) { alert(event.type) }`. That is: its first argument is called `"event"`, and the body is taken from the attribute.
|
||||||
|
````
|
||||||
|
|
||||||
## Summary
|
## Summary
|
||||||
|
|
||||||
There are 3 ways to assign event handlers:
|
There are 3 ways to assign event handlers:
|
||||||
|
@ -339,4 +383,6 @@ DOM properties are ok to use, but we can't assign more than one handler of the p
|
||||||
|
|
||||||
The last way is the most flexible, but it is also the longest to write. There are few events that only work with it, for instance `transtionend` and `DOMContentLoaded` (to be covered).
|
The last way is the most flexible, but it is also the longest to write. There are few events that only work with it, for instance `transtionend` and `DOMContentLoaded` (to be covered).
|
||||||
|
|
||||||
|
When a handler is called, it gets an event objects as the first argument. It contains details about what's happened. We'll see more of them later.
|
||||||
|
|
||||||
As of now we're just starting to work with events. More details in the next chapters.
|
As of now we're just starting to work with events. More details in the next chapters.
|
||||||
|
|
|
@ -1,36 +0,0 @@
|
||||||
# Мяч под курсор мыши
|
|
||||||
|
|
||||||
Основная сложность первого этапа -- сдвинуть мяч под курсор, т.к. координаты клика `e.clientX/Y` -- относительно окна, а мяч позиционирован абсолютно внутри поля, его координаты `left/top` нужно ставить относительно левого-верхнего внутреннего (внутри рамки!) угла поля.
|
|
||||||
|
|
||||||
Чтобы правильно вычислить координаты мяча, нужно получить координаты угла поля и вычесть их из `clientX/Y`:
|
|
||||||
|
|
||||||
```js
|
|
||||||
var field = document.getElementById('field');
|
|
||||||
var ball = document.getElementById('ball');
|
|
||||||
|
|
||||||
field.onclick = function(e) {
|
|
||||||
|
|
||||||
*!*
|
|
||||||
var fieldCoords = field.getBoundingClientRect();
|
|
||||||
var fieldInnerCoords = {
|
|
||||||
top: fieldCoords.top + field.clientTop,
|
|
||||||
left: fieldCoords.left + field.clientLeft
|
|
||||||
};
|
|
||||||
|
|
||||||
ball.style.left = e.clientX - fieldInnerCoords.left + 'px';
|
|
||||||
ball.style.top = e.clientY - fieldInnerCoords.top + 'px';
|
|
||||||
*/!*
|
|
||||||
|
|
||||||
};
|
|
||||||
```
|
|
||||||
|
|
||||||
Далее мяч нужно сдвинуть на половину его ширины и высоты `ball.clientWidth/clientHeight`, чтобы он оказался центром под курсором.
|
|
||||||
|
|
||||||
Здесь есть важный "подводный камень" -- размеры мяча в исходном документе не прописаны. Там просто стоит `<img>`. Но на момент выполнения JavaScript картинка, возможно, ещё не загрузилась, так что высота и ширина мяча будут неизвестны (а они необходимы для центрирования).
|
|
||||||
|
|
||||||
Нужно добавить `width/height` в тег `<img>` или задать размеры в CSS, тогда на момент выполнения JavaScript будет знать их и передвинет мяч правильно.
|
|
||||||
|
|
||||||
Код, который полностью центрирует мяч, вы найдете в полном решении:
|
|
||||||
|
|
||||||
[iframe border="1" src="solution" height="260" link edit]
|
|
||||||
|
|
|
@ -1,92 +0,0 @@
|
||||||
<!DOCTYPE HTML>
|
|
||||||
<html>
|
|
||||||
|
|
||||||
<head>
|
|
||||||
<meta charset="utf-8">
|
|
||||||
<style>
|
|
||||||
#field {
|
|
||||||
width: 200px;
|
|
||||||
height: 150px;
|
|
||||||
border: 10px groove black;
|
|
||||||
background-color: #00FF00;
|
|
||||||
position: relative;
|
|
||||||
overflow: hidden;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ball {
|
|
||||||
position: absolute;
|
|
||||||
left: 0;
|
|
||||||
top: 0;
|
|
||||||
width: 40px;
|
|
||||||
height: 40px;
|
|
||||||
-webkit-transition: all 1s;
|
|
||||||
-moz-transition: all 1s;
|
|
||||||
-o-transition: all 1s;
|
|
||||||
-ms-transition: all 1s;
|
|
||||||
transition: all 1s;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body style="height:2000px">
|
|
||||||
|
|
||||||
Кликните на любое место поля, чтобы мяч перелетел туда.
|
|
||||||
<br>
|
|
||||||
|
|
||||||
|
|
||||||
<div id="field">
|
|
||||||
<img src="https://js.cx/clipart/ball.svg" id="ball"> . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
|
|
||||||
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
var field = document.getElementById('field');
|
|
||||||
var ball = document.getElementById('ball');
|
|
||||||
|
|
||||||
|
|
||||||
field.onclick = function(event) {
|
|
||||||
|
|
||||||
// координаты поля относительно окна
|
|
||||||
var fieldCoords = this.getBoundingClientRect();
|
|
||||||
|
|
||||||
// координаты левого-верхнего внутреннего угла поля
|
|
||||||
var fieldInnerCoords = {
|
|
||||||
top: fieldCoords.top + field.clientTop,
|
|
||||||
left: fieldCoords.left + field.clientLeft
|
|
||||||
};
|
|
||||||
|
|
||||||
// разместить по клику,
|
|
||||||
// но сдвинув относительно поля (т.к. position:relative)
|
|
||||||
// и сдвинув на половину ширины/высоты
|
|
||||||
// (!) используются координаты относительно окна clientX/Y, как и в fieldCoords
|
|
||||||
var ballCoords = {
|
|
||||||
top: event.clientY - fieldInnerCoords.top - ball.clientHeight / 2,
|
|
||||||
left: event.clientX - fieldInnerCoords.left - ball.clientWidth / 2
|
|
||||||
};
|
|
||||||
|
|
||||||
// вылезает за верхнюю границу - разместить по ней
|
|
||||||
if (ballCoords.top < 0) ballCoords.top = 0;
|
|
||||||
|
|
||||||
// вылезает за левую границу - разместить по ней
|
|
||||||
if (ballCoords.left < 0) ballCoords.left = 0;
|
|
||||||
|
|
||||||
|
|
||||||
// вылезает за правую границу - разместить по ней
|
|
||||||
if (ballCoords.left + ball.clientWidth > field.clientWidth) {
|
|
||||||
ballCoords.left = field.clientWidth - ball.clientWidth;
|
|
||||||
}
|
|
||||||
|
|
||||||
// вылезает за нижнюю границу - разместить по ней
|
|
||||||
if (ballCoords.top + ball.clientHeight > field.clientHeight) {
|
|
||||||
ballCoords.top = field.clientHeight - ball.clientHeight;
|
|
||||||
}
|
|
||||||
|
|
||||||
ball.style.left = ballCoords.left + 'px';
|
|
||||||
ball.style.top = ballCoords.top + 'px';
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
</body>
|
|
||||||
|
|
||||||
</html>
|
|
|
@ -1,40 +0,0 @@
|
||||||
<!DOCTYPE HTML>
|
|
||||||
<html>
|
|
||||||
|
|
||||||
<head>
|
|
||||||
<meta charset="utf-8">
|
|
||||||
<style>
|
|
||||||
#field {
|
|
||||||
width: 200px;
|
|
||||||
height: 150px;
|
|
||||||
border: 10px groove black;
|
|
||||||
background-color: #00FF00;
|
|
||||||
position: relative;
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ball {
|
|
||||||
position: absolute;
|
|
||||||
top: 50%;
|
|
||||||
left: 50%;
|
|
||||||
margin-left: -20px;
|
|
||||||
margin-top: -20px;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body style="height:2000px">
|
|
||||||
|
|
||||||
Кликните на любое место поля, чтобы мяч перелетел туда.
|
|
||||||
<br> Мяч никогда не вылетит за границы поля.
|
|
||||||
|
|
||||||
|
|
||||||
<div id="field">
|
|
||||||
<img src="https://js.cx/clipart/ball.svg" id="ball"> . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
|
|
||||||
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
</body>
|
|
||||||
|
|
||||||
</html>
|
|
|
@ -1,22 +0,0 @@
|
||||||
importance: 5
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
# Передвигать мяч по полю
|
|
||||||
|
|
||||||
Сделайте так, что при клике по полю мяч перемещался на место клика.
|
|
||||||
|
|
||||||
[iframe src="solution" height="260" link]
|
|
||||||
|
|
||||||
Требования:
|
|
||||||
|
|
||||||
- Мяч после перелёта должен становиться центром ровно под курсор мыши, если это возможно без вылета за край поля.
|
|
||||||
- CSS-анимация не обязательна, но желательна.
|
|
||||||
- Мяч должен останавливаться у границ поля, ни в коем случае не вылетать за них.
|
|
||||||
- При прокрутке страницы с полем ничего не должно ломаться.
|
|
||||||
|
|
||||||
Замечания:
|
|
||||||
|
|
||||||
- Код не должен зависеть от конкретных размеров мяча и поля.
|
|
||||||
- Вам пригодятся свойства `event.clientX/event.clientY`
|
|
||||||
|
|
|
@ -1,108 +0,0 @@
|
||||||
# Event object
|
|
||||||
|
|
||||||
To handle an event we'd like to know more about what's happened. For a mouse event we may need to know pointer coordinates, for a keyboard event -- which key was pressed and so on.
|
|
||||||
|
|
||||||
Each kind of event has special properties that browser writes into
|
|
||||||
Детали произошедшего браузер записывает в "объект события", который передаётся первым аргументом в обработчик.
|
|
||||||
|
|
||||||
[cut]
|
|
||||||
|
|
||||||
## Свойства объекта события
|
|
||||||
|
|
||||||
Пример ниже демонстрирует использование объекта события:
|
|
||||||
|
|
||||||
```html run
|
|
||||||
<input type="button" value="Нажми меня" id="elem">
|
|
||||||
|
|
||||||
<script>
|
|
||||||
elem.onclick = function(*!*event*/!*) {
|
|
||||||
// вывести тип события, элемент и координаты клика
|
|
||||||
alert(event.type + " на " + event.currentTarget);
|
|
||||||
alert(event.clientX + ":" + event.clientY);
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
```
|
|
||||||
|
|
||||||
Свойства объекта `event`:
|
|
||||||
|
|
||||||
`event.type`
|
|
||||||
: Тип события, в данном случае `click`
|
|
||||||
|
|
||||||
`event.currentTarget`
|
|
||||||
: Элемент, на котором сработал обработчик. Значение -- в точности такое же, как и у `this`, но бывают ситуации, когда обработчик является методом объекта и его `this` при помощи `bind` привязан к этому объекту, тогда мы можем использовать `event.currentTarget`.
|
|
||||||
|
|
||||||
`event.clientX / event.clientY`
|
|
||||||
: Координаты курсора в момент клика (относительно окна)
|
|
||||||
|
|
||||||
Есть также и ряд других свойств, в зависимости от событий, которые мы разберём в дальнейших главах, когда будем подробно знакомиться с событиями мыши, клавиатуры и так далее.
|
|
||||||
|
|
||||||
````smart header="Объект события доступен и в HTML"
|
|
||||||
При назначении обработчика в HTML, тоже можно использовать переменную `event`, это будет работать кросс-браузерно:
|
|
||||||
|
|
||||||
```html autorun height=60
|
|
||||||
<input type="button" onclick="*!*alert(event.type)*/!*" value="Тип события">
|
|
||||||
```
|
|
||||||
|
|
||||||
Это возможно потому, что когда браузер из атрибута создаёт функцию-обработчик, то она выглядит так: `function(event) { alert(event.type) }`. То есть, её первый аргумент называется `"event"`.
|
|
||||||
````
|
|
||||||
|
|
||||||
## Особенности IE8-
|
|
||||||
|
|
||||||
IE8- вместо передачи параметра обработчику создаёт глобальный объект `window.event`. Обработчик может обратиться к нему.
|
|
||||||
|
|
||||||
Работает это так:
|
|
||||||
|
|
||||||
```js
|
|
||||||
elem.onclick = function() {
|
|
||||||
// window.event - объект события
|
|
||||||
alert( window.event.clientX );
|
|
||||||
};
|
|
||||||
```
|
|
||||||
|
|
||||||
### Кроссбраузерное решение
|
|
||||||
|
|
||||||
Универсальное решение для получения объекта события:
|
|
||||||
|
|
||||||
```js
|
|
||||||
element.onclick = function(event) {
|
|
||||||
event = event || window.event; // (*)
|
|
||||||
|
|
||||||
// Теперь event - объект события во всех браузерах.
|
|
||||||
};
|
|
||||||
```
|
|
||||||
|
|
||||||
Строка `(*)`, в случае, если функция не получила `event` (IE8-), использует `window.event`.-событие `event`.
|
|
||||||
|
|
||||||
Можно написать и иначе, если мы сами не используем переменную `event` в замыкании:
|
|
||||||
|
|
||||||
```js
|
|
||||||
element.onclick = function(e) {
|
|
||||||
e = e || event;
|
|
||||||
|
|
||||||
// Теперь e - объект события во всех браузерах.
|
|
||||||
};
|
|
||||||
```
|
|
||||||
|
|
||||||
## Итого
|
|
||||||
|
|
||||||
- Объект события содержит ценную информацию о деталях события.
|
|
||||||
- Он передается первым аргументом `event` в обработчик для всех браузеров, кроме IE8-, в которых используется глобальная переменная `window.event`.
|
|
||||||
|
|
||||||
Кросс-браузерно для JavaScript-обработчика получаем объект события так:
|
|
||||||
|
|
||||||
```js
|
|
||||||
element.onclick = function(event) {
|
|
||||||
event = event || window.event;
|
|
||||||
|
|
||||||
// Теперь event - объект события во всех браузерах.
|
|
||||||
};
|
|
||||||
```
|
|
||||||
|
|
||||||
Еще вариант:
|
|
||||||
|
|
||||||
```js
|
|
||||||
element.onclick = function(e) {
|
|
||||||
e = e || event; // если нет другой внешней переменной event
|
|
||||||
...
|
|
||||||
};
|
|
||||||
```
|
|
|
@ -1,6 +1,6 @@
|
||||||
# Всплытие и перехват
|
# Bubbling and capturing
|
||||||
|
|
||||||
Давайте сразу начнём с примера.
|
Let's start with an example.
|
||||||
|
|
||||||
Этот обработчик для `<div>` сработает, если вы кликните по вложенному тегу `<em>` или `<code>`:
|
Этот обработчик для `<div>` сработает, если вы кликните по вложенному тегу `<em>` или `<code>`:
|
||||||
|
|
||||||
|
@ -239,4 +239,3 @@ for (var i = 0; i < elems.length; i++) {
|
||||||
2. Разумная -- когда происходит событие, то разумно дать возможность первому сработать обработчику на самом элементе, поскольку он наиболее конкретен. Код, который поставил обработчик именно на этот элемент, знает максимум деталей о том, что это за элемент, чем он занимается.
|
2. Разумная -- когда происходит событие, то разумно дать возможность первому сработать обработчику на самом элементе, поскольку он наиболее конкретен. Код, который поставил обработчик именно на этот элемент, знает максимум деталей о том, что это за элемент, чем он занимается.
|
||||||
|
|
||||||
Далее имеет смысл передать обработку события родителю -- он тоже понимает, что происходит, но уже менее детально, далее -- выше, и так далее, до самого объекта `document`, обработчик на котором реализовывает самую общую функциональность уровня документа.
|
Далее имеет смысл передать обработку события родителю -- он тоже понимает, что происходит, но уже менее детально, далее -- выше, и так далее, до самого объекта `document`, обработчик на котором реализовывает самую общую функциональность уровня документа.
|
||||||
|
|
||||||
|
|
Before Width: | Height: | Size: 9.9 KiB After Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 23 KiB After Width: | Height: | Size: 24 KiB |
Before Width: | Height: | Size: 77 KiB After Width: | Height: | Size: 75 KiB |
Before Width: | Height: | Size: 179 KiB After Width: | Height: | Size: 172 KiB |
Before Width: | Height: | Size: 8.9 KiB After Width: | Height: | Size: 9.4 KiB |
Before Width: | Height: | Size: 21 KiB After Width: | Height: | Size: 22 KiB |