Skip to content

Commit 0db83b2

Browse files
authored
Merge branch 'master' into patch-1
2 parents 7ffb6ce + 59acd01 commit 0db83b2

File tree

19 files changed

+82
-53
lines changed

19 files changed

+82
-53
lines changed

1-js/02-first-steps/04-variables/2-declare-variables/solution.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ That's simple:
66
let ourPlanetName = "Earth";
77
```
88

9-
Note, we could use a shorter name `planet`, but it might be not obvious what planet it refers to. It's nice to be more verbose. At least until the variable isNotTooLong.
9+
Note, we could use a shorter name `planet`, but it might not be obvious what planet it refers to. It's nice to be more verbose. At least until the variable isNotTooLong.
1010

1111
## The name of the current visitor
1212

1-js/05-data-types/04-array/10-maximal-subarray/solution.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ alert( getMaxSubSum([1, 2, 3]) ); // 6
5757
alert( getMaxSubSum([100, -9, 2, -3, 5]) ); // 100
5858
```
5959

60-
The solution has a time complexety of [O(n<sup>2</sup>)](https://en.wikipedia.org/wiki/Big_O_notation). In other words, if we increase the array size 2 times, the algorithm will work 4 times longer.
60+
The solution has a time complexity of [O(n<sup>2</sup>)](https://en.wikipedia.org/wiki/Big_O_notation). In other words, if we increase the array size 2 times, the algorithm will work 4 times longer.
6161

6262
For big arrays (1000, 10000 or more items) such algorithms can lead to a serious sluggishness.
6363

1-js/05-data-types/04-array/article.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -209,7 +209,7 @@ arr.push("Pear"); // modify the array by reference
209209
alert( fruits ); // Banana, Pear - 2 items now
210210
```
211211

212-
...But what makes arrays really special is their internal representation. The engine tries to store its elements in the contiguous memory area, one after another, just as depicted on the illustrations in this chapter, and there are other optimizations as well, to make arrays work really fast.
212+
...But what makes arrays really special is their internal representation. The engine tries to store its elements in the contiguous memory area, one after another, just as depicted on the illustrations in this chapter, and there are other optimizations as well, to make arrays work really fast.
213213

214214
But they all break if we quit working with an array as with an "ordered collection" and start working with it as if it were a regular object.
215215

1-js/05-data-types/08-weakmap-weakset/article.md

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -207,7 +207,7 @@ alert(cache.size); // 1 (Ouch! The object is still in cache, taking memory!)
207207

208208
For multiple calls of `process(obj)` with the same object, it only calculates the result the first time, and then just takes it from `cache`. The downside is that we need to clean `cache` when the object is not needed any more.
209209

210-
If we replace `Map` with `WeakMap`, then this problem disappears. The cached result will be removed from memory automatically after the object gets garbage collected .
210+
If we replace `Map` with `WeakMap`, then this problem disappears. The cached result will be removed from memory automatically after the object gets garbage collected.
211211

212212
```js run
213213
// 📁 cache.js
@@ -284,7 +284,8 @@ The most notable limitation of `WeakMap` and `WeakSet` is the absence of iterati
284284

285285
`WeakSet` is `Set`-like collection that stores only objects and removes them once they become inaccessible by other means.
286286

287-
It's main advantages are that they have weak reference to objects, so they can easily be removed by garbage collector.
288-
That comes at the cost of not having support for `clear`, `size`, `keys`, `values` ...
287+
Their main advantages are that they have weak reference to objects, so they can easily be removed by garbage colector.
288+
289+
That comes at the cost of not having support for `clear`, `size`, `keys`, `values`...
289290

290291
`WeakMap` and `WeakSet` are used as "secondary" data structures in addition to the "primary" object storage. Once the object is removed from the primary storage, if it is only found as the key of `WeakMap` or in a `WeakSet`, it will be cleaned up automatically.

1-js/11-async/05-promise-api/article.md

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -219,7 +219,7 @@ The first promise here was fastest, so it became the result. After the first set
219219
220220
## Promise.any
221221
222-
Similar to `Promise.race`, but waits only for the first fulfilled promise and gets its result. If all of the given promises are rejected, then the returned promise is rejected.
222+
Similar to `Promise.race`, but waits only for the first fulfilled promise and gets its result. If all of the given promises are rejected, then the returned promise is rejected with [`AggregateError`](mdn:js/AggregateError) - a special error object that stores all promise errors in its `errors` property.
223223
224224
The syntax is:
225225
@@ -239,6 +239,20 @@ Promise.any([
239239
240240
The first promise here was fastest, but it was rejected, so the second promise became the result. After the first fulfilled promise "wins the race", all further results are ignored.
241241
242+
Here's an example when all promises fail:
243+
244+
```js run
245+
Promise.any([
246+
new Promise((resolve, reject) => setTimeout(() => reject(new Error("Ouch!")), 1000)),
247+
new Promise((resolve, reject) => setTimeout(() => reject(new Error("Error!")), 2000))
248+
]).catch(error => {
249+
console.log(error.constructor.name); // AggregateError
250+
console.log(error.errors[0]); // Error: Ouch!
251+
console.log(error.errors[1]); // Error: Error
252+
});
253+
```
254+
255+
As you can see, error objects for failed promises are available in the `errors` property of the `AggregateError` object.
242256
243257
## Promise.resolve/reject
244258
@@ -302,7 +316,7 @@ There are 5 static methods of `Promise` class:
302316
- `status`: `"fulfilled"` or `"rejected"`
303317
- `value` (if fulfilled) or `reason` (if rejected).
304318
3. `Promise.race(promises)` -- waits for the first promise to settle, and its result/error becomes the outcome.
305-
4. `Promise.any(promises)` -- waits for the first promise to fulfill, and its result becomes the outcome. If all of the given promises rejects, it becomes the error of `Promise.any`.
319+
4. `Promise.any(promises)` -- waits for the first promise to fulfill, and its result becomes the outcome. If all of the given promises are rejected, [`AggregateError`](mdn:js/AggregateError) becomes the error of `Promise.any`.
306320
5. `Promise.resolve(value)` -- makes a resolved promise with the given value.
307321
6. `Promise.reject(error)` -- makes a rejected promise with the given error.
308322

1-js/99-js-misc/01-proxy/article.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -969,7 +969,7 @@ Initially, `revoke` is separate from `proxy`, so that we can pass `proxy` around
969969

970970
We can also bind `revoke` method to proxy by setting `proxy.revoke = revoke`.
971971

972-
Another option is to create a `WeakMap` that has `proxy` as the key the corresponding `revoke` as the value, that allows to easily find `revoke` for a proxy:
972+
Another option is to create a `WeakMap` that has `proxy` as the key and the corresponding `revoke` as the value, that allows to easily find `revoke` for a proxy:
973973

974974
```js run
975975
*!*

2-ui/1-document/07-modifying-document/10-clock-setinterval/solution.md

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,15 +39,19 @@ The clock-managing functions:
3939
```js
4040
let timerId;
4141

42-
function clockStart() { // run the clock
43-
timerId = setInterval(update, 1000);
42+
function clockStart() { // run the clock
43+
if (!timerId) { // only set a new interval if the clock is not running
44+
timerId = setInterval(update, 1000);
45+
}
4446
update(); // (*)
4547
}
4648

4749
function clockStop() {
4850
clearInterval(timerId);
49-
timerId = null;
51+
timerId = null; // (**)
5052
}
5153
```
5254

5355
Please note that the call to `update()` is not only scheduled in `clockStart()`, but immediately run in the line `(*)`. Otherwise the visitor would have to wait till the first execution of `setInterval`. And the clock would be empty till then.
56+
57+
Also it is important to set a new interval in `clockStart()` only when the clock is not running. Otherways clicking the start button several times would set multiple concurrent intervals. Even worse - we would only keep the `timerID` of the last interval, losing references to all others. Then we wouldn't be able to stop the clock ever again! Note that we need to clear the `timerID` when the clock is stopped in the line `(**)`, so that it can be started again by running `clockStart()`.

2-ui/1-document/07-modifying-document/10-clock-setinterval/solution.view/index.html

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,12 +43,17 @@
4343
}
4444

4545
function clockStart() {
46-
timerId = setInterval(update, 1000);
46+
// set a new interval only if the clock is stopped
47+
// otherwise we would rewrite the timerID reference to the running interval and wouldn't be able to stop the clock ever again
48+
if (!timerId) {
49+
timerId = setInterval(update, 1000);
50+
}
4751
update(); // <-- start right now, don't wait 1 second till the first setInterval works
4852
}
4953

5054
function clockStop() {
5155
clearInterval(timerId);
56+
timerId = null; // <-- clear timerID to indicate that the clock has been stopped, so that it is possible to start it again in clockStart()
5257
}
5358

5459
clockStart();

2-ui/99-ui-misc/02-selection-range/article.md

Lines changed: 29 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -8,33 +8,36 @@ libs:
88

99
In this chapter we'll cover selection in the document, as well as selection in form fields, such as `<input>`.
1010

11-
JavaScript can get the existing selection, select/deselect both as a whole or partially, remove the selected part from the document, wrap it into a tag, and so on.
11+
JavaScript can access an existing selection, select/deselect DOM nodes as a whole or partially, remove the selected content from the document, wrap it into a tag, and so on.
1212

13-
You can get ready to use recipes at the end, in "Summary" section. But you'll get much more if you read the whole chapter. The underlying `Range` and `Selection` objects are easy to grasp, and then you'll need no recipes to make them do what you want.
13+
You can find some recipes for common tasks at the end of the chapter, in "Summary" section. Maybe that covers your current needs, but you'll get much more if you read the whole text.
1414

15-
## Range
16-
17-
The basic concept of selection is [Range](https://dom.spec.whatwg.org/#ranges): basically, a pair of "boundary points": range start and range end.
15+
The underlying `Range` and `Selection` objects are easy to grasp, and then you'll need no recipes to make them do what you want.
1816

19-
Each point represented as a parent DOM node with the relative offset from its start. If the parent node is an element node, then the offset is a child number, for a text node it's the position in the text. Examples to follow.
17+
## Range
2018

21-
Let's select something.
19+
The basic concept of selection is [Range](https://dom.spec.whatwg.org/#ranges), that is essentially a pair of "boundary points": range start and range end.
2220

23-
First, we can create a range (the constructor has no parameters):
21+
A `Range` object is created without parameters:
2422

2523
```js
2624
let range = new Range();
2725
```
2826

2927
Then we can set the selection boundaries using `range.setStart(node, offset)` and `range.setEnd(node, offset)`.
3028

31-
For example, consider this fragment of HTML:
29+
The first argument `node` can be either a text node or an element node. The meaning of the second argument depends on that:
30+
31+
- If `node` is a text node, then `offset` must be the position in the text.
32+
- If `node` is an element node, then `offset` must be the child number.
33+
34+
For example, let's create a range in this fragment:
3235

33-
```html
36+
```html autorun
3437
<p id="p">Example: <i>italic</i> and <b>bold</b></p>
3538
```
3639

37-
Here's its DOM structure, note that here text nodes are important for us:
40+
Here's its DOM structure:
3841

3942
<div class="select-p-domtree"></div>
4043

@@ -72,10 +75,17 @@ let selectPDomtree = {
7275
drawHtmlTree(selectPDomtree, 'div.select-p-domtree', 690, 320);
7376
</script>
7477

75-
Let's select `"Example: <i>italic</i>"`. That's two first children of `<p>` (counting text nodes):
78+
Let's make a range for `"Example: <i>italic</i>"`.
79+
80+
As we can see, this phrase consists of exactly the first and the second children of `<p>`:
7681

7782
![](range-example-p-0-1.svg)
7883

84+
- The starting point has `<p>` as the parent `node`, and `0` as the offset.
85+
- The ending point also has `<p>` as the parent `node`, but `2` as the offset (it specifies the range up to, but not including `offset`).
86+
87+
Here's the demo, if you run it, you can see that the text gets selected:
88+
7989
```html run
8090
<p id="p">Example: <i>italic</i> and <b>bold</b></p>
8191

@@ -87,17 +97,14 @@ Let's select `"Example: <i>italic</i>"`. That's two first children of `<p>` (cou
8797
range.setEnd(p, 2);
8898
*/!*
8999
90-
// toString of a range returns its content as text (without tags)
91-
alert(range); // Example: italic
100+
// toString of a range returns its content as text, without tags
101+
console.log(range); // Example: italic
92102
93-
// apply this range for document selection (explained later)
103+
// let's apply this range for document selection (explained later)
94104
document.getSelection().addRange(range);
95105
</script>
96106
```
97107

98-
- `range.setStart(p, 0)` -- sets the start at the 0th child of `<p>` (that's the text node `"Example: "`).
99-
- `range.setEnd(p, 2)` -- spans the range up to (but not including) 2nd child of `<p>` (that's the text node `" and "`, but as the end is not included, so the last selected node is `<i>`).
100-
101108
Here's a more flexible test stand where you try more variants:
102109

103110
```html run autorun
@@ -121,7 +128,7 @@ From <input id="start" type="number" value=1> – To <input id="end" type="numbe
121128
</script>
122129
```
123130

124-
E.g. selecting from `1` to `4` gives range `<i>italic</i> and <b>bold</b>`.
131+
E.g. selecting in the same `<p>` from offset `1` to `4` gives range `<i>italic</i> and <b>bold</b>`:
125132

126133
![](range-example-p-1-3.svg)
127134

@@ -264,11 +271,9 @@ There also exist methods to compare ranges, but these are rarely used. When you
264271

265272
## Selection
266273

267-
`Range` is a generic object for managing selection ranges. We may create such objects, pass them around -- they do not visually select anything on their own.
268-
269-
The document selection is represented by `Selection` object, that can be obtained as `window.getSelection()` or `document.getSelection()`.
274+
`Range` is a generic object for managing selection ranges. We may create `Range` objects, pass them around -- they do not visually select anything on their own.
270275

271-
A selection may include zero or more ranges. At least, the [Selection API specification](https://www.w3.org/TR/selection-api/) says so. In practice though, only Firefox allows to select multiple ranges in the document by using `key:Ctrl+click` (`key:Cmd+click` for Mac).
276+
The document selection is represented by `Selection` object, that can be obtained as `window.getSelection()` or `document.getSelection()`. A selection may include zero or more ranges. At least, the [Selection API specification](https://www.w3.org/TR/selection-api/) says so. In practice though, only Firefox allows to select multiple ranges in the document by using `key:Ctrl+click` (`key:Cmd+click` for Mac).
272277

273278
Here's a screenshot of a selection with 3 ranges, made in Firefox:
274279

@@ -289,7 +294,7 @@ The main selection properties are:
289294
- `isCollapsed` -- `true` if selection selects nothing (empty range), or doesn't exist.
290295
- `rangeCount` -- count of ranges in the selection, maximum `1` in all browsers except Firefox.
291296

292-
````smart header="Selection end may be in the document before start"
297+
````smart header="Usually, the selection end `focusNode` is after its start `anchorNode`, but it's not always the case"
293298
There are many ways to select the content, depending on the user agent: mouse, hotkeys, taps on a mobile etc.
294299

295300
Some of them, such as a mouse, allow the same selection can be created in two directions: "left-to-right" and "right-to-left".

2-ui/99-ui-misc/02-selection-range/range-example-p-2-b-3-range.svg

Lines changed: 1 addition & 1 deletion
Loading

0 commit comments

Comments
 (0)