Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Mouse events basics #46

Merged
Changes from all commits
Commits
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
196 changes: 94 additions & 102 deletions 2-ui/3-event-details/1-mouse-events-basics/article.md
Original file line number Diff line number Diff line change
@@ -1,89 +1,87 @@
# Mouse events basics
# Evenements de base de la souris

Mouse events come not only from "mouse manipulators", but are also emulated on touch devices, to make them compatible.
Les évènements de souris ne proviennent pas uniquement des "manipulateurs de la souris", mais ils peuvent aussi être émulés sur des appareils tactiles, afin de les rendre compatibles.

In this chapter we'll get into more details about mouse events and their properties.
Dans ce chapitre nous verrons plus en détail les évènements clics et leurs propriétés.

## Mouse event types
## Les types d'évènements de Souris

We can split mouse events into two categories: "simple" and "complex"
Nous regroupons les évènements de types souris en deux catégories: "Simples" et "Complexes" .

### Simple events
### Les évènements simples

The most used simple events are:
Les évènements simples les plus utilisés sont:

`mousedown/mouseup`
: Mouse button is clicked/released over an element.
: Le bouton de la souris est appuyé et relâché sur un élément.

`mouseover/mouseout`
: Mouse pointer comes over/out from an element.
: Le pointeur de la souris traverse à l'intérieur ou hors d'un élément.

`mousemove`
: Every mouse move over an element triggers that event.
: Chaque déplacement de la souris sur un élément déclenche cet évènement.

...There are several other event types too, we'll cover them later.
...Il existe plusieurs autres types d'évènements aussi, nous allons les couvrir plus tard.

### Complex events
### Les évènements complexes

`click`
: Triggers after `mousedown` and then `mouseup` over the same element if the left mouse button was used.
: est déclenché après un évènement `mousedown` et suite à un `mouseup` un sur le même élément si le bouton gauche de la souris a été utilisé

`contextmenu`
: Triggers after `mousedown` if the right mouse button was used.
: est déclenché après un évènement `mousedown` si le bouton gauche de la souris a été utilisé.

`dblclick`
: Triggers after a double click over an element.
: est déclenché après un évènement double clique sur un élément.

Complex events are made of simple ones, so in theory we could live without them. But they exist, and that's good, because they are convenient.
Les évènements complexes sont faits à partir d’évènements simples, donc en théorie nous pourrions nous en passer. Mais ils existent et cela est une bonne chose parce qu’ils sont convenables.

### Events order
### L’ordre des évènements

An action may trigger multiple events.
Une action peut déclencher plusieurs évènements.

For instance, a click first triggers `mousedown`, when the button is pressed, then `mouseup` and `click` when it's released.
Par exemple, un clic déclenche d'abord un évènement `mousedown`, lorsqu'un bouton est appuyé, ensuite un évènement `mouseup` et un évènement `click` lorsqu’il est relâché.

In cases when a single action initiates multiple events, their order is fixed. That is, the handlers are called in the order `mousedown` -> `mouseup` -> `click`. Events are handled in the same sequence: `onmouseup` finishes before `onclick` runs.
Au cas où une action unique initialise plusieurs évènements, leur ordre est fixé. Cela veut dire, les gestionnaires d’évènements sont appelés selon l’ordre suivant `mousedown` -> `mouseup` -> `click`. Les évènements sont gérés selon la même séquence: `onmouseup` finit avant que `onclick` ne démarre.

```online
Click the button below and you'll see the events. Try double-click too.
Clique sur le bouton en bas et vous verrez les évènements. Essayez l’évènement double clic aussi. Dans TestStand en bas tous les évènements de la souris sont enregistrés, et si il y a plus d’une seconde de retard entre eux, ils sont alors séparés par une ligne horizontale.

On the teststand below all mouse events are logged, and if there are more than 1 second delay between them, then they are separated by a horizontal ruler.

Also we can see the `which` property that allows to detect the mouse button.
Nous pouvons voir la propriété `which` qui permet de détecter le bouton de la souris.

<input onmousedown="return logMouse(event)" onmouseup="return logMouse(event)" onclick="return logMouse(event)" oncontextmenu="return logMouse(event)" ondblclick="return logMouse(event)" value="Click me with the right or the left mouse button" type="button"> <input onclick="logClear('test')" value="Clear" type="button"> <form id="testform" name="testform"> <textarea style="font-size:12px;height:150px;width:360px;"></textarea></form>
```

## Getting the button: which
## Obtenir le bouton: which

Click-related events always have the `which` property, which allows to get the exact mouse button.
Les évènements relatifs à l’événement clic ont toujours la propriété `which`, qui permet d’obtenir le bouton exact de la souris .

