This commit is contained in:
Ilya Kantor 2019-07-01 19:06:32 +03:00
parent 9a7deaeab9
commit a17282b510
3 changed files with 23 additions and 21 deletions

View file

@ -342,7 +342,7 @@ Just remember: `if (~str.indexOf(...))` reads as "if found".
Technically speaking, numbers are truncated to 32 bits by `~` operator, so there exist other big numbers that give `0`, the smallest is `~4294967295=0`. That makes such check is correct only if a string is not that long.
Right now we can see it only in the old code, as modern JavaScript provides `.includes` method (see below).
Right now we can see this trick only in the old code, as modern JavaScript provides `.includes` method (see below).
### includes, startsWith, endsWith

View file

@ -2,7 +2,7 @@
Drag'n'Drop is a great interface solution. Taking something, dragging and dropping is a clear and simple way to do many things, from copying and moving (see file managers) to ordering (drop into cart).
In the modern HTML standard there's a [section about Drag Events](https://html.spec.whatwg.org/multipage/interaction.html#dnd).
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.
They are interesting because they allow to solve simple tasks easily, and also allow to handle 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. Then JavaScript gains access to its contents.
@ -94,7 +94,7 @@ So we should listen on `document` to catch it.
## Correct positioning
In the examples above the ball is always centered 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';
@ -119,8 +119,6 @@ For instance, if we start dragging by the edge of the ball, then the cursor shou
let shiftY = event.clientY - ball.getBoundingClientRect().top;
```
Please note that there's no method to get document-relative coordinates in JavaScript, so we use window-relative coordinates here.
2. Then while dragging we position the ball on the same shift relative to the pointer, like this:
```js
@ -146,7 +144,8 @@ ball.onmousedown = function(event) {
moveAt(event.pageX, event.pageY);
// centers the ball at (pageX, pageY) coordinates
// moves the ball at (pageX, pageY) coordinates
// taking initial shifts into account
function moveAt(pageX, pageY) {
ball.style.left = pageX - *!*shiftX*/!* + 'px';
ball.style.top = pageY - *!*shiftY*/!* + 'px';
@ -180,17 +179,17 @@ In action (inside `<iframe>`):
The difference is especially noticeable if we drag the ball by its right-bottom corner. In the previous example the ball "jumps" under the pointer. Now it fluently follows the cursor from the current position.
## Detecting droppables
## Potential drop targets (droppables)
In previous examples the ball could be dropped just "anywhere" to stay. In real-life we usually take one element and drop it onto another. For instance, a file into a folder, or a user into a trash can or whatever.
In other words, we take a "draggable" element and drop it onto "droppable" element.
We need to know the target droppable at the end of Drag'n'Drop -- to do the corresponding action, and, preferably, during the dragging process, to highlight it.
We need to know where the element was dropped at the end of Drag'n'Drop -- to do the corresponding action, and, preferably, know the droppable we're dragging over, to highlight it.
The solution is kind-of interesting and just a little bit tricky, so let's cover it here.
What's the first idea? Probably to put `onmouseover/mouseup` handlers on potential droppables and detect when the mouse pointer appears over them. And then we know that we are dragging/dropping on that element.
What may be the first idea? Probably to set `mouseover/mouseup` handlers on potential droppables and detect when the mouse pointer appears over them. And then we know that we are dragging over/dropping on that element.
But that doesn't work.
@ -217,7 +216,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 coordinates are out of the window).
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).
So in any of our mouse event handlers we can detect the potential droppable under the pointer like this:
@ -226,12 +225,12 @@ So in any of our mouse event handlers we can detect the potential droppable unde
ball.hidden = true; // (*)
let elemBelow = document.elementFromPoint(event.clientX, event.clientY);
ball.hidden = false;
// elemBelow is the element below the ball. If it's droppable, we can handle it.
// elemBelow is the element below the ball, may be droppable
```
Please note: we need to hide the ball before the call `(*)`. Otherwise we'll usually have a ball on these coordinates, as it's the top element under the pointer: `elemBelow=ball`.
We can use that code to check what we're "flying over" at any time. And handle the drop when it happens.
We can use that code to check what element we're "flying over" at any time. And handle the drop when it happens.
An extended code of `onMouseMove` to find "droppable" elements:

View file

@ -39,7 +39,7 @@ We leave it as an exercise for the reader. Also, at the end of the chapter you'l
## Writing to document.cookie
We can write to `document.cookie`. But it's not a data property, it's an accessor.
We can write to `document.cookie`. But it's not a data property, it's an accessor. An assignment to it is treated specially.
**A write operation to `document.cookie` passes through the browser that updates cookies mentioned in it, but doesn't touch other cookies.**
@ -84,11 +84,11 @@ document.cookie = "user=John; path=/; expires=Tue, 19 Jan 2038 03:14:07 GMT"
- **`path=/mypath`**
The url path prefix, where the cookie is accessible. Must be absolute. By default, it's the current path.
The url path prefix, the cookie will be accessible for pages under that path. Must be absolute. By default, it's the current path.
If a cookie is set with `path=/admin`, it's visible at pages `/admin` and `/admin/something`, but not at `/home` or `/adminpage`.
Usually, we set `path=/` to make the cookie accessible from all website pages.
Usually, we should set `path` to the root: `path=/` to make the cookie accessible from all website pages.
## domain
@ -110,19 +110,22 @@ alert(document.cookie); // no user
**There's no way to let a cookie be accessible from another 2nd-level domain, so `other.com` will never receive a cookie set at `site.com`.**
It's a safety restriction, to allow us to store sensitive data in cookies.
It's a safety restriction, to allow us to store sensitive data in cookies, that should be available only on one site.
...But if we'd like to grant access to subdomains like `forum.site.com`, that's possible. We should explicitly set `domain` option to the root domain: `domain=site.com`:
...But if we'd like to allow subdomains like `forum.site.com` get a cookie, that's possible. When setting a cookie at `site.com`, we should explicitly set `domain` option to the root domain: `domain=site.com`:
```js
// at site.com, make the cookie accessible on any subdomain:
// at site.com
// make the cookie accessible on any subdomain *.site.com:
document.cookie = "user=John; domain=site.com"
// later
// at forum.site.com
alert(document.cookie); // with user
alert(document.cookie); // has cookie user=John
```
For historical reasons, `domain=.site.com` (a dot at the start) also works this way, it might better to add the dot to support very old browsers.
For historical reasons, `domain=.site.com` (a dot before `site.com`) also works the same way, allowing access to the cookie from subdomains. That's an old notation, should be used if we need to support very old browsers.
So, `domain` option allows to make a cookie accessible at subdomains.