Skip to content

Commit 12b579a

Browse files
committed
Update "Coordinates" files
1 parent 2593a68 commit 12b579a

File tree

10 files changed

+93
-72
lines changed

10 files changed

+93
-72
lines changed

2-ui/1-document/11-coordinates/2-position-at/source.view/index.html

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,13 @@
4141
* relative to the anchor element.
4242
*/
4343
function showNote(anchor, position, html) {
44-
// ... your code ...
44+
45+
let note = document.createElement('div');
46+
note.className = "note";
47+
note.innerHTML = html;
48+
document.body.append(note);
49+
50+
positionAt(anchor, position, note);
4551
}
4652

4753
// test it

2-ui/1-document/11-coordinates/2-position-at/task.md

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,15 @@ importance: 5
44

55
# Show a note near the element
66

7-
Create a function `positionAt(anchor, position, elem)` that positions `elem`, depending on `position` either at the top (`"top"`), right (`"right"`) or bottom (`"bottom"`) of the element `anchor`.
7+
Create a function `positionAt(anchor, position, elem)` that positions `elem`, depending on `position` near `anchor` element.
88

9-
Call it inside the function `showNote(anchor, position, html)` that shows an element with the class `"note"` and the text `html` at the given position near the anchor.
9+
The `position` must be a string with any one of 3 values:
10+
- `"top"` - position `elem` right above `anchor`
11+
- `"right"` - position `elem` immediately at the right of `anchor`
12+
- `"bottom"` - position `elem` right below `anchor`
1013

11-
Show the notes like here:
14+
It's used inside function `showNote(anchor, position, html)`, provided in the task source code, that creates a "note" element with given `html` and shows it at the given `position` near the `anchor`.
1215

13-
[iframe src="solution" height="350" border="1" link]
16+
Here's the demo of notes:
1417

15-
P.S. The note should have `position:fixed` for this task.
18+
[iframe src="solution" height="350" border="1" link]

2-ui/1-document/11-coordinates/article.md

Lines changed: 61 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -4,56 +4,68 @@ To move elements around we should be familiar with coordinates.
44

55
Most JavaScript methods deal with one of two coordinate systems:
66

7-
1. Relative to the window(or another viewport) top/left.
8-
2. Relative to the document top/left.
7+
1. **Relative to the window** - similar to `position:fixed`, calculated from the window top/left edge.
8+
- we'll denote these coordinates as `clientX/clientY`, the reasoning for such name will become clear later, when we study event properties.
9+
2. **Relative to the document** - similar to `position:absolute` in the document root, calculated from the document top/left edge.
10+
- we'll denote them `pageX/pageY`.
911

10-
It's important to understand the difference and which type is where.
12+
When the page is scrolled to the very beginning, so that the top/left corner of the window is exactly the document top/left corner, these coordinates equal each other. But after the document shifts, window-relative coordinates of elements change, as elements move across the window, while document-relative coordinates remain the same.
1113

12-
## Window coordinates: getBoundingClientRect
14+
On this picture we take a point in the document and demonstrate its coordinates before the scroll (left) and after it (right):
1315

14-
Window coordinates start at the upper-left corner of the window.
16+
![](document-and-window-coordinates-scrolled.svg)
1517

16-
The method `elem.getBoundingClientRect()` returns window coordinates for `elem` as an object with properties:
18+
When the document scrolled:
19+
- `pageY` - document-relative coordinate stayed the same, it's counted from the document top (now scrolled out).
20+
- `clientY` - window-relative coordinate did change (the arrow became shorter), as the same point became closer to window top.
1721

18-
- `top` -- Y-coordinate for the top element edge,
19-
- `left` -- X-coordinate for the left element edge,
20-
- `right` -- X-coordinate for the right element edge,
21-
- `bottom` -- Y-coordinate for the bottom element edge.
22+
## Element coordinates: getBoundingClientRect
2223