It is not used for `click` and `contextmenu` events, because the former happens only on left-click, and the latter -- only on right-click.
Elle n’est pas utilisée pour les évènements `click` et `contextmenu`, parce que le premier se passe uniquement sur le clic gauche et le dernier – uniquement sur le clic droit.

But if we track `mousedown` and `mouseup`, then we need it, because these events trigger on any button, so `which` allows to distinguish between "right-mousedown" and "left-mousedown".
Mais si nous voulons suivre les évènements `mousedown` and `mouseup`, alors nous en avons besoin, parce que ces évènements se déclenchent sur n’importe quel bouton, donc `which`permet de distinguer entre "right-mousedown" et "left-mousedown".

There are the three possible values:
Voici les trois valeurs possibles:

- `event.which == 1` -- the left button
- `event.which == 2` - the middle button
- `event.which == 3` - the right button

The middle button is somewhat exotic right now and is very rarely used.
Le bouton du milieu est quelque peu exotique jusqu’à présent et est très rarement utilisé.

## Modifiers: shift, alt, ctrl and meta
## Les Touches de Modifications: shift, alt, ctrl and meta

All mouse events include the information about pressed modifier keys.
Tous les évènements de la souris contiennent des informations à propos des touches de modifications qui sont appuyées.

The properties are:
Les propriétés sont :

- `shiftKey`
- `altKey`
- `ctrlKey`
- `metaKey` (`key:Cmd` for Mac)

For instance, the button below only works on `key:Alt+Shift`+click:
Par exemple le bouton en bas fonctionne seulement avec `key:Alt+Shift`+click:

```html autorun height=60
```html autorun height=60
<button id="button">Alt+Shift+Click on me!</button>

<script>
Expand All @@ -96,63 +94,60 @@ For instance, the button below only works on `key:Alt+Shift`+click:
};
</script>
```
```warn header="Attention: Sur Mac c’est souvent `Cmd` au lieu de `Ctrl`"

```warn header="Attention: on Mac it's usually `Cmd` instead of `Ctrl`"
On Windows and Linux there are modifier keys `key:Alt`, `key:Shift` and `key:Ctrl`. On Mac there's one more: `key:Cmd`, it corresponds to the property `metaKey`.
Sur Windows et Lunix il y a les touches de Modification key:Alt`, `key:Shift` and `key:Ctrl`.Sur Mac il y a une de plus: `key:Cmd`, elle correspond à la propriété `metaKey`.

In most cases when Windows/Linux uses `key:Ctrl`, on Mac people use `key:Cmd`. So where a Windows user presses `key:Ctrl+Enter` or `key:Ctrl+A`, a Mac user would press `key:Cmd+Enter` or `key:Cmd+A`, and so on, most apps use `key:Cmd` instead of `key:Ctrl`.
Dans la plus part des cas lorsque Windows/Linux utilise `key:Ctrl`, les gens sur Mac utilisent `key:Cmd`. Donc là ou un utilisateur Windows appuie sur `key:Ctrl+Enter` ou `key:Ctrl+A`, un utilisateur Mac va appuyer sur `key:Cmd+Enter` oubien sur `key:Cmd+A`, ainsi de suite, la plupart des apps utilisent `key:Cmd` au lieu de `key:Ctrl`.

So if we want to support combinations like `key:Ctrl`+click, then for Mac it makes sense to use `key:Cmd`+click. That's more comfortable for Mac users.
Donc si nous voulons supporter les combinaisons comme `key:Ctrl`+click, alors sur Mac on est sensé utiliser `key:Cmd`+click. C’est plus confortable pour les usagers de Mac.

Even if we'd like to force Mac users to `key:Ctrl`+click -- that's kind of difficult. The problem is: a left-click with `key:Ctrl` is interpreted as a *right-click* on Mac, and it generates the `contextmenu` event, not `click` like Windows/Linux.
Même si nous voudrions forcer les usagers de Mac à utiliser to `key:Ctrl`+click -- cela semble être difficile. Le problème en est : qu’un clic-gauche avec `key:Ctrl` est interprète comme un *right-click* sur Mac, et cela génère l’évènement `contextmenu`, non pas un `click` comme sous Windows/Lunix.

So if we want users of all operational systems to feel comfortable, then together with `ctrlKey` we should use `metaKey`.
Donc si nous voulons que les usagers de tous les systèmes d’Exploitations soient confortables, alors avec `ctrlKey` nous devons utiliser `metaKey`.

For JS-code it means that we should check `if (event.ctrlKey || event.metaKey)`.
Pour JS-code cela signifie que nous devons contrôler si `if (event.ctrlKey || event.metaKey)`.
```

```warn header="There are also mobile devices"
Keyboard combinations are good as an addition to the workflow. So that if the visitor has a
keyboard -- it works. And if your device doesn't have it -- then there's another way to do the same.
```warn header="Il y a aussi les appareils mobiles"

Les combinaisons du clavier sont tout aussi bonnes comme ajout au processus de travail. De sorte que si un visiteur a un clavier—cela fonctionne. Et si votre appareil n'en possède pas—qu’il possède un autre moyen d’effectuer la même chose.
```

## Coordinates: clientX/Y, pageX/Y
## Cordonnées: clientX/Y, pageX/Y

All mouse events have coordinates in two flavours:
Tous les évènements de souris ont des cordonnées en deux types :

1. Window-relative: `clientX` and `clientY`.
2. Document-relative: `pageX` and `pageY`.
1. Window-relative: `clientX` et `clientY`.
2. Document-relative: `pageX` et `pageY`.

For instance, if we have a window of the size 500x500, and the mouse is in the left-upper corner, then `clientX` and `clientY` are `0`. And if the mouse is in the center, then `clientX` and `clientY` are `250`, no matter what place in the document it is. They are similar to `position:fixed`.
Par exemple, si nous avons une fenêtre de taille 500x500, et la souris est au coin gauche en haut, alors `clientX` et `clientY` ont une valeur de `0`. Et si la souris est au centre, alors `clientX` et `clientY` ont une valeur de `250`, quel que soit la position dans le document il se trouve. Et ils ont une position similaire à`position:fixed`.

