Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
51 commits
Select commit Hold shift + click to select a range
cb3380c
Update index.html
leviding Apr 17, 2022
95498b4
Update index.html
leviding Apr 17, 2022
bb31eef
fix minor grammatical mistakes
TimothyRuszala Apr 17, 2022
0641648
Case sensitive word change
pavansuthar Apr 18, 2022
e424ad2
minor grammar fix
Rnbsov Apr 18, 2022
ee1daf7
Update article.md
Rnbsov Apr 18, 2022
888e4b9
Fix language in Methods of primitives task
Apr 19, 2022
1f81da0
Fix grammar in 'Symbol type'
Apr 19, 2022
d62faff
minor typos and English improvements
OmerBaddour Apr 20, 2022
adca4b3
minor fix, and explanation improvements
OmerBaddour Apr 21, 2022
68aa3ef
Update article.md
Rnbsov Apr 23, 2022
c3d92ec
add a comma
Rnbsov Apr 23, 2022
4aa9f81
replace side-effect with side effect
Rnbsov Apr 25, 2022
37057a7
Update article.md
Rnbsov Apr 26, 2022
f8d68ca
Update article.md
Rnbsov Apr 26, 2022
9bcd822
add a run button
Rnbsov Apr 29, 2022
cc9b015
add quotes
Rnbsov Apr 30, 2022
2cccadc
add highliting
Rnbsov Apr 30, 2022
b4379c5
Fixed grammatical error.
MondoBurrito May 1, 2022
c5c1d61
update localStorage size limit
Kirshach May 1, 2022
a1cd7b7
add missing break line
Rnbsov May 1, 2022
8eed0d7
Merge pull request #2964 from OmerBaddour/patch-1
iliakan May 3, 2022
bf83b15
remove one extra break line
Rnbsov May 3, 2022
5ef143d
closes #2982
iliakan May 3, 2022
9fcd38f
Merge pull request #2981 from Rnbsov/patch-34
iliakan May 3, 2022
6ce9e71
Merge pull request #2979 from Kirshach/patch-1
iliakan May 3, 2022
8149cb0
just add a comma
Rnbsov May 3, 2022
f65c25d
Merge pull request #2978 from MondoBurrito/patch-3
iliakan May 3, 2022
da3890a
Merge pull request #2977 from Rnbsov/patch-33
iliakan May 3, 2022
9119eca
Merge pull request #2976 from Rnbsov/patch-31
iliakan May 3, 2022
9c5a077
Merge pull request #2975 from Rnbsov/patch-30
iliakan May 3, 2022
ad6f23b
closes #2973
iliakan May 3, 2022
18a976b
Merge pull request #2972 from Rnbsov/patch-29
iliakan May 3, 2022
64d0c11
Merge pull request #2969 from Rnbsov/patch-28
iliakan May 3, 2022
ba44374
Merge pull request #2968 from Rnbsov/patch-27
iliakan May 3, 2022
87b5780
Merge pull request #2971 from Rnbsov/side-effect
iliakan May 3, 2022
0e47678
typo
Rnbsov May 3, 2022
1dc862c
Merge pull request #2966 from OmerBaddour/patch-2
iliakan May 3, 2022
12024bc
minor fixes
iliakan May 3, 2022
e9dfecc
Merge pull request #2986 from Rnbsov/patch-37
iliakan May 3, 2022
254f82f
Merge pull request #2985 from Rnbsov/patch-36
iliakan May 3, 2022
7af623e
Merge pull request #2984 from Rnbsov/patch-35
iliakan May 3, 2022
5015a76
Merge pull request #2963 from Luca1152/patch-2
iliakan May 3, 2022
e27d5ca
Merge pull request #2962 from Luca1152/patch-1
iliakan May 3, 2022
b60f9fc
Merge pull request #2960 from Rnbsov/patch-26
iliakan May 3, 2022
54c3fb9
Merge pull request #2959 from Rnbsov/patch-25
iliakan May 3, 2022
a3a1492
Merge pull request #2958 from pavansuthar/pavan-patch-01
iliakan May 3, 2022
c01efda
minor fixes
iliakan May 3, 2022
e74245e
Merge pull request #2957 from TimothyRuszala/patch-1
iliakan May 3, 2022
206485f
Merge pull request #2956 from leviding/patch-43
iliakan May 3, 2022
b3ff007
merging all conflicts
iliakan May 9, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions 1-js/02-first-steps/04-variables/article.md
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,11 @@ let my-name; // παύλες '-' απαγορεύονται
```

```smart header="Case matters"
<<<<<<< HEAD
Μεταβλητές `apple` και `AppLE` είναι δύο διαφορετικές μεταβλητές.
=======
Variables named `apple` and `APPLE` are two different variables.
>>>>>>> 206485fc3a5465f961608b6e7303fae2e1a0e0b5
```

````smart header="Non-Latin letters are allowed, but not recommended"
Expand Down Expand Up @@ -298,7 +302,11 @@ const pageLoadTime = /* ο χρόνος που χρειάζεται για να

Η τιμή του "pageLoadTime" δεν είναι γνωστή πριν από τη φόρτωση της σελίδας, επομένως έχει κανονική ονομασία. Αλλά εξακολουθεί να είναι σταθερή επειδή δεν αλλάζει μετά την ανάθεση.

<<<<<<< HEAD
Με άλλα λόγια, οι σταθερές με κεφαλαία ονομασία χρησιμοποιούνται μόνο ως ψευδώνυμα για "hard-coded" τιμές.
=======
In other words, capital-named constants are only used as aliases for "hard-coded" values.
>>>>>>> 206485fc3a5465f961608b6e7303fae2e1a0e0b5

## Να λεμε τα πράγματα με το ονομά τους

Expand Down
4 changes: 4 additions & 0 deletions 1-js/02-first-steps/13-while-for/article.md
Original file line number Diff line number Diff line change
Expand Up @@ -263,7 +263,11 @@ for (let i = 0; i < 10; i++) {

Από τεχνική άποψη, αυτό είναι πανομοιότυπο με το παραπάνω παράδειγμα. Σίγουρα, μπορούμε απλώς να τυλίξουμε τον κώδικα σε ένα μπλοκ `if` αντί να χρησιμοποιήσουμε το `continue`.

<<<<<<< HEAD
Αλλά ως παρενέργεια, αυτό δημιούργησε ένα ακόμη επίπεδο ένθεσης (η κλήση `alert` μέσα στα άγκυστρα). Εάν ο κώδικας στο εσωτερικό του `if` είναι μεγαλύτερος από μερικές γραμμές, αυτό μπορεί να μειώσει τη συνολική αναγνωσιμότητα.
=======
But as a side effect, this created one more level of nesting (the `alert` call inside the curly braces). If the code inside of `if` is longer than a few lines, that may decrease the overall readability.
>>>>>>> 206485fc3a5465f961608b6e7303fae2e1a0e0b5
````

````warn header="Δεν υπάρχει `break/continue` στη δεξιά πλευρά του '?'"
Expand Down
4 changes: 4 additions & 0 deletions 1-js/02-first-steps/14-switch/article.md
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,11 @@ switch (a) {

Τώρα και τα δύο `3` και `5` εμφανίζουν το ίδιο μήνυμα.

<<<<<<< HEAD
Η ικανότητα "ομαδοποίησης" περιπτώσεων είναι μια παρενέργεια του τρόπου λειτουργίας του `switch/case` χωρίς το `break`. Εδώ η εκτέλεση του `case 3` ξεκινά από τη γραμμή `(*)` και περνάει από το `case 5`, επειδή δεν υπάρχει `break`.
=======
The ability to "group" cases is a side effect of how `switch/case` works without `break`. Here the execution of `case 3` starts from the line `(*)` and goes through `case 5`, because there's no `break`.
>>>>>>> 206485fc3a5465f961608b6e7303fae2e1a0e0b5

## Η σημασία του τύπου

Expand Down
4 changes: 4 additions & 0 deletions 1-js/02-first-steps/15-function-basics/article.md
Original file line number Diff line number Diff line change
Expand Up @@ -470,7 +470,11 @@ function name(parameters, delimited, by, comma) {

Για να κάνετε τον κώδικα καθαρό και κατανοητό, συνίσταται η χρήση κυρίως τοπικών μεταβλητών και παραμέτρων στη συνάρτηση, όχι εξωτερικών μεταβλητών.

<<<<<<< HEAD
Είναι πάντα πιο εύκολο να κατανοήσουμε μια συνάρτηση που παίρνει παραμέτρους, δουλεύει μαζί τους και επιστρέφει ένα αποτέλεσμα, παρά μια συνάρτηση που δεν έχει παραμέτρους, αλλά τροποποιεί τις εξωτερικές μεταβλητές ως side-effect.
=======
It is always easier to understand a function which gets parameters, works with them and returns a result than a function which gets no parameters, but modifies outer variables as a side effect.
>>>>>>> 206485fc3a5465f961608b6e7303fae2e1a0e0b5

Ονομασία συναρτήσεων:

Expand Down
8 changes: 4 additions & 4 deletions 1-js/02-first-steps/16-function-expressions/article.md
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ Everything would work the same.


````smart header="Why is there a semicolon at the end?"
You might wonder, why does Function Expression have a semicolon `;` at the end, but Function Declaration does not:
You might wonder, why do Function Expressions have a semicolon `;` at the end, but Function Declarations do not:

```js
function sayHi() {
Expand Down Expand Up @@ -144,13 +144,13 @@ function showCancel() {
ask("Do you agree?", showOk, showCancel);
```

In practice, such functions are quite useful. The major difference between a real-life `ask` and the example above is that real-life functions use more complex ways to interact with the user than a simple `confirm`. In the browser, such function usually draws a nice-looking question window. But that's another story.
In practice, such functions are quite useful. The major difference between a real-life `ask` and the example above is that real-life functions use more complex ways to interact with the user than a simple `confirm`. In the browser, such functions usually draw a nice-looking question window. But that's another story.

**The arguments `showOk` and `showCancel` of `ask` are called *callback functions* or just *callbacks*.**

The idea is that we pass a function and expect it to be "called back" later if necessary. In our case, `showOk` becomes the callback for "yes" answer, and `showCancel` for "no" answer.

We can use Function Expressions to write the same function much shorter:
We can use Function Expressions to write an equivalent, shorter function:

```js run no-beautify
function ask(question, yes, no) {
Expand Down Expand Up @@ -186,7 +186,7 @@ Let's formulate the key differences between Function Declarations and Expression

First, the syntax: how to differentiate between them in the code.

- *Function Declaration:* a function, declared as a separate statement, in the main code flow.
- *Function Declaration:* a function, declared as a separate statement, in the main code flow:

```js
// Function Declaration
Expand Down
2 changes: 1 addition & 1 deletion 1-js/03-code-quality/05-testing-mocha/article.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ describe("pow", function() {
A spec has three main building blocks that you can see above:

`describe("title", function() { ... })`
: What functionality we're describing. In our case we're describing the function `pow`. Used to group "workers" -- the `it` blocks.
: What functionality we're describing? In our case we're describing the function `pow`. Used to group "workers" -- the `it` blocks.

`it("use case description", function() { ... })`
: In the title of `it` we *in a human-readable way* describe the particular use case, and the second argument is a function that tests it.
Expand Down
20 changes: 8 additions & 12 deletions 1-js/04-object-basics/02-object-copy/article.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ And here's how it's actually stored in memory:

The object is stored somewhere in memory (at the right of the picture), while the `user` variable (at the left) has a "reference" to it.

We may think of an object variable, such as `user`, as like a sheet of paper with the address of the object on it.
We may think of an object variable, such as `user`, like a sheet of paper with the address of the object on it.

When we perform actions with the object, e.g. take a property `user.name`, the JavaScript engine looks at what's at that address and performs the operation on the actual object.

Expand Down Expand Up @@ -104,11 +104,9 @@ For comparisons like `obj1 > obj2` or for a comparison against a primitive `obj

So, copying an object variable creates one more reference to the same object.

But what if we need to duplicate an object? Create an independent copy, a clone?
But what if we need to duplicate an object?

That's also doable, but a little bit more difficult, because there's no built-in method for that in JavaScript. But there is rarely a need -- copying by reference is good most of the time.

But if we really want that, then we need to create a new object and replicate the structure of the existing one by iterating over its properties and copying them on the primitive level.
We can create a new object and replicate the structure of the existing one, by iterating over its properties and copying them on the primitive level.

Like this:

Expand All @@ -133,7 +131,7 @@ clone.name = "Pete"; // changed the data in it
alert( user.name ); // still John in the original object
```

Also we can use the method [Object.assign](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign) for that.
We can also use the method [Object.assign](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign).

The syntax is:

Expand Down Expand Up @@ -190,7 +188,7 @@ There are also other methods of cloning an object, e.g. using the [spread syntax

## Nested cloning

Until now we assumed that all properties of `user` are primitive. But properties can be references to other objects. What to do with them?
Until now we assumed that all properties of `user` are primitive. But properties can be references to other objects.

Like this:
```js run
Expand All @@ -205,9 +203,7 @@ let user = {
alert( user.sizes.height ); // 182
```

Now it's not enough to copy `clone.sizes = user.sizes`, because the `user.sizes` is an object, it will be copied by reference. So `clone` and `user` will share the same sizes:

Like this:
Now it's not enough to copy `clone.sizes = user.sizes`, because `user.sizes` is an object, and will be copied by reference, so `clone` and `user` will share the same sizes:

```js run
let user = {
Expand All @@ -224,10 +220,10 @@ alert( user.sizes === clone.sizes ); // true, same object

// user and clone share sizes
user.sizes.width++; // change a property from one place
alert(clone.sizes.width); // 51, see the result from the other one
alert(clone.sizes.width); // 51, get the result from the other one
```

To fix that, we should use a cloning loop that examines each value of `user[key]` and, if it's an object, then replicate its structure as well. That is called a "deep cloning".
To fix that and make `user` and `clone` truly separate objects, we should use a cloning loop that examines each value of `user[key]` and, if it's an object, then replicate its structure as well. That is called a "deep cloning".

We can use recursion to implement it. Or, to not reinvent the wheel, take an existing implementation, for instance [_.cloneDeep(obj)](https://lodash.com/docs#cloneDeep) from the JavaScript library [lodash](https://lodash.com).

Expand Down
2 changes: 1 addition & 1 deletion 1-js/04-object-basics/08-symbol/article.md
Original file line number Diff line number Diff line change
Expand Up @@ -238,7 +238,7 @@ alert( Symbol.keyFor(sym2) ); // id

The `Symbol.keyFor` internally uses the global symbol registry to look up the key for the symbol. So it doesn't work for non-global symbols. If the symbol is not global, it won't be able to find it and returns `undefined`.

That said, any symbols have `description` property.
That said, all symbols have the `description` property.

For instance:

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,4 @@ str.test = 5;
alert(str.test);
```

How do you think, will it work? What will be shown?
What do you think, will it work? What will be shown?
4 changes: 2 additions & 2 deletions 1-js/05-data-types/02-number/article.md
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,7 @@ There are two ways to do so:
alert( num.toFixed(1) ); // "12.4"
```

Please note that result of `toFixed` is a string. If the decimal part is shorter than required, zeroes are appended to the end:
Please note that the result of `toFixed` is a string. If the decimal part is shorter than required, zeroes are appended to the end:

```js run
let num = 12.34;
Expand Down Expand Up @@ -246,7 +246,7 @@ Can we work around the problem? Sure, the most reliable method is to round the r

```js run
let sum = 0.1 + 0.2;
alert( sum.toFixed(2) ); // 0.30
alert( sum.toFixed(2) ); // "0.30"
```

Please note that `toFixed` always returns a string. It ensures that it has 2 digits after the decimal point. That's actually convenient if we have an e-shopping and need to show `$0.30`. For other cases, we can use the unary plus to coerce it into a number:
Expand Down
10 changes: 5 additions & 5 deletions 1-js/05-data-types/03-string/article.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ let guestList = "Guests: // Error: Unexpected token ILLEGAL
* John";
```

Single and double quotes come from ancient times of language creation when the need for multiline strings was not taken into account. Backticks appeared much later and thus are more versatile.
Single and double quotes come from ancient times of language creation, when the need for multiline strings was not taken into account. Backticks appeared much later and thus are more versatile.

Backticks also allow us to specify a "template function" before the first backtick. The syntax is: <code>func&#96;string&#96;</code>. The function `func` is called automatically, receives the string and embedded expressions and can process them. This is called "tagged templates". This feature makes it easier to implement custom templating, but is rarely used in practice. You can read more about it in the [manual](mdn:/JavaScript/Reference/Template_literals#Tagged_templates).

Expand Down Expand Up @@ -214,7 +214,7 @@ alert( 'Interface'.toLowerCase() ); // interface

Or, if we want a single character lowercased:

```js
```js run
alert( 'Interface'[0].toLowerCase() ); // 'i'
```

Expand Down Expand Up @@ -371,8 +371,8 @@ alert( "Widget".includes("id", 3) ); // false, from position 3 there is no "id"
The methods [str.startsWith](mdn:js/String/startsWith) and [str.endsWith](mdn:js/String/endsWith) do exactly what they say:

```js run
alert( "Widget".startsWith("Wid") ); // true, "Widget" starts with "Wid"
alert( "Widget".endsWith("get") ); // true, "Widget" ends with "get"
alert( "*!*Wid*/!*get".startsWith("Wid") ); // true, "Widget" starts with "Wid"
alert( "Wid*!*get*/!*".endsWith("get") ); // true, "Widget" ends with "get"
```

## Getting a substring
Expand Down Expand Up @@ -604,7 +604,7 @@ You will find more ways to deal with surrogate pairs later in the chapter <info:

### Diacritical marks and normalization

In many languages there are symbols that are composed of the base character with a mark above/under it.
In many languages, there are symbols that are composed of the base character with a mark above/under it.

For instance, the letter `a` can be the base character for: `àáâäãåā`. Most common "composite" character have their own code in the UTF-16 table. But not all of them, because there are too many possible combinations.

Expand Down
2 changes: 1 addition & 1 deletion 1-js/06-advanced-functions/06-function-object/article.md
Original file line number Diff line number Diff line change
Expand Up @@ -326,7 +326,7 @@ welcome(); // Hello, Guest (nested call works)

Now it works, because the name `"func"` is function-local. It is not taken from outside (and not visible there). The specification guarantees that it will always reference the current function.

The outer code still has its variable `sayHi` or `welcome`. And `func` is an "internal function name", how the function can call itself internally.
The outer code still has its variable `sayHi` or `welcome`. And `func` is an "internal function name", the way for the function to can call itself reliably.

```smart header="There's no such thing for Function Declaration"
The "internal name" feature described here is only available for Function Expressions, not for Function Declarations. For Function Declarations, there is no syntax for adding an "internal" name.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -232,7 +232,7 @@ setTimeout(function() {...}, 100);

For `setInterval` the function stays in memory until `clearInterval` is called.

There's a side-effect. A function references the outer lexical environment, so, while it lives, outer variables live too. They may take much more memory than the function itself. So when we don't need the scheduled function anymore, it's better to cancel it, even if it's very small.
There's a side effect. A function references the outer lexical environment, so, while it lives, outer variables live too. They may take much more memory than the function itself. So when we don't need the scheduled function anymore, it's better to cancel it, even if it's very small.
````

## Zero delay setTimeout
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,4 @@ alert(dictionary); // "apple,__proto__"

When we create a property using a descriptor, its flags are `false` by default. So in the code above, `dictionary.toString` is non-enumerable.

See the the chapter [](info:property-descriptors) for review.
See the chapter [](info:property-descriptors) for review.
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,14 @@ alert( rabbit.hasOwnProperty('name') ); // true

But that's not all yet.

Even after the fix, there's still important difference in `"class Rabbit extends Object"` versus `class Rabbit`.
Even after the fix, there's still an important difference between `"class Rabbit extends Object"` and `class Rabbit`.

As we know, the "extends" syntax sets up two prototypes:

1. Between `"prototype"` of the constructor functions (for methods).
2. Between the constructor functions themselves (for static methods).

In our case, for `class Rabbit extends Object` it means:
In the case of `class Rabbit extends Object` it means:

```js run
class Rabbit extends Object {}
Expand All @@ -37,7 +37,7 @@ alert( Rabbit.prototype.__proto__ === Object.prototype ); // (1) true
alert( Rabbit.__proto__ === Object ); // (2) true
```

So `Rabbit` now provides access to static methods of `Object` via `Rabbit`, like this:
So `Rabbit` now provides access to the static methods of `Object` via `Rabbit`, like this:

```js run
class Rabbit extends Object {}
Expand Down Expand Up @@ -67,7 +67,7 @@ alert ( Rabbit.getOwnPropertyNames({a: 1, b: 2})); // Error

So `Rabbit` doesn't provide access to static methods of `Object` in that case.

By the way, `Function.prototype` has "generic" function methods, like `call`, `bind` etc. They are ultimately available in both cases, because for the built-in `Object` constructor, `Object.__proto__ === Function.prototype`.
By the way, `Function.prototype` also has "generic" function methods, like `call`, `bind` etc. They are ultimately available in both cases, because for the built-in `Object` constructor, `Object.__proto__ === Function.prototype`.

Here's the picture:

Expand Down
11 changes: 11 additions & 0 deletions 1-js/09-classes/03-static-properties-methods/article.md
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,17 @@ Static methods are also used in database-related classes to search/save/remove e
Article.remove({id: 12345});
```

````warn header="Static methods aren't available for individual objects"
Static methods are callable on classes, not on individual objects.

E.g. such code won't work:

```js
// ...
article.createTodays(); /// Error: article.createTodays is not a function
```
````

## Static properties

[recent browser=Chrome]
Expand Down
2 changes: 1 addition & 1 deletion 1-js/13-modules/01-modules-intro/article.md
Original file line number Diff line number Diff line change
Expand Up @@ -272,7 +272,7 @@ In other words:
- module scripts wait until the HTML document is fully ready (even if they are tiny and load faster than HTML), and then run.
- relative order of scripts is maintained: scripts that go first in the document, execute first.

As a side-effect, module scripts always "see" the fully loaded HTML-page, including HTML elements below them.
As a side effect, module scripts always "see" the fully loaded HTML-page, including HTML elements below them.

For instance:

Expand Down
2 changes: 1 addition & 1 deletion 2-ui/1-document/07-modifying-document/5-why-aaa/task.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,6 @@ Why does that happen?
alert(table); // the table, as it should be

table.remove();
// why there's still aaa in the document?
// why there's still "aaa" in the document?
</script>
```
4 changes: 2 additions & 2 deletions 2-ui/3-event-details/1-mouse-events-basics/article.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ Click-related events always have the `button` property, which allows to get the

We usually don't use it for `click` and `contextmenu` events, because the former happens only on left-click, and the latter -- only on right-click.

From the other hand, `mousedown` and `mouseup` handlers may need `event.button`, because these events trigger on any button, so `button` allows to distinguish between "right-mousedown" and "left-mousedown".
On the other hand, `mousedown` and `mouseup` handlers may need `event.button`, because these events trigger on any button, so `button` allows to distinguish between "right-mousedown" and "left-mousedown".

The possible values of `event.button` are:

Expand Down Expand Up @@ -154,7 +154,7 @@ Move the mouse over the input field to see `clientX/clientY` (the example is in

## Preventing selection on mousedown

Double mouse click has a side-effect that may be disturbing in some interfaces: it selects text.
Double mouse click has a side effect that may be disturbing in some interfaces: it selects text.

For instance, double-clicking on the text below selects it in addition to our handler:

Expand Down
Loading