23-
Like this:
24+
The method `elem.getBoundingClientRect()` returns window coordinates for a minimal rectangle that encloses `elem` as an object of built-in [DOMRect](https://www.w3.org/TR/geometry-1/#domrect) class.
2425

25-
![](coords.png)
26+
Main `DOMRect` properties:
2627

28+
- `x/y` -- X/Y-coordinates of the rectangle origin relative to window,
29+
- `width/height` -- width/height of the rectangle (can be negative).
2730

28-
Window coordinates do not take the scrolled out part of the document into account, they are calculated from the window's upper-left corner.
31+
Additionally, there are derived properties:
2932

30-
In other words, when we scroll the page, the element goes up or down, *its window coordinates change*. That's very important.
33+
- `top/bottom` -- Y-coordinate for the top/bottom rectangle edge,
34+
- `left/right` -- X-coordinate for the left/right rectangle edge.
3135

3236
```online
33-
Click the button to see its window coordinates:
37+
For instance click this button to see its window coordinates:
3438
35-
<input id="brTest" type="button" value="Show button.getBoundingClientRect() for this button" onclick='showRect(this)'/>
39+
<p><input id="brTest" type="button" value="Get coordinates using button.getBoundingClientRect() for this button" onclick='showRect(this)'/></p>
3640
3741
<script>
3842
function showRect(elem) {
3943
let r = elem.getBoundingClientRect();
40-
alert("{top:"+r.top+", left:"+r.left+", right:"+r.right+", bottom:"+ r.bottom + "}");
44+
alert(`x:${r.x}
45+
y:${r.y}
46+
width:${r.width}
47+
height:${r.height}
48+
top:${r.top}
49+
bottom:${r.bottom}
50+
left:${r.left}
51+
right:${r.right}
52+
`);
4153
}
4254
</script>
4355
44-
If you scroll the page, the button position changes, and window coordinates as well.
56+
If you scroll the page and repeat, you'll notice that as window-relative button position changes, its window coordinates (`y/top/bottom` if you scroll vertically) change as well.
4557
```
4658

47-
Also:
59+
Here's the picture of `elem.getBoundingClientRect()` output:
4860

49-
- Coordinates may be decimal fractions. That's normal, internally browser uses them for calculations. We don't have to round them when setting to `style.position.left/top`, the browser is fine with fractions.
50-
- Coordinates may be negative. For instance, if the page is scrolled down and the top `elem` is now above the window. Then, `elem.getBoundingClientRect().top` is negative.
51-
- Some browsers (like Chrome) provide additional properties, `width` and `height` of the element that invoked the method to `getBoundingClientRect` as the result. We can also get them by subtraction: `height=bottom-top`, `width=right-left`.
61+
![](coordinates.svg)
5262

53-
```warn header="Coordinates right/bottom are different from CSS properties"
54-
If we compare window coordinates versus CSS positioning, then there are obvious similarities to `position:fixed`. The positioning of an element is also relative to the viewport.
63+
As you can see, `x/y` and `width/height` fully describe the rectangle. Derived properties can be easily calculated from them:
5564

56-
But in CSS, the `right` property means the distance from the right edge, and the `bottom` property means the distance from the bottom edge.
65+
- `left = x`
66+
- `top = y`
67+
- `right = x + width`
68+
- `bottom = y + height`
5769

5870
Please note:
5971

@@ -119,8 +131,6 @@ The method `document.elementFromPoint(x,y)` only works if `(x,y)` are inside the
119131

120132
If any of the coordinates is negative or exceeds the window width/height, then it returns `null`.
121133

122-
In most cases such behavior is not a problem, but we should keep that in mind.
123-
124134
Here's a typical error that may occur if we don't check for it:
125135

126136
```js
@@ -132,11 +142,11 @@ elem.style.background = ''; // Error!
132142
```
133143
````
134144
135-
## Using for position:fixed
145+
## Using for "fixed" positioning
136146
137-
Most of time we need coordinates to position something. In CSS, to position an element relative to the viewport we use `position:fixed` together with `left/top` (or `right/bottom`).
147+
Most of time we need coordinates in order to position something.
138148
139-
We can use `getBoundingClientRect` to get coordinates of an element, and then to show something near it.
149+
To show something near an element, we can use `getBoundingClientRect` to get its coordinates, and then CSS `position` together with `left/top` (or `right/bottom`).
140150
141151
For instance, the function `createMessageUnder(elem, html)` below shows the message under `elem`:
142152
@@ -183,32 +193,14 @@ The reason is obvious: the message element relies on `position:fixed`, so it rem
183193
184194
To change that, we need to use document-based coordinates and `position:absolute`.
185195
186-
## Document coordinates
196+
## Document coordinates [#getCoords]
187197
188198
Document-relative coordinates start from the upper-left corner of the document, not the window.
189199
190200
In CSS, window coordinates correspond to `position:fixed`, while document coordinates are similar to `position:absolute` on top.
191201
192202
We can use `position:absolute` and `top/left` to put something at a certain place of the document, so that it remains there during a page scroll. But we need the right coordinates first.
193203
194-
For clarity we'll call window coordinates `(clientX,clientY)` and document coordinates `(pageX,pageY)`.
195-
196-
When the page is not scrolled, then window coordinate and document coordinates are actually the same. Their zero points match too:
197-
198-
![](document-window-coordinates-zero.png)
199-
200-
And if we scroll it, then `(clientX,clientY)` change, because they are relative to the window, but `(pageX,pageY)` remain the same.
201-
202-
Here's the same page after the vertical scroll:
203-
204-
![](document-window-coordinates-scroll.png)
205-
206-
- `clientY` of the header `"From today's featured article"` became `0`, because the element is now on window top.
207-
- `clientX` didn't change, as we didn't scroll horizontally.
208-
- `pageX` and `pageY` coordinates of the element are still the same, because they are relative to the document.
209-
210-
## Getting document coordinates [#getCoords]
211-
212204
There's no standard method to get the document coordinates of an element. But it's easy to write it.
213205
214206
The two coordinate systems are connected by the formula:
@@ -231,6 +223,26 @@ function getCoords(elem) {
231223
}
232224
```
233225
226+
If in the example above we used it with `position:absolute`, then the message would stay near the element on scroll.
227+
228+
The modified `createMessageUnder` function:
229+
230+
```js
231+
function createMessageUnder(elem, html) {
232+
let message = document.createElement('div');
233+
message.style.cssText = "*!*position:absolute*/!*; color: red";
234+
235+
let coords = *!*getCoords(elem);*/!*
236+
237+
message.style.left = coords.left + "px";
238+
message.style.top = coords.bottom + "px";
239+
240+
message.innerHTML = html;
241+
242+
return message;
243+
}
244+
```
245+
234246
## Summary
235247
236248
Any point on the page has coordinates:
-36.4 KB
Binary file not shown.
-87.8 KB
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.

2-ui/1-document/11-coordinates/head.html

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,30 @@
11
<script>
22
document.addEventListener('DOMContentLoaded', function() {
33

4-
let elem = document.getElementById('coords-show-mark');
4+
let elem = document.getElementById('coords-show-mark');
55

6-
// no elem in ebook mode
7-
if (elem) {
8-
elem.onclick = function() {
6+
// no elem in ebook (pdf/epub) mode
7+
if (elem) {
8+
elem.onclick = function() {
99

10-
function createMessageUnder(elem, text) {
11-
let coords = elem.getBoundingClientRect();
12-
let message = document.createElement('div');
13-
message.style.cssText = "position:fixed; color: red";
10+
function createMessageUnder(elem, text) {
11+
let coords = elem.getBoundingClientRect();
12+
let message = document.createElement('div');
13+
message.style.cssText = "position:fixed; color: red";
1414

15-
message.style.left = coords.left + "px";
16-
message.style.top = coords.bottom + "px";
15+
message.style.left = coords.left + "px";
16+
message.style.top = coords.bottom + "px";
1717

18-
message.innerHTML = text;
18+
message.innerHTML = text;
1919

20-
return message;
21-
}
20+
return message;
21+
}
2222

23-
let message = createMessageUnder(elem, 'Hello, world!');
24-
document.body.append(message);
25-
setTimeout(() => message.remove(), 5000);
23+
let message = createMessageUnder(elem, 'Hello, world!');
24+
document.body.append(message);
25+
setTimeout(() => message.remove(), 5000);
26+
}
2627
}
27-
}
2828

2929
});
3030

0 commit comments

Comments
 (0)