````online
Move the mouse over the input field to see `clientX/clientY` (it's in the `iframe`, so coordinates are relative to that `iframe`):
Glisse la souris à l’intérieur des champs de saisie texte pour voir les `clientX/clientY` (C’est dans l `iframe`, ainsi les cordonnées sont relatives à cet `iframe`):

```html autorun height=50
<input onmousemove="this.value=event.clientX+':'+event.clientY" value="Mouse over me">
```
````
Les cordonnées relatives au document sont comptés à partir du coin gauche en haut du document, et non pas par rapport à la fenêtre.
Les coordonnées `pageX`, `pageY` sont similaires à `position:absolute` au niveau document.
Vous pouvez lire plus à propos des cordonnées dans le chapitre <info:coordinates>.

Document-relative coordinates are counted from the left-upper corner of the document, not the window.
Coordinates `pageX`, `pageY` are similar to `position:absolute` on the document level.

You can read more about coordinates in the chapter <info:coordinates>.
## Aucune sélection au clic mousedown

## No selection on mousedown
Les clics de souris ont un effet secondaire qui peut être perturbant. Le double clic sélectionne le texte.

Mouse clicks have a side-effect that may be disturbing. A double click selects the text.

If we want to handle click events ourselves, then the "extra" selection doesn't look good.

For instance, a double-click on the text below selects it in addition to our handler:
Si nous voulons gérer les évènements clic, alors la sélection en "extra" ne rend pas bien.
Par exemple, un double-clic sur le texte en bas le sélectionne en ajout à notre gestionnaire d’évènement :

```html autorun height=50
<b ondblclick="alert('dblclick')">Double-click me</b>
```

There's a CSS way to stop the selection: the `user-select` property from [CSS UI Draft](https://www.w3.org/TR/css-ui-4/).
Il existe un moyen par css de stopper la sélection : la propriété `user-select` voir [CSS UI Draft](https://www.w3.org/TR/css-ui-4/).

Most browsers support it with prefixes:
Plusieurs navigateurs le supportent avec les préfixes :

```html autorun height=50
<style>
Expand All @@ -164,80 +159,77 @@ Most browsers support it with prefixes:
}
</style>

Before...
Avant...
<b ondblclick="alert('Test')">
Unselectable
Non sélectionnable
</b>
...After
...Apres
```

Now if you double-click on "Unselectable", it doesn't get selected. Seems to work.
Maintenant si vous effectuez un double-clic sur "Non sélectionnable", le texte n’est pas sélectionné. Ça semble marcher.

...But there is a potential problem! The text became truly unselectable. Even if a user starts the selection from "Before" and ends with "After", the selection skips "Unselectable" part. Do we really want to make our text unselectable?
But il y a un problème potentiel ! Le texte devient en réalité non sélectionnable. Même si un utilisateur commence la sélection à partir d’"Avant" et se termine par "Apres", la sélection saute la partie "Non sélectionnable". Voulons-nous vraiment rendre notre texte non sélectionnable ?

Most of time, we don't. A user may have valid reasons to select the text, for copying or other needs. That may be inconvenient if we don't allow them to do it. So this solution is not that good.
La plus part du temps, ce n’est pas ce que nous voulons. Un utilisateur peut avoir des raisons valides de sélectionner le texte, pour la copie ou d’autres besoins. Cela pourrait être inconvenable si nous ne leur permettrons pas de le faire. Donc cette solution n’est pas aussi bonne.

What we want is to prevent the selection on double-click, that's it.
Ce que nous voulons c’est d’empêcher la sélection au double-click, uniquement.

A text selection is the default browser action on `mousedown` event. So the alternative solution would be to handle `mousedown` and prevent it, like this:
La sélection du texte est l’action par défaut du navigateur de l’évènement `mousedown`. Donc une solution alternative serait de gérer le `mousedown` et de l’empêcher, comme ainsi :

```html autorun height=50
Before...
Avant...
<b ondblclick="alert('Click!')" *!*onmousedown="return false"*/!*>
Double-click me
Double-click sur moi
</b>
...After
...Apres
```

Now the bold element is not selected on double clicks.

The text inside it is still selectable. However, the selection should start not on the text itself, but before or after it. Usually that's fine though.
Maintenant l’élément en gras n’est pas sélectionné aux doubles clics.
Le texte à l’intérieur est encore sélectionnable. Cependant, la sélection ne doit pas commencer sur le texte lui-même, mais avant ou après celui-ci. Souvent, c’est suffisant cependant.

````smart header="Canceling the selection"
Instead of *preventing* the selection, we can cancel it "post-factum" in the event handler.

Here's how:
Au lieu d’*empêcher* la sélection, nous pouvons l’annuler a posteriori dans le gestionnaire de l’évènement
Voici comment procéder:

```html autorun height=50
Before...
Avant...
<b ondblclick="*!*getSelection().removeAllRanges()*/!*">
Double-click me
Double-click sur moi
</b>
...After
...Après
```

If you double-click on the bold element, then the selection appears and then is immediately removed. That doesn't look nice though.
Si vous faites un double-click sur l’élément en gras, alors la sélection apparait et ensuite elle est immédiatement enlevée. Cela n’est pas joli cependant.

````

````smart header="Preventing copying"
If we want to disable selection to protect our content from copy-pasting, then we can use another event: `oncopy`.

Si nous voulons désactiver la sélection pour protéger notre contenu du copier-coller, alors nous pouvons utiliser un autre évènement : `oncopy`.
```html autorun height=80 no-beautify
<div *!*oncopy="alert('Copying forbidden!');return false"*/!*>
Dear user,
The copying is forbidden for you.
If you know JS or HTML, then you can get everything from the page source though.

Cher Utilisateur
Il vous est interdit de faire du copier-coller.
Si vous connaissez JS ou HTML, alors vous pouvez tout obtenir à partir de la page source néanmoins.
</div>
```
If you try to copy a piece of text in the `<div>`, that won't work, because the default action `oncopy` is prevented.
Si vous essayer de copier une partie de texte dans un `<div>`, cela ne va pas fonctionner, parce que l’action par défaut `oncopy` est empêchée.

Surely that can't stop the user from opening HTML-source, but not everyone knows how to do it.
Surement cela ne peut empêcher l’utilisateur d’ouvrir le code source HTML, mais tout le monde ne sait pas comment le faire.
````

## Summary
## Résumé

Mouse events have the following properties:
Les évènements de souris ont les propriétés suivantes :

- Button: `which`.
- Modifier keys (`true` if pressed): `altKey`, `ctrlKey`, `shiftKey` and `metaKey` (Mac).
- If you want to handle `key:Ctrl`, then don't forget Mac users, they use `key:Cmd`, so it's better to check `if (e.metaKey || e.ctrlKey)`.

- Modifier keys (`true` if pressed): `altKey`, `ctrlKey`, `shiftKey` et `metaKey` (Mac).
- Si vous voulez gérer `key:Ctrl`, alors n’oubliez pas les utilisateurs Mac qui utilisent `key:Cmd`, alors il est mieux de contrôler si `if (e.metaKey || e.ctrlKey)`.
- Window-relative coordinates: `clientX/clientY`.
- Document-relative coordinates: `pageX/pageY`.

It's also important to deal with text selection as an unwanted side-effect of clicks.

There are several ways to do this, for instance:
1. The CSS-property `user-select:none` (with browser prefixes) completely disables text-selection.
2. Cancel the selection post-factum using `getSelection().removeAllRanges()`.
3. Handle `mousedown` and prevent the default action (usually the best).
Il est important de traiter la sélection de texte comme étant un effet secondaire non volontaire des clics
Il y a plusieurs moyens de faire cela, par exemple :
1. La propriété css `user-select:none` (avec les prefixes navigateur) désactive complètement la sélection de texte.
2. Annule la sélection post-factum en utilisant `getSelection().removeAllRanges()`.
3. Gere l’évènement `mousedown` et empêche l’action par default (souvent la meilleur